Welcome to Krate
Krate is a Go-native static site generator with signal-based reactivity. It compiles TSX/JSX pages into static HTML at build time and generates a tiny hydration bundle that makes pages interactive on the client.
No React. No external bundler subprocess. No Node.js required for core compilation. The compiler — lexer, parser, bundler, renderer, CSS pipeline and Tailwind generator — is 100% custom Go, and builds run in milliseconds.
Highlights
- Go-native compiler — a custom lexer, parser, bundler, and renderer. Builds run in milliseconds.
- Signals, not React — fine-grained reactivity with
createSignal/createEffect/createMemo. - SSG-first — every page is pre-rendered to static HTML. Hydration binds signals to the DOM via
data-k/data-khmarkers. - File-based routing —
src/pages/maps to URLs, with nested routes, dynamic segments ([param]), and_layout.tsxlayouts. - Component tiers — static, client, server (
@server), and runtime (@runtime, via embedded QuickJS) components in one page. - Full CSS pipeline — CSS Modules (FNV-32a scoping), Go-native Tailwind, minification, and
@importinlining. - SSR, ISR & streaming —
getStaticProps,getServerSideProps, revalidate-based ISR, and Suspense-based streaming SSR. - SPA router — client-side navigation with DOM tree reconciliation; state, focus, and scroll survive transitions.
- Plugin system — Go plugin hooks plus community plugins written in JavaScript, executed inside the embedded QuickJS runtime.
- WASM docs search — the docs plugin ships a search bar powered by Microsoft's docfind, with the index embedded into a WASM module at build time.
How it works
Source (.tsx/.ts/.md/.mdx) │ ▼ Lexer (tokenize) ──► Parser (AST) ──► Bundler (imports, CSS modules, React rewrite) │ ▼ Renderer (SSR: AST → HTML + signal/handler detection) │ ▼ Hydration Codegen (signals → JS bundle with data-k/data-kh bindings) │ ▼ Build Output (HTML + hashed JS + hashed CSS + manifest.json) A taste
import { createSignal } from '@krate/runtime'; export default function Counter() { const [count, setCount] = createSignal(0); return ( <div> <span>{count()}</span> <button onClick={() => setCount(c => c + 1)}>+</button> </div> ); } The <span>{count()}</span> becomes server-rendered HTML at build time, and the hydration bundle registers an effect that updates just that text node when setCount is called.
Where to go next
| Goal | Page |
|---|---|
| Install and scaffold | Getting Started |
| Configuration options | Configuration |
| Every CLI command | CLI Reference |
| Signals and effects | Reactivity |
| Routing and layouts | Routing & Layouts |