Every static site generator's homepage says fast, simple and modern. So does mine. Those three words have stopped meaning anything, so let me try to place Stati with sentences instead, including the ones that say "not for you".
What Stati is
A static site generator and nothing else. Markdown and Eta templates go in, a folder of HTML files comes out. Nothing of Stati runs in the browser. There is no runtime, no hydration, no component tree waking up after the page loads. If a page has JavaScript, it's because you wrote a .ts file and Stati bundled it with esbuild and put it on the pages you asked for.
It's TypeScript-first. The config is stati.config.ts through defineConfig(), so your editor knows the options before you do. Client code is TypeScript, compiled per bundle, with include and exclude patterns per page. The templates are Eta, which is HTML with <% %> tags around plain JavaScript, and a layout is a whole document you can read from <!DOCTYPE html> to </html>.
Everything a content site needs comes in the box: sitemap, robots.txt, RSS feeds, SEO tags with Open Graph and Twitter cards, a JSON search index, navigation helpers, callable partials with props, build hooks, build metrics, a dev server with live reload and an error overlay. Each is off until one typed line turns it on. None needs a plugin, because there is no plugin system.
Then there's Incremental Static Generation. Stati keeps a cache manifest between builds and re-renders only the pages whose content or templates changed, or whose time-to-live ran out. TTLs can age: a post that's a day old is rebuilt every five minutes, a month old daily, a year old never, until something it depends on changes. stati invalidate "tag:news" clears by tag, path or age. This is normal in the big frameworks and unusual in a plain generator, and it's the part I'm proudest of.
And it's small: a handful of runtime dependencies in core, counted every time one is added.
What Stati isn't
Not a framework. No React, Vue or Svelte components, no islands, no MDX. If you want a React component inside your Markdown, use Astro. I mean that without irony: Astro is excellent at exactly that, and Stati will never try.
Not a CMS. There is no admin, no editor, no login. Content is files in a git repository. If someone needs to write without git, put a headless CMS in front and write its posts to Markdown before the build.
Not a server. ISG happens at build time. A TTL running out doesn't regenerate anything on the host, it decides what the next stati build renders again. Fresh content on a static host means a scheduled build. If you need pages rendered on request, you need a server, and Stati is not one.
Not Hugo. Hugo renders a hundred thousand pages before Node has finished loading its modules, and if you have that many pages and no cache, use Hugo. Stati's answer to speed is not rendering what didn't change, which gets you most of the way on sites with hundreds and thousands of pages and is beside the point at a hundred thousand.
Not a plugin ecosystem. You can add markdown-it plugins, your own template filters and build hooks. You can't install a "Stati plugin", because I'd rather build the five things every site needs than maintain an API for the fifty things some site might.
Not internationalised, not yet. No locale routing, no translated strings. You can build a bilingual site with two folders and two layouts, but Stati won't hold your hand.
Where it sits
- Jekyll: where I started, in Ruby. Stati is the same idea with a toolchain I actually have installed.
- Hugo: the fastest, Go templates, a single binary. Choose it for scale. Stati is for people who would rather write JavaScript in their templates than Go.
- Eleventy: the closest cousin. JavaScript, file-based, many template languages, and a rich plugin ecosystem you assemble yourself. Stati is the opposite trade: one template language, the common features built in, typed config, incremental builds. If you like assembling, Eleventy. If you like unboxing, Stati.
- Astro: components, islands, MDX, content collections, and a static mode. The best choice when a site has interactive parts. Stati is the choice when it doesn't.
- Next, Nuxt and friends in static export mode: frameworks first, generators second. I rebuilt this blog on one of them and wrote about it in 2020. The export is a feature of the framework, so you inherit the framework.
When to use it
Use Stati when:
- The site is content: a blog, documentation, a newsletter archive, a company site with pages.
- You like HTML and want templates that look like it.
- You want TypeScript in the config and in the browser, and nothing else in the browser.
- You want the boring features done and don't want to shop for them.
- The site is big enough that rebuilding everything on every commit is annoying.
Skip it when the site is an app with a static shell, when your writers need an editor, when you need request-time rendering, or when MDX is the reason you write.
Where I want it to go
This is the part where I'm allowed to dream a little.
I want a site that outlives its tooling. You install Stati once, write Markdown for ten years, and the only thing that changes is the version number in package.json. Every breaking change costs me a long think and a changelog entry you can act on in a minute.
Listings should always be right. Today a layout can list a folder's posts. Soon the listing will know when a post it lists changes its title, and rebuild itself and nothing else. Pagination and a page per tag come with it, from one template file with a bracket in its name. This blog needs both before it can move over, and it's moving over.
Images should work without a build step on a Lambda. Width and height on every image so pages don't jump, modern formats at several sizes, and a link preview card drawn for every page from a template, without a headless browser anywhere. That belongs in its own package, so core stays small and the people with pixel art and no photos don't pay for an image encoder.
I want the docs to be enough for an agent. Not because I think an LLM should design your site, but because a tool an agent can use correctly from its documentation alone is a tool with honest documentation.
And I want it to stay something one person can hold in his head.
If your site is content, try it with npx create-stati. If it's an app, I've just saved you an afternoon.