Getting Started
This guide walks you through installing the Krate CLI, scaffolding a project, and building your first page.
Prerequisites
- Node.js 20+ — for the npm CLI wrapper and running
krate.config.ts - Go 1.26+ — only needed when building the compiler from source
The published CLI ships pre-built binaries for macOS, Linux and Windows, so you do not need Go to build a site.
Install the CLI
npm install -g @krate/core # or pnpm add -g @krate/core Create a project
krate init my-app # or, using the create-krate-app scaffold directly: npx create-krate-app@latest my-app krate init (alias krate create) scaffolds a complete project — including krate.config.ts, tsconfig.json, package.json, a landing page, a layout, and a 404 page. With no directory it prompts for a name.
Add a page:
// src/pages/index.tsx export default function Home() { return <h1>Hello, World!</h1>; } Build and run
krate dev # dev server with hot reload on http://localhost:3000 krate build # production build → dist/ krate serve # preview the production build Your first interactive page
Krate's reactivity is built on signals. A signal is a getter/setter pair; reading a signal inside an effect subscribes that effect to it.
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> ); } count()reads the current value.setCount(c => c + 1)writes a new value and notifies subscribers.- At build time the renderer extracts the initial value and emits static HTML.
- At runtime the hydration bundle wires the button to update the
<span>.
Data fetching
Pages can declare build-time props with getStaticProps:
export async function getStaticProps() { const res = await fetch('https://api.example.com/data'); return { props: { data: await res.json() } }; } export default function Page({ data }) { return <pre>{JSON.stringify(data, null, 2)}</pre>; } Synchronous getStaticProps (object literal returns) is evaluated by the compiler directly; asynchronous ones run through an npx tsx bootstrap at build time.
Layouts
A _layout.tsx file wraps every page in its directory (and subdirectories):
// src/pages/_layout.tsx export default function Layout({ children }) { return ( <div> <nav><a href="/">Home</a></nav> <main>{children}</main> </div> ); } Dynamic routes
Files named [param].tsx become dynamic segments:
// src/pages/video/[id].tsx → /video/abc123 export default function VideoPage({ params }) { return <h1>Video {params.id}</h1>; } Built-in components
Built-in components (Head, Link, Icon, Image, Script, Style) are recognized by the compiler by name — no import needed:
export default function Page() { return ( <> <Head> <title>My Page</title> <meta name="description" content="A cool page" /> </Head> <Icon name="lucide:heart" /> <Image src="/photo.jpg" width={800} alt="Photo" /> <Link href="/about">About</Link> </> ); } <Image> compiles to a WebP-first <picture>: lossy WebP variants generated at build time with original-format fallback, responsive srcset/sizes, lazy/eager loading, blur placeholders, and aspect-ratio-based CLS mitigation. <Link> renders an SPA-enabled <a> with prefetching, replace, scroll, hash scrolling, and aria-current for the active route.
Next steps
- Explore Configuration for the full config surface.
- Learn Reactivity in depth.
- See Routing & Layouts for routing features.