The navigation on this site had a problem that wasn’t obvious from the outside. Behind the “Blog” dropdown was a dynamic list, generated at build time by scanning the src/pages/ directory with Node’s fs.readdirSync. Every folder with an index.astro became a nav item. Every .astro file that wasn’t explicitly excluded became one too.

It worked. It also produced this dropdown: Diary · Experiments · Glossary · Learn · Notes · Search.

That list is a filesystem. Not a site structure.


1. Navigation should reflect information architecture, not file architecture

The fundamental error in the original nav was that it exposed the implementation detail (how pages are stored) rather than the mental model: how a reader thinks about the site.

A reader doesn’t think in directories. They think in purposes: where do I go to learn something? Where do I go to read something shorter and more personal? File organisation answers none of those questions. Explicit, intentionally named links do.

The new nav (Learn · Diary · Notes · About · Search) maps directly to the three content modes the site operates in. Each word describes the nature of what you’ll find, not a container.


2. Name what’s inside, not the container

“Blog” is a container word. It tells you the format (a weblog) but says nothing about the content or mode of reading. It could contain tutorials, opinion pieces, listicles, project write-ups, anything.

Compare:

  • “Blog” → could mean anything
  • “Learn” → structured, arc-based, reading to understand something
  • “Diary” → personal, observational, shorter
  • “Notes” → process writing, meta, about the making of the site

Each word in the new nav pre-qualifies the visit. A reader looking for structured colour theory goes to Learn without having to click in and look around first. That friction removal is the job of good naming.


3. Dropdowns are a last resort

A dropdown is justified when a category contains too many items to flatten: when collapsing them is the only way to keep the primary nav scannable.

For three to five content sections, a dropdown is pure overhead:

  • It hides options behind an interaction (hover or click)
  • It creates a two-step decision: first choose the category, then choose the item
  • On mobile it breaks down entirely, requiring tap-to-expand mechanics
  • It implies a hierarchy that may not exist. Diary, Learn, Notes aren’t subcategories of Blog; they’re peers

Flat navigation exposes everything at once. Scannable. One step.


4. Wayfinding and utility are different jobs

Navigation serves two distinct purposes that shouldn’t share the same location.

Wayfinding asks: where am I, and where can I go to explore? This lives in the header, always visible, always available.

Utility asks: how do I take a specific action? (Contact, legal pages, tools.) This lives in the footer, reachable when you’re looking for it, not competing for attention while you’re reading.

The old nav included Contact and Tools at the same level as About and Search. Contact is not a destination you navigate to mid-read; it’s a destination you seek out when you’ve already decided you want to get in touch. Footer placement serves that intent better.


5. Reduce the decision surface

Every navigation item is a micro-decision. The cost of each decision is small, but they compound.

Old nav: About · Blog ▾ (Diary · Experiments · Glossary · Learn · Notes · Search) · Tools · Contact · Search = ten or more targets competing for the same moment of attention.

New nav: Learn · Diary · Notes · About · Search = five. Each clearly distinct. No overlap, no ambiguity.

This isn’t minimalism for its own sake. It’s recognising that the purpose of navigation is to get the reader somewhere useful as quickly as possible, not to demonstrate the full scope of what the site contains.


6. Don’t automate what needs a decision

The fs.readdirSync approach was clever: zero maintenance, nav always in sync with the pages directory. But the cleverness was the problem.

Navigation structure is an editorial decision. It encodes what the site thinks is important, what it wants to surface, what reading paths it’s trying to create. Delegating that to the filesystem removes the decision entirely and replaces it with whatever file organisation happens to exist.

When I added a glossary/ directory, it appeared in the nav. When I built experiments/, it appeared. Neither of those belonged in the primary navigation. The automaton didn’t know that.

Explicit is better. A list of five links is easier to maintain than a dynamic scanner with an exclusion list, and it forces you to think about whether each item belongs.


The result is a navigation bar that takes about two seconds to read in full. That’s the benchmark.