Lesson · Beginner

Build a multi-page site

Organize several HTML documents, shared assets, relative links, and navigation into a small site that works without JavaScript.

Published
Last checked

Plan the file tree first

A small site can use one HTML file per stable page and share CSS, scripts, and images.

site/
├── index.html
├── about.html
├── contact.html
├── css/
│   └── site.css
└── images/
    └── workshop.webp

Each document needs its own title, main heading, and relevant content. Repeated navigation should link to real files with the same labels and order.

<nav aria-label="Primary">
  <a href="index.html">Home</a>
  <a href="about.html">About</a>
  <a href="contact.html">Contact</a>
</nav>

Test from more than the home page

Open and reload each page directly. Broken relative paths often hide when you only navigate from the root. Test at narrow widths and with JavaScript disabled before publishing.

How browsers actually behave

Each HTML document is an independent navigation target with its own URL, history entry, title, and response. Shared CSS and images may be cached, but the browser does not automatically synchronize repeated navigation markup. A file that works from the home page can still fail when opened directly if its asset paths were resolved from the wrong directory.

Static hosts commonly map a directory to its index.html and may enforce case-sensitive filenames even when a local development disk does not. Clean URLs, trailing slashes, redirects, and 404 behavior depend on host configuration and must be tested after deployment.

Decisions and trade-offs

Create one page per stable user job rather than one page per keyword variation. Small sites can maintain repeated navigation manually; once duplication causes drift, a static-site generator or framework template can create the same ordinary HTML from shared data.

Choose a URL convention early and keep internal links, canonicals, and sitemap entries aligned. Prefer durable names that describe content rather than temporary campaign language. Store shared assets in predictable directories and avoid traversals so complicated that authors cannot reason about them.

Accessibility consequences

Consistent navigation labels and order reduce relearning between pages. aria-current="page" can identify the current destination without disabling its link. Each page still needs its own descriptive title, main heading, skip link target, and visible focus behavior.

Navigation must survive JavaScript failure. A client-side transition can improve speed, but ordinary anchors should preserve deep links, reloads, history, and open-in-new-tab behavior.

Common failures and fixes

  • A nested page loses CSS. Its relative asset path assumes the root. Correct the path or use a deliberate root-relative convention.
  • Direct navigation returns 404. The deployment only tested client routing. Configure static rewrites or publish real documents and test deep links.
  • One page shows stale navigation. Repeated markup drifted. Move stable navigation data into a shared build template.
  • Two URLs show the same page. Trailing-slash or filename variants are not normalized. Choose one canonical and redirect alternatives in one hop.

Verify it

Open every page directly in a clean session, reload it, and follow navigation in both directions. Run a link checker and compare internal destinations with the generated sitemap. Inspect the Network panel for 404 assets and unexpected redirect chains. Test exact filename case on the deployed host, then complete the main journey with JavaScript blocked, keyboard only, 200% zoom, and a 320-pixel viewport.

Exercise and next step

Create a three-page project. Add one shared stylesheet and confirm every page loads it when opened directly. Next, publish the exact tested artifact and verify its public routes.

Boundary of this lesson

A multi-page structure does not require a client router, database, or build framework. Those tools become useful when shared templates, content volume, or authenticated behavior justify them. Conversely, copying dozens of pages by hand eventually creates drift. Watch for repeated navigation, metadata, and footer changes as the signal to introduce a deterministic build step. Preserve the resulting ordinary URLs and server-rendered HTML so the architecture continues to work through reloads, deep links, and script failure.

Practice with a moved page

Rename one page and one asset deliberately. Update internal links, navigation, canonical identity, sitemap membership, and the host redirect for the retired URL. Request the old and new addresses directly and verify one permanent hop to the final successful page. This small migration exposes every place where a multi-page site can duplicate path knowledge and shows why a registry or shared build source becomes valuable.

Finish by crawling from each entry page, not only the home page. Every public document should reach the shared navigation, stylesheet, and recovery routes when opened directly. Compare the crawl with the sitemap and generated output; an orphaned page or unreferenced asset signals that path knowledge has drifted between sources.