Stop 06 · Browser APIsTopics · 8/13

History API

Part of the Frontend Developer Roadmap

In short

In apps like Gmail, clicking a link changes the URL but the page never fully reloads. The History API makes that possible, and keeps the back button working.

`history.pushState`/`replaceState` and the `popstate` event let JavaScript manipulate the browser's URL and back/forward history without a full page reload — the foundation of client-side routing. This enables single-page applications to keep URLs meaningful and navigable while updating views without performing a full document navigation.

The jaadu mascot sits on a train seat flipping back through a small ticket booklet.

Think of it like this

Pages in a train ticket booklet

Each stop in your trip gets a page in the booklet. You can add a new page without starting a new booklet, and flipping back shows earlier stops. pushState adds a page, the back button flips back.

Watch it happen

How a single-page app changes view

User
Your JS
History

clicks /about link

1/6Your click handler calls preventDefault, so the browser doesn't load a new page.

The big ideas

What you need to know

pushState adds an entry

history.pushState(state, "", url) changes the URL and adds a history entry, without loading a new page.

replaceState swaps it

Updates the current URL without adding an entry. Good for filters, so back doesn't step through every click.

popstate on back

When the user presses back or forward, popstate fires. Your code re-renders the right view.

You render, not the browser

pushState only changes the URL. Showing the right content is your job.

See it in code

Walk through the code

js
1function render(path) {2  app.innerHTML = path === "/about" ? "<h1>About</h1>" : "<h1>Home</h1>";3}4 5document.addEventListener("click", (e) => {6  const link = e.target.closest("a[data-link]");7  if (!link) return;8  e.preventDefault();9  history.pushState({}, "", link.href);10  render(location.pathname);11});12 13window.addEventListener("popstate", () => render(location.pathname));14render(location.pathname);

1/4render decides what to show for a path. Here, just two views.

This is a tiny router. React Router and the Next.js router do the same thing under the hood, with many more features.

Save yourself the pain

Common mistakes

Oops

Expecting popstate to fire when you call pushState.

Do this instead

popstate fires only on back and forward. Render the view yourself right after pushState.

Oops

Refreshing /about on your deployed app and getting a 404.

Do this instead

Configure the server to send index.html for all app routes, so your JavaScript can render them.

Your mission

Build a tiny router

~30 min

Quick check

Your app calls history.pushState({}, "", "/profile"). What changes on screen by itself?

Go deeper

  1. 1Use `pushState` to change the URL without reloading the page. Verify the behavior with realistic data and handle the failure or empty state as well.
  2. 2Listen for `popstate` to react to the browser's back/forward buttons. Validate your understanding by applying it in a small practical example.
  3. 3Understand this is exactly what React Router/Next.js use under the hood.

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge