Pages & routing
The directory is the router. Configuration is only for what can't be inferred.
The tree is the router
An application root is the directory containing crisptastic.toml. Source
discovery never follows paths outside it. Routes, assets, partials, error
handlers and local defaults are inferred from structure; configuration exists
only for facts that cannot be inferred.
Route source files
| Source suffix | Route | Content type |
|---|---|---|
index.html.crisp | / | text/html |
about.html.crisp | /about | text/html |
account/index.html.crisp | /account/ | text/html |
api/profile.json.crisp | /api/profile.json | application/json |
guide/index.md.crisp | /guide/ | text/html (Markdown → HTML) |
robots.txt.crisp | /robots.txt | text/plain |
Canonical directory routes end with /. /account may redirect to /account/
with status 308 when only the directory route exists.
Dynamic segments
blog/[slug].html.crisp → /blog/:slug
[name] matches exactly one non-empty decoded path segment. Static routes
outrank dynamic ones; more static segments outrank fewer; longer routes outrank
shorter; remaining ties are compile-time ambiguity errors. Catch-all segments
are not in profile 1.
Reserved namespaces
_partials/ private reusable sources
_errors/ private error handlers
_triggers/ private synthetic-event routes
assets/ public build assets
.crisptastic/ local generated state
dist/ conventional build output
Any path segment beginning with _ is private and never becomes a public route,
but may be included by public routes.
Route policy
Default methods are GET and HEAD. A route that uses a mutating method must
declare it in the manifest, which prevents accidental mutation endpoints:
[routes."/api/profile.json"]
methods = ["GET", "PATCH"]
body = "json"
max_body_bytes = 65536
auth = "required"
capabilities = ["data"]
Unknown policy keys and policies for nonexistent routes are build errors.
OPTIONS is host-generated from the method policy.
Assets
Every regular file under assets/ is an asset input. .scss entry files (not
beginning with _) compile to .css; Sass partials are inputs only. Other
assets are byte-preserving. Every output gets a SHA-256 digest, length and
content type; the Capsule stores bytes once by digest and maps public paths to
them. Public asset URLs are served from /assets/....
Error handlers
_errors/404.html.crisp
_errors/500.html.crisp
_errors/default.html.crisp
Handlers receive a safe error context, run with a quarter of the render budget, and cannot perform mutating capability operations.
The manifest
crisptastic.toml declares what cannot be inferred: the app identity, minimum
runtime version and language profile, deploy authorities and health route, and
resource limits.
schema = 1
name = "example"
[runtime]
minimum_version = "0.2.0"
language_profile = 1
[deploy]
authorities = ["example.com", "www.example.com"]
health_route = "/_health.json"
[limits]
render_ms = 5000
response_bytes = 8388608
capability_operations = 32