statica
Just HTML. statica turns ordinary HTML files into a static site. You write valid HTML, link build-time data and fragments, and statica emits plain files.
Full reference: docs/guide.md · Man pages: docs/man/
Install
Rust (crates.io):
JavaScript (npm):
Homebrew:
Prebuilt macOS and Linux binaries from GitHub releases. See homebrew/README.md for tap setup.
# package.json scripts: "build": "statica build ."
From this repo (dev):
Quick start
&&
CLI
statica [PATH] build (default)
statica build [PATH] build
statica serve [PATH] preview out_dir (axum + tower-http)
statica watch [PATH] watch + rebuild + serve
statica new <NAME> scaffold
statica -h / --help
statica -v / --version
Project location: PATH (default .) → resolve against process cwd → walk up for statica.toml → site root is that dir, or project / --project under it.
Nested config tables use compact SPECs (CLI wins over the file):
Man pages
Config (statica.toml)
Optional. Missing file → defaults. See docs/guide.md for the full reference.
= "" # relative to this file; empty = here
= ".dist"
= "" # needed for sitemap / RSS
[]
= false
= true
= true
= true
[]
= false
= 50000
[[]]
= 10
= "published_at"
= true
= true
[]
= false
= 50
[]
= "0.0.0.0"
= 4321
[]
= false
= ["en"]
| Asset kind | Tool |
|---|---|
| CSS | lightningcss (nesting, modern syntax → browser-ready; minify with --process or --minify) |
| JS | oxc |
| HTML | minify-html (final pass with --minify) |
| Images | oxipng + image |
| Fonts | copied as-is |
Inline <style> (pages + fragments) is always transformed. Linked .css under asset_dirs is transformed when [process].css is on. Enable [minify] / --minify for a final pass on emitted HTML, CSS, and JS (including inline <style> / <script>).
Authoring
statica source is valid HTML. It uses normal <template>, <slot>, and <link> elements as build-time authoring primitives, so keep them where HTML allows them.
index.html → .dist/index.html
posts/[slug]/index.html → .dist/posts/{item.slug}/index.html
blog/[page]/index.html → .dist/blog/1/, blog/2/, … ([[pagination]])
- Scalar page text →
data-t="${item.field}", or literal text withdata-t="Plain text" - Attributes →
${item.slug}/${page.pagination.next_href}/${i18n.locale} - Fragment mount:
<slot id="fragment-id"></slot>passes the current item/context - Fragment loop:
<slot id="fragment-id" data-each="items"></slot>passes each item - Page
data-binddeclares canonical roots such as{item},{page},{data}, or{i18n}before use - Data link IDs are directly available by
id; they cannot be nameddata,item,page, ori18n - Collection: linked data +
[slug]; current record isitem - Pagination: linked data +
[page]; page chunk ispage.pagination - Fragments never receive canonical page context; pass values through the mount context or link fragment-local data
Keep content funnels build-time. Production output should not fetch site data at runtime unless you are intentionally adding unrelated client behavior.
Crate layout
crates/statica-cli— CLI (cwd/project resolve, config, SPECs, watch/serve, man pages)crates/statica— discover → funnel → bind → scope → emitexamples/blog— dogfood fixturedocs/— guide + man pages
License
MIT
Author
(c) 2026 Simão Nziaka