0Pricing
HTML Academy · Lesson

Hash-Based vs Path-Based Routing

Compare hash routing with pushState-based history routing.

Hash-Based vs Path-Based Routing is a free HTML Academy lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the HTML Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Two Strategies for SPA URLs

SPAs need URLs that the browser does not fetch. Two approaches: hash-based uses the fragment (everything after #) which the browser never sends to the server, and path-based uses the pathname plus History API trickery.

Hash-Based Routing

URLs look like https://example.com/#/about. The server only sees / and serves the same HTML for every URL. Client JS reads location.hash to decide which view to render. Simple, requires no server config.

The hashchange Event

Hash-based routers listen for the hashchange event, which fires whenever location.hash changes. Combined with reading window.location.hash, this is all the API needed for client routing — no History API involved.

window.addEventListener("hashchange", () => {
  const route = location.hash.slice(1) || "/";
  renderPage(route);
});

Path-Based Routing

URLs look like https://example.com/about — indistinguishable from server-rendered URLs. The History API's pushState changes the path without reloading; popstate fires on back/forward; click interception turns <a> into SPA navigation.

Server Configuration Required

For path-based routing, the server must return the SPA's index.html for any path the user might enter directly (or refresh). Otherwise refreshing /about gets a 404. Configure: try the file, fall back to index.html (history fallback in Nginx, vite-plugin-history-api in Vite dev).

# Nginx config
location / {
  try_files $uri $uri/ /index.html;
}

SEO and Sharing

Search engines and many tools cannot crawl hash fragments at all — content at /#/about is invisible to old crawlers (Google handles it via headless rendering, others may not). Path-based URLs are crawled normally, making them strictly better for SEO.

User Perception

Hash URLs are visibly "weird" — users notice the # and may not trust the link or remember to copy the full URL. Path URLs look like every other web URL, which is what users expect. Modern SPAs almost always pick path-based routing for this reason alone.

Implementation Complexity

Hash-based: ~10 lines of JS (hashchange listener + render). Path-based: pushState calls, popstate listener, link click interception, server-side fallback. Hash is the lightest possible choice; path requires more infrastructure for a better user experience.

Static Hosting Considerations

Pure static hosts (GitHub Pages' default config) cannot do server-side fallback, so path-based routing breaks on refresh. Workarounds: 404.html redirect tricks, host on Netlify/Vercel (which understand SPA fallback), or accept hash-based for static-host-only projects.

Hybrid Approaches

Some apps mix both: path-based for the primary route, hash for in-page sections (modals, tab anchors). The hashchange event still fires for these, complementing the History-based router for sub-page state without polluting the main URL.

Migrating Between the Two

To migrate hash to path: rewrite all internal links, add server fallback, replace hashchange logic with popstate, redirect old hash URLs to path equivalents with a small bootstrap script that runs once and calls history.replaceState.

Decision Criteria

Pick hash-based for: static hosts without rewrites, internal admin tools where SEO does not matter, embedded widgets. Pick path-based for: anything user-facing, anything that should be SEO-indexed, anything shared on social media — which is most apps.

Knowledge Check

Why does path-based SPA routing require server configuration that hash-based routing does not?

Summary

Hash-based routing (URLs like /#/about) needs no server config but has weak SEO and uses ugly URLs. Path-based routing (URLs like /about) needs a server fallback to index.html, but produces clean, SEO-friendly, shareable URLs. Modern public-facing SPAs use path-based; static-host or internal projects may still pick hash for simplicity.

Frequently asked questions

Is the “Hash-Based vs Path-Based Routing” lesson free?

Yes — the full text of “Hash-Based vs Path-Based Routing” is free to read here on the web, and the HTML Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the HTML Academy course, upgrade to CoddyKit PRO.

What will I learn in “Hash-Based vs Path-Based Routing”?

Compare hash routing with pushState-based history routing. You practise HTML Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start HTML Academy?

No prior experience is required. HTML Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Hash-Based vs Path-Based Routing” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this HTML Academy lesson?

Yes. Every HTML Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. pushState and replaceState
  2. The popstate Event
  3. Hash-Based vs Path-Based Routing
  4. The Navigation API modern browsers
← Back to HTML Academy