What is routing? (how URLs become pages)
In one sentence:Routing is how your app matches a URL to the page or endpoint that should answer it; when no route matches, the visitor gets a 404.
What it actually is
Routing is the map between URLs and your app’s content. When someone opens /pricing, something has to decide what that address means, which page to render or which piece of backend code to run. That decision is routing. Think of the directory board in an office lobby: a visitor arrives with a name, and the board points them to a floor and a door. The URL is the name, the route is the entry on the board, and the page or API endpoint is the office behind the door.
Most modern frameworks use file-based routing, where the folder structure is the map. Put a file at src/pages/about.astro (Astro) or app/about/page.js (Next.js) and /about exists. There is no routing config to maintain; the file’s location is the address. Square brackets make a segment dynamic: app/blog/[slug]/page.js matches /blog/anything, and your code receives the value (slug: "anything"), so one file can serve a thousand blog posts.
There are two ways to move between routes once a site is open. Server-side navigation is the classic web: every click asks the server for a fresh HTML page. Client-side navigation is what single-page apps do: JavaScript intercepts the click, swaps components in place, and updates the address bar without a reload. It feels instant, and it sets up the one routing bug almost every vibe coder hits.
Why your AI just did this
Ask your agent for “a settings page” and it may not write any routing code at all. It creates a file in the right folder, the route appears, and its summary says something like “added a route at /settings.” The same convention often covers data: in Next.js, a file at app/api/posts/route.js becomes the /api/posts endpoint. So when your agent talks about routes, look at the file tree first; that is usually where the change happened.
Routing vocabulary also shows up when links break. “That route doesn’t exist yet” or “the dynamic segment doesn’t match” both mean the map and the address disagree. And if you’re building with plain React (no framework), your agent will bring in a router library such as React Router, because React itself ships without one.
When you’ll run into it
The famous one: everything works on localhost, you deploy, the app still works while you click around, then you refresh on /dashboard (or send someone that link) and get a 404. A single-page app ships one real HTML file, index.html, and the router runs in the browser’s JavaScript. Clicking your way to /dashboard works because JavaScript changed the view. Refreshing is a different request: the browser asks the server for /dashboard, the server looks for a file by that name, finds nothing, and answers 404. The route lives in JavaScript the server never runs.
Dev hid the bug because dev servers cover for you. Vite’s dev server, for example, runs in SPA mode by default (appType: 'spa') and answers unknown paths with index.html so the router can take over. Production hosts are stricter. The fix is a fallback rule that tells your host: for any path you don’t recognize, serve index.html and let the client-side router handle it. On Netlify that is one line in a _redirects file, /* /index.html 200. On Vercel it is a rewrite in vercel.json that sends every path to /index.html; Vercel’s Vite docs warn that deep links in a Vite single-page app won’t work until you add it. Cloudflare Pages assumes a single-page app when your build has no top-level 404.html and applies the fallback on its own. Hosts differ, so ask your agent for the rule that matches where you deploy.
Two more places you’ll meet routing: frameworks that render pages on the server (SSR or SSG) skip the refresh bug entirely, because the server knows every route and can answer any URL directly. And in dev, a typo’d folder name shows up as your framework’s built-in 404 page, which is routing telling you the map has no such entry.
What to check
- Refresh every page of your deployed app straight from the URL bar before you call a deploy done; clicking around only tests client-side navigation
- Read the
app/orpages/folder when a URL misbehaves; the file tree is the route map, so a wrong folder name is a wrong URL - Add your host’s SPA fallback rule if refreshing 404s in production (on Netlify:
/* /index.html 200in a_redirectsfile) - Confirm dynamic segments line up: a folder named
[id]hands your code a value calledid, notslug - Ask your agent whether pages render on the server or only in the browser; server-rendered apps don’t need the fallback
Say it like a dev
Instead of: “my app breaks when I refresh the page” Say: “My single-page app 404s on hard refresh in production. Add the host’s fallback rewrite so unknown paths serve index.html.”
Instead of: “I want another screen for settings” Say: “Add a /settings route with its own page component, using the framework’s file-based routing.”
Instead of: “some product links work and some don’t” Say: “The dynamic route /products/[id] isn’t matching every case. Check the segment name and the params the page receives.”
People actually ask
“Why does my app work until I refresh the page, then show a 404?”
Your app is likely a single-page app: one index.html file plus JavaScript that handles navigation in the browser. Clicking works because JavaScript swaps the view, but refreshing asks the server for a file at that exact path, and no such file exists. The fix is a fallback rule on your host that serves index.html for unrecognized paths so the client-side router can take over.
“What is file-based routing?”
It means your project's folders and files are the URL map. A file at app/about/page.js in Next.js, or src/pages/about.astro in Astro, becomes the /about page with no routing config to maintain. Wrapping a folder name in square brackets, like app/blog/[slug], makes that part of the URL dynamic, so one file can handle every blog post.
“Is a route the same thing as an endpoint?”
They share the same idea: a URL matched to code. A route usually returns a page for a person to look at, while an endpoint returns data, often JSON, for other code to consume. Many frameworks define both the same way, with files placed in an app or routes folder.
Related terms
Checked against
- https://nextjs.org/docs/app/api-reference/file-conventions/dynamic-routes
- https://nextjs.org/docs/app/api-reference/file-conventions/route
- https://docs.astro.build/en/guides/routing/
- https://vite.dev/config/shared-options.html
- https://docs.netlify.com/manage/routing/redirects/rewrites-proxies/
- https://vercel.com/docs/frameworks/frontend/vite
- https://developers.cloudflare.com/pages/configuration/serving-pages/
- https://react.dev/learn/build-a-react-app-from-scratch
Just met this in a real session? Glim reads it in plain words.
Paste what your agent just did, a git diff, your terminal, or its summary, and Glim tells you what changed and what to check before you ship. Nothing stored.
Explain my session →