Move a Next.js App Router or Pages Router site to Krate.
#Migrating from Next.js
Krate's pages, routing, and <Link> semantics mirror Next.js closely, so most files need small edits. The biggest conceptual change: there is no React runtime — components are plain functions returning JSX, and state uses signals.
#Concept mapping
| Next.js | Krate |
|---|---|
useState | createSignal (const [v, setV] = createSignal(0)) |
useEffect | createEffect |
useMemo | createMemo |
useRef | ref={el => …} / useRef (krate runtime) |
className | class |
app/page.tsx | src/pages/index.tsx |
app/blog/[slug]/page.tsx | src/pages/blog/[slug].tsx |
layout.tsx | _layout.tsx (nearest wins; stacks) |
generateStaticParams | generateStaticParams (same shape) |
export const revalidate | export const revalidate (ISR) |
next/link | global <Link> (or <a data-krate-link>) |
next/image | global <Image> |
next/head | global <Head> |
API routes app/api/x/route.ts | src/api/x.ts (JS) or src/api/x.go (Go) |
#Steps
- Scaffold & install
npx create-krate-app@latest my-site
cd my-site && npm install- Move pages. Copy
app//page.tsx(orpages/) intosrc/pages/, renamingindexand stripping thepagefilename:
app/page.tsx -> src/pages/index.tsx
app/about/page.tsx -> src/pages/about.tsx
app/blog/[slug]/page.tsx -> src/pages/blog/[slug].tsx Wrap app/layout.tsx content in src/pages/_layout.tsx.
- Convert state. Replace hooks:
// Next.js
const [n, setN] = useState(0);
// Krate
const [n, setN] = createSignal(0);
// read by calling: n() (not n)
- Fix attribute names.
className→class;htmlFor→for.
- Links & images. Replace
next/link/next/imageimports with the globals<Link href="…">/<Image src width height alt>.
- Data fetching. Replace
fetchin server components withcreateResourceor build-time reads; see Data Fetching.
- API routes. Move
app/api//route.tshandlers tosrc/api/.tsexportingGET/POST/etc. Prefer Go routes (src/api/*.go) for hot endpoints.
- Config. Translate
next.config.jstokrate.config.ts(redirects,rewrites,headers,images,env).
- Build & check.
krate build && krate check#Gradual adoption via React interop
React interop is always on. Krate automatically rewrites React hooks (useState, useEffect, useMemo, useReducer, useRef, useCallback, useContext, useId) and React.* member calls to signal-based equivalents during compilation, and auto-calls bare reads ({count} → count()), so files deeply tied to React hooks compile without config changes. This is a migration aid, not a full React runtime — see React Compatibility.
#What is intentionally different
- No
getServerSideProps/getStaticProps— use render modes (export const config = { ssr: true }) andcreateResource. - No React context; share state via module-level signals or props.
- Streaming uses
<Suspense>with region rendering (see Rendering).
#See also
Last updated: 2026-10-16
Contributors: Noinkin