skip to content

File-Based Route Conventions

The directory tree as the route table: dynamic, catch-all and optional segments, precedence at one depth, groups that organise files but not the URL. Asked because no central route list exists.

on this pageshow

questions

6

In a meta-framework whose routes come from the directory tree, what makes one file a page at a URL and its neighbour not?

level: juniorimportance: must knowfreq 74%

answer

  1. the tree is the route table
  2. folder = segment, file = claim
  3. reserved name, not file contents
  4. index shape claims the folder's own URL
  5. everything else is colocated code

basics

~20 s

A file becomes a route only when its name matches the router's reserved route-module name, at its position under the routes directory; the folder chain becomes the URL. Every other file there is colocated code the router ignores.

solid answer

~50 s

In a file-based router the route table is derived, not written. A build step walks one designated routes directory: each folder level contributes one URL segment, and a folder becomes addressable only when it holds a file with the router's **reserved route-module name** — the index shape. The same reserved name in a nested folder claims that deeper URL. Anything else in the folder — a component, a test, a stylesheet, a helper — is *colocated*: importable by the route, invisible to the router. That is why dropping a well-written component into a folder and visiting the matching URL gives a 404: the folder exists and contributes a segment for anything beneath it, but nothing claims the URL itself. Reserved names differ between frameworks; the rule that a file's **name and position**, not its contents, decide routability does not.

go deeper

for a junior

Recall the two-line rule: folders make segments, and a file with the reserved route-module name claims the URL. When a new page 404s, check the directory, the file name, and the folder chain in that order.

for a middle

Explain the mapping precisely: index shape versus named child, why colocated files are invisible to the router, and why an unmatched URL is a not-found rather than an error the build could have caught.

for a senior

Show the practice around the convention: where shared code lives relative to the routes tree, how route deletion stays clean, and how the team answers 'which URLs do we serve' when no file lists them.

for a principal

Frame the tradeoff you are buying organisation-wide: implicit registration removes a class of sync bugs and adds an unreadable route table, and you owe the org a generated listing or typed helpers to compensate.

## The route table nobody wrote In a **file-based router** the application's URLs are not listed anywhere. A build step walks one designated **routes directory** and derives the table from what it finds there. The rule most meta-frameworks share is small enough to state in two lines: 1. **Each folder level under the routes directory contributes one URL segment**, named after the folder. 2. **A file with the router's reserved route-module name claims a URL** — the folder's own URL when that name sits directly inside it, a deeper URL when it sits in a nested folder. Notice what is *not* in those two lines: the file's contents. A module can export a flawless component, be imported by three other files and type-check cleanly, and still never be reachable, because routability is decided by **name and position**, never by what a module exports. The convention replaces a registration call: you create a path on disk and a path on the web appears. ## Index shapes and named segments Every file-based router needs to distinguish *the URL of this folder* from *a URL one level deeper*. The first is conventionally called the **index** shape. | On disk | URL served | What it expresses | |---|---|---| | the reserved route-module name directly inside `settings/` | `/settings` | the **index** of that folder | | the reserved route-module name inside `settings/profile/` | `/settings/profile` | a **named child segment** | | a flat route file named for the child beside the index, where a router allows flat names | `/settings/profile` | the same child, written flat | | a folder `settings/` containing no route module at all | nothing | a segment for its children only | Some routers spell the index as a reserved file name inside the folder; others let a flat file name carry the whole path. The distinction that matters is conceptual and portable: **one shape claims the folder's own URL, the other claims a child**. Frameworks also differ on whether folder-per-segment, flat dotted file names, or both are supported — a difference of spelling over the same tree-to-table mapping. ## Colocation: the files that are not routes Because only reserved names route, a route folder can safely hold the code that belongs to that route: the components it renders, its tests, its styles, small helpers. This **colocation** is a deliberate benefit of the convention, not an accident: - **Deleting a route is deleting a directory.** Everything that existed only for that URL goes with it, so dead code has nowhere to hide. - **Reviewers see the blast radius.** A diff confined to one route folder is, by construction, confined to one URL subtree. - **Imports get shorter and more honest** — the things used by exactly one route sit next to it instead of in a global bucket. - **The cost is a mixed directory.** The routes tree now holds two kinds of file, and skimming it no longer shows only URLs. Most routers therefore also offer a marker that tells them to ignore a folder wholesale, and many teams keep anything shared outside the routes directory entirely. Colocated files are still ordinary modules. They are not served to the browser as files, and they are bundled only if a route actually imports them. ## Why a miss is a 404, not a build failure The router builds its table from what it found; a request for a URL no entry claims is simply unmatched, and unmatched is the not-found path. Nothing in the build knows you *intended* that folder to be a page, so nothing can warn you. This is the characteristic newcomer bug of file-based routing, and the diagnosis is always the same three checks: 1. Is the file under the **routes directory** the framework scans, and not a sibling of it? 2. Does its name match the **reserved route-module name** exactly, including extension and case? 3. Does the chain of folders above it spell the URL you actually requested? ## What the convention buys and what it costs The upside is that the filesystem is the documentation: a URL tells you where the file is, and a file tells you what URL it serves, with no registration list to keep in sync and no chance of a route that exists in code but was never registered. The downside is the mirror image. **There is no single place to read the route table**, so answering "what URLs does this app serve?" means walking a tree. A rename is a directory move that no compiler sees, so internal links written as strings break silently. And the reserved names are magic: nothing in the language explains why one file name is special, which is why most frameworks ship a generated listing or typed route helpers to hand back what the convention took away.

  • If the router ignores non-route files, why do teams still keep shared components out of the routes directory?
    Ignoring them keeps them off the web, not out of the way. A routes tree mixing URLs with shared helpers is harder to skim, and a helper used by five routes has no natural owner folder. Colocation earns its keep for code that exists for exactly one route; anything shared belongs outside.
  • Why does a folder with no route module in it still matter?
    It contributes a URL segment for everything beneath it, so nested routes still spell their path through it, and it is a natural home for files shared by that subtree. It simply claims no URL of its own, which is why requesting that level alone does not match.
  • What happens if two different on-disk shapes describe the same URL?
    The URL, not the file path, is the key, so the two entries collide. Most routers treat that as ambiguity and fail the build or report a conflict rather than silently choosing; a few resolve it by a documented precedence rule. Either way it is a defect to remove, not a feature.

Room numbering in a building: the corridor and door plate together make an address, and the reserved plate is what makes the door a room anyone can ask for. The furniture inside has no address of its own.

saying these in an interview costs you the question

  • Thinks any component file in a route folder becomes a page
  • Believes creating the folder alone publishes the URL
  • Expects a central route list somewhere to register each page
  • Assumes colocated files are served to the browser as files
  • Reads the 404 as a build failure rather than an unclaimed URL
  • Thinks the file's exports, not its name, decide routability
open as a page

In a file-based router, how do dynamic, catch-all and optional segments differ in what they match and in what the route receives?

level: middleimportance: must knowfreq 78%

basics

~20 s

A dynamic segment matches exactly one non-empty path segment and hands the route one value. A catch-all matches the whole remainder as an ordered collection. The optional form of either also matches the shorter URL where that part is absent.

open as a page

When a static folder and a dynamic segment at the same depth both match a URL, which one serves the request, and what decides that?

level: middleimportance: should knowfreq 62%

basics

~20 s

The more specific shape wins: a literal segment beats a dynamic one, which beats a catch-all, compared depth by depth from the left. A directory tree has no declaration order, so routers rank by specificity instead.

open as a page

In a file-based router, what does a folder the router omits from the URL let you do, and what does it deliberately not change?

level: middleimportance: should knowfreq 50%

basics

~20 s

It groups route files on disk — by section, team or shared shell — without contributing a URL segment. URLs are unchanged, so two groups describing the same path collide, and the grouping is invisible in the address.

open as a page

How would you weigh a convention-derived route table against an explicit central route configuration for a large, multi-team application?

level: principalimportance: should knowfreq 40%

basics

~20 s

Decide by who reads the route table and how routes are created. Convention removes registration bugs and scales across teams; a central list stays readable and programmable. At scale, usually convention plus a generated listing and enforced conventions.

open as a page