Routing
epresso uses routes-as-code: every file under pages/ becomes one or more
routes. Content stays in content/; pages/ produces URLs.
Page kinds
| File | Kind |
|---|---|
pages/about.md | Direct Markdown page (layout via front matter) |
pages/blog/[slug].ep | Single-file route (Python frontmatter + Jinja body) |
pages/robots.txt.py | Endpoint exporting get() -> (content_type, body) |
Route parts
Path segments support static text, {param}, and {...param} (spread):
pages/blog/index.md → /blog/pages/blog/[slug].ep → /blog/<slug>/pages/blog/[slug]/index.ep → /blog/<slug>/ (index.ep = directory root)pages/blog/[...slug].ep → /blog/a/b/ (spread captures the rest)
index in a filename maps to the directory root. Clean directory URLs are
generated with a configurable trailing slash ([build] trailing_slash).
Endpoints
A .py page that exports get() becomes a static endpoint:
pages/robots.txt.py pythondef get(): return "text/plain", "User-agent: *\nAllow: /\n"
File-style URLs like /robots.txt skip the trailing slash. data.json and RSS
feeds are commonly built this way.
.ep single-file routes
The recommended route format — Python frontmatter + Jinja body in one file. See
[The .ep file format](components.md.
epresso---from epresso.routing import Routedef get_static_paths(): return [Route(path=f"/blog/{p.id}/", params={"slug": p.id}, data=p) for p in site.get_collection("posts")]---<article><h1>{{ props.title }}</h1>{{ content | safe }}</article>
A static .ep route with no get_static_paths() renders once at its default path.
site is injected into the frontmatter. A returned Route carries path,
optional params, data (the props passed to the template), and an optional
cache_key (auto-derived from a content entry's digest when absent, so edits
re-render only that path).
Pagination
paginate is a helper that splits entries into numbered page routes:
pythonfrom epresso.routing import paginatedef get_static_paths(): return paginate(site.get_collection("posts"), per_page=10, base_path="/blog/")
It produces base_path/ and base_path/page/N/, each route carrying
data={"entries", "page", "num_pages", "prev", "next"} and params={"page": n}.
Route object
pythonfrom epresso.routing import RouteRoute( path="/blog/hello/", params={"slug": "hello"}, data={...}, # props passed to the template content_type="text/html", body=None, # raw body for endpoints cache_key=None, # incremental identity)
Importable helpers
discover_route_patterns(pages_dir), expand_pattern(pattern, trailing, data_api),
parse_route(path), output_path_for(route_path), and paginate(...) are all
exported from epresso.routing for programmatic use.
View transitions & prefetch
epresso is a static, multi-page site — links cause a normal full-page navigation.
There are no view-transition or prefetch primitives; every URL is a real HTML
document you can deep-link and cache. Add client-side niceties (transition
animations, link prefetch) yourself in a component <script>.