Pages, APIs, layouts, and 404s live in the filesystem.
app/ handles SSR pages. api/ returns typed JSON. Layout and 404 handling stay in the same primitive layer instead of being bolted on later.
merjs v0.2.5
File-based routing, SSR, type-safe APIs, hot reload, Cloudflare Workers deploys, and client-side WASM. Same developer shape, but much faster and much leaner: 115,093 req/s locally and just 4.8 MB RAM under CI load.
< 5 mscold start
115kreq/s
4.8 MBRAM
260 KBbinary
At a glance
The workflow feels familiar. The runtime profile does not. merjs keeps file routing, layouts, streaming, and typed APIs, then drops the Node-first assumptions beneath them.
native runtimeNo Node process and no package-manager boot tax.
edge-readySame app model can target Cloudflare Workers as a single WASM bundle.
bench board
The numbers are the story: faster startup, higher throughput, lower latency, lower RAM, smaller binary.
Cold startApple M-series local runs
Homepage throughputwrk -t4 -c50
Average latencylower is better
RAM under loadGitHub Actions benchmark
Binary footprintrelease build
Framework surface
app/ handles SSR pages. api/ returns typed JSON. Layout and 404 handling stay in the same primitive layer instead of being bolted on later.
merjs can render a full page, stream chunks, or split layout shell from body without dragging React in just to unlock the pattern.
Zig structs, comptime validation, and std.json remove the extra schema layer and the usual drift between code and transport.
Compile client logic directly to WASM, keep one language end-to-end, and avoid a second JS build chain just to make the browser interactive.
The in-process file watcher pushes changes over /_mer/events SSE. No JS bundler in the loop, no devtools agent.
Mark a page prerender = true and zig build prod writes static HTML to dist/. Same routes, no server.
app/users/[id].zig becomes /users/:id. Path params land on the request struct, typed and ready.
Signed and encrypted by default, configurable per-app, and zero external services to stand up. No Redis, no JWT library, no sidecar.
public/ ships at the root.Hits disk once on first request, then served from in-memory cache. MIME types and ETags handled by the framework.
Scans templates at codegen time and emits only the classes you actually used. Supports hover:, md:, dark:, and arbitrary w-[42px] values — no Tailwind, no PostCSS.
Telemetry lives in the framework, not a sidecar. Drop in your sink (stdout, OTLP, Sentry) without redoing the request path.
The same Zig source compiles to a native binary or a wasm32 edge bundle. Ship to Cloudflare Workers, Vercel Functions, Render web services, Fly machines, Railway, or any Linux host — no rewrites, no provider-specific shape.
Philosophy
The server is a native binary. The client is WASM. The runtime is the platform you are already deploying to.
Validation, request parsing, and serialization stay in Zig instead of spreading across schema files and runtime adapters.
Keep the good parts: routing, layouts, reloads, edge deploys. Remove the layers that only existed because JavaScript had to be everywhere.
Current release
The release page goes deeper into memory reuse, caching, shell-first paint, fetch strategy, and the concrete 4.8 MB vs 71.7 MB RAM story.