Docs menu

Getting started

IntroductionInstallationProject structure

Building pages

RoutingPagesLayoutsStylingMarkdownContent and dataIslands

Going live

SEO and headDeployingForms

Guides

Build a brochure site

Advanced

Running as a server

Reference

Reference

Building 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
  • paths lists every value the route can take. The static build makes one page per entry, and in dev any other URL gets the 404 page, so dev and production behave the same.
  • A dynamic route without paths still works in dev and start, 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.