Docs menu
Getting started
IntroductionInstallationProject structureBuilding pages
RoutingPagesLayoutsStylingMarkdownContent and dataIslandsGoing live
SEO and headDeployingFormsGuides
Build a brochure siteAdvanced
Running as a serverReference
ReferenceBuilding pages
Routing
How files in src/pages become URLs, including dynamic and catch-all routes.
The path of a file in src/pages is its URL. There's no route list to keep up to date.
| File | URL |
|---|---|
index.imba |
/ |
about.imba |
/about |
about/index.imba |
/about (same as above) |
privacy.md |
/privacy (a Markdown page) |
blog/[slug].imba |
/blog/anything: one file for many pages |
docs/[...path].imba |
/docs, /docs/a, /docs/a/b: catch-all |
404.imba |
shown for URLs that don't exist |
Files and folders starting with _ are ignored.
Dynamic routes
A [name] in a file or folder name matches one URL segment and passes it to the page as
params.name:
# src/pages/blog/[slug].imba
import {posts} from '../../posts'
# Which pages exist (needed for the static build)
export def paths
posts.map do({slug}) {slug}
# Runs before render; the result arrives as `data`
export def load {params}
posts.find do $1.slug == params.slug
export default tag PostPage
data
<self> <h1> data.title
pathslists every value the route can take. The static build makes one page per entry, and indevany other URL gets the 404 page, so dev and production behave the same.- A dynamic route without
pathsstill works indevandstart, but is skipped (with a warning) in the static build.
[...name] matches any number of segments, including none: docs/[...path].imba gets
params.path as '', 'a' or 'a/b'.
Which route wins
When several routes could match, the more specific one wins: a fixed segment beats
[param], which beats [...rest]. So blog/new.imba is used for /blog/new even though
blog/[slug].imba also matches.
If two files give the same URL (about.imba and about/index.imba), the build warns and
uses the first.
Not-found pages
src/pages/404.imba is used for any URL with no page. It gets status 404, is kept out of
search results (noindex), and the static build writes it to dist/404.html, which
Netlify and Cloudflare Pages use automatically.
Instant page changes
Every page is a normal HTML page, so clicking a link loads the next one in full. Two things make that feel instant, with no JavaScript from imba-pages:
- Prerendering. When a visitor hovers over a link to another page on the site, the browser loads that page in the background, so the click shows it at once. This uses the browser's speculation rules.
- Cross-fades. The old page fades into the new one instead of flashing white (view transitions). Visitors who ask for reduced motion don't get them.
Both are on by default. Browsers that don't support them load pages as usual. To change
them, in src/site.imba:
export const prefetch = 'tap' # 'hover' (default), 'tap', 'eager' or no
export const viewTransitions = no # turn off the cross-fade
'tap' waits until the link is pressed, and 'eager' starts sooner than hover. Add
data-no-prefetch to a link that shouldn't be loaded early, such as one that logs out or
counts clicks. Links that open in a new tab or download a file are already skipped.
Analytics tools that count page views when a page loads may count prerendered pages the visitor never opens. Most well-known ones handle prerendering; check yours if it matters.