The static stack
--stack static scaffolds plain HTML + JS + vanilla CSS (BEM) from _template/static-site: no framework, no install, no build step, nothing to compile. Open index.html in a browser and it works; pnpm deploy ships the files as-is.
Which types
Website types only: website, website-blog, website-blog-docs, single-page. There is no authed app area, so --type webapp requires --stack react, and --features does not apply. Theming is via --accent + --mode (--design belongs to the react stack); for more, edit the custom properties at the top of css/site.css.
pnpm new my-site --type website-blog-docs --stack static --accent teal --mode light
open apps/my-site/index.html # it's just files
pnpm deploy my-site # → Cloudflare Pages (or --to any provider)
What gets generated
- index.html + css/ + js/ — the site itself
- blog/ — generated post pages + blog/index.html (website-blog and website-blog-docs)
- docs/ — generated doc pages + docs/index.html (website-blog-docs)
- content/blog.json and content/docs.json — the editable sources the generator reads
- llms.txt — a machine-readable site summary
The regen-blog workflow
Blog and docs pages are plain HTML generated from JSON. Edit the JSON, regenerate, done — the command regenerates blog AND docs:
# 1. edit apps/my-site/content/blog.json or content/docs.json
pnpm regen-blog my-site
# 2. re-deploy when happy
pnpm deploy my-site
Editing content/docs.json
docs.json is an array of sections {title, pages}; each page is {slug, title, body} where body is a list of blocks. Block kinds: p, h2, h3, quote, code, list (with items), and video (src + caption). Text is HTML-escaped — write plain text. The sidebar renders itself from the structure. blog.json follows the same block model per post. These very pages are built exactly this way.
{
"slug": "my-page",
"title": "My page",
"body": [
{ "kind": "p", "text": "Plain text paragraph." },
{ "kind": "h2", "text": "A heading" },
{ "kind": "list", "items": ["one", "two"] },
{ "kind": "code", "text": "pnpm regen-blog my-site" }
]
}