Pages, Navigation & Routing

Turn a single page into a multi-page site with a shared header, footer, and navigation.

14 min read·5 parts·beginner

Your site so far lives on a single scrolling page. That's fine for a one-shot landing, but the moment you want an About page, a Contact form, or an article you can share, you need real routes — separate URLs that can be linked to, bookmarked, and indexed. This lesson turns the portfolio into a proper multi-page site with a shared header, footer, and navigation.


Part 1 · From one page to many

A single long page is easiest to build and read top-to-bottom. But distinct sections — Services, About, Contact — each deserve their own URL so people can share /contact directly, search engines can index them separately, and analytics can tell you which one earned the visit.

Avoid
One long page with #anchors
Every "section" shares the same URL, the same title, and the same social preview. /#contact and /#about look identical to Google.
Do
Separate routes per section
/about, /services, and /contact each have their own title, description, and share image — and each is a real pageview.
Rule of thumb
If a section could reasonably stand on its own — you'd link to it from an email, a business card, or a tweet — it should be its own route. Anchors are fine for a table of contents inside one long article, not as your primary navigation.

Part 2 · Anatomy of a page

Every route in a modern site has four pieces. The agent knows all four — you just need the vocabulary to talk about them.

Figure 2.1
https://ahmadnajmi.com/aboutURLresolves toShared layout (header + footer, once)Header · logo · navPage contentabout.tsx · unique to this routeplus its own title, description, og:imageFooter · links · copyright
A page is a URL that resolves to a route file, wrapped by a shared layout, with its own content and metadata.
  • URL — what people type or share. Keep it short, lowercase, kebab-cased: /case-studies, not /CaseStudies.
  • Route file — one file per URL. Filenames map to URLs; the agent creates them for you.
  • Shared layout — header, footer, and site chrome written once and reused on every page.
  • Page metadata — a per-route title, description, and social image so each URL previews correctly.

Part 3 · Adding a new page

Adding a page is a four-move prompt: name the URL, describe the content, ask for it to appear in the nav, and set its metadata. Do all four in a single message so you don't ship an orphan page.

Figure 3.1
  1. 1Route

    Name the URL and create the route file.

  2. 2Content

    Draft the section — hero, body, CTA.

  3. 3Nav

    Add it to the header (and footer) links.

  4. 4Meta

    Unique title, description, og:image.

The four moves for shipping a new page. Skipping any one leaves a page users can't find or search engines can't rank.

A prompt that adds a whole page

"Add a new route at /about. Content: a one-column editorial page — short bio, three career highlights, and a CTA linking to /contact. Add 'About' to the header nav between 'Home' and 'Research'. Set the page title to 'About — Ahmad Najmi', description to a 150-character bio, and reuse the same design tokens as the home page."
Naming tip
Route names are contracts with the internet. Once you publish /blog/hello-lovable, changing it breaks every link ever shared. Pick names that will still make sense in a year.

Part 4 · Shared layout & navigation

The header and footer belong in a shared layout, written once and rendered around every route. Change the logo in the layout and it updates everywhere. Add a nav link there and every page gets it.

Figure 4.1
ahmadnajmi.com/about
Ahmad Najmi
About
The current route is highlighted. The layout renders on every page.
Active-link state: users always know which page they're on. The agent handles this with one prop when you ask.

What to ask for

  • Put the header and footer in a shared layout so I only edit them once.
  • Highlight the active nav link — accent underline, matching design tokens.
  • Add a mobile menu: a hamburger that opens a full-screen overlay with the same links.
  • Keep the footer minimal — email, socials, and a copyright line.
Watch-out
If a new page appears blank after adding it, the layout is probably missing its outlet — the slot where child pages render. Tell the agent the layout must render its outlet and it will fix it in one pass.

Part 5 · Dynamic & nested routes

Some URLs aren't fixed — they carry data. A blog post at /blog/why-i-teach, a project at /projects/nexscholar, a lesson at /teach/lovable/lesson-4. These are dynamic routes: one file that renders many URLs by reading a parameter out of the path.

Figure 5.1
URLsOne route file/blog/why-i-teach/blog/hello-lovable/blog/design-tokensblog.$slug.tsxreads slug from the URL
One dynamic route file serves every slug. The URL segment becomes a parameter you read to fetch the right content.

When to reach for a dynamic route

  • You have a list of similar items — posts, projects, lessons — and each needs its own URL.
  • You want each item to have its own title, description, and share image.
  • The number of items will grow, and you don't want to hand-write a route file for every one.

When not to

  • You have three static sections. Just make three static routes — dynamic routing is overkill.
  • The content is genuinely one page (a resume, a single essay). Keep it simple.
"Add a dynamic route /blog/$slug that reads the slug from the URL and looks up the matching post from a list I'll add later. If the slug doesn't match, show a 'Not found' state. Give each post its own title and description in the metadata."

Routing cheat sheet

Five moves that turn any page into a proper route on a proper site.

  • Route — one URL per shareable section; short, lowercase, kebab-case.
  • Layout — header and footer live in the shared layout, not on each page.
  • Nav — every new page gets added to the header (and footer, if it belongs).
  • Meta — unique title, description, and og:image per route, always.
  • Dynamic — reach for $slug only when you have a growing list, not for three static pages.
Recap
Your portfolio is no longer one page — it's a site. The design system from Lesson 3 now carries across a real header, footer, and set of routes. Next, in Lesson 5, we'll fill those routes with real content and media: images that load fast, icons that stay crisp, and generated assets that don't look generated.