Every section is its own route
2026-11-06 · 2 min read · Engineering
I replaced a single page of anchor links with six routes, and three bugs disappeared without being fixed.
The shape I started with
The site used to be one long page. Hero, services, projects, about, skills, contact, stacked in a column, with a nav that scrolled you to an anchor. It is the default shape for a portfolio and I had never questioned it.
Three things that pushed me off it
The nav active state was a lie. It only updated when you clicked a link, so scrolling past a section never changed it, and landing on a deep link or reloading the page showed the wrong one.
Every section needed an entrance animation to justify existing, which is how motion turns into decoration. Fade-and-slide-up on six blocks is not choreography, it is a tic.
And one page can only carry one title and one description, so every view shared metadata that described none of them.
What routes fixed for free
Active state is now derived from the current path, so a deep link, a reload and a back button are all correct by construction. There is no scroll position to track and no observer to keep in sync.
Each view carries its own title and description. And motion has exactly one job left: the transition between views.
The cost
The transition is now load-bearing. On one page, a bad scroll animation is a small annoyance; between routes, a hard cut is the most visible flaw the site can have. I have moved work into the motion phase rather than removed it.
One guard made the change safe. Typed routes turn a link to a route that does not exist into a compile error, so the structure cannot rot quietly as I move things around. The first time I enabled it, it rejected my own nav links - they had been plain strings that nothing had ever checked.