I do this in two pages I have set up in Jekyll.
The first thing I do is creating an entry inside _config.yml with the information of all the pages:
# this goes inside _config.yml. Change as required
navigation:
- text: What we do
url: /en/what-we-do/
- text: Who we are
url: /en/who-we-are/
- text: Projects
url: /en/projects/
layout: project
- text: Blog
url: /en/blog/
layout: post
Then, on my main layout, I use that information to generate the navigation links. On each link, I compare the url of the link with the url of the current page. If they are equal, the page is active. Otherwise, they are not.
There's a couple special cases: all blog posts must highlight the "blog" link, and the front pages (English and Spanish) must not present the nav bar. For both cases, I rely on the fact that blog posts and front pages have specific layouts (notice that the "Blog" and "Project" links on the yaml have an extra parameter called "layout")
The navigation code is generated like this:
{% unless page.layout == 'front' %}
<ul class="navigation">
{% for link in site.navigation %}
{% assign current = nil %}
{% if page.url == link.url or page.layout == link.layout %}
{% assign current = 'current' %}
{% endif %}
<li class="{% if forloop.first %}first{% endif %} {{ current }} {% if forloop.last %}last{% endif %}">
<a class="{{ current }}" href="{{ link.url }}">{{ link.text }}</a>
</li>
{% endfor %}
</ul>
{% endunless %}
I still have to remember adding an entry to _config.yaml every time I add a new page, and then restart Jekyll, but it happens very infrequently now.
I think the navigation yaml could go inside an _include called "navigation" or something similar, but I haven't tried using yaml inside those so I don't know whether it will work. In my case, since I've got a multi-lingual site, it's easier to have everything inside config (missing translations are easier to spot)
I hope this helps.