README.md

October 26, 2025 · View on GitHub

@lazarv/react-server

Run React anywhere

Build React apps with server-side rendering the way it should be — write a single file, run one command, and everything just works. Powered by Vite with React included out of the box.

Documentation · Getting Started · Examples


Get Started in Seconds

npx @lazarv/create-react-server

Or go fully manual — one dependency, one file, one command:

pnpm add @lazarv/react-server
// App.jsx
export default function App() {
  return <h1>Hello World!</h1>;
}
pnpm react-server ./App.jsx

That's it. No config files, no boilerplate, no React installation. Your app is running with full SSR.

Want to try it without installing anything? npx @lazarv/react-server ./App.jsx works too.


Why @lazarv/react-server?

Most React frameworks require significant setup before you write your first component. @lazarv/react-server takes a different approach — it's as simple as running a script with node, but for React. Start with a single file and scale to a full-featured application with file-system routing, caching, static generation, and multi-runtime deployment as your needs grow.

Built on Vite for instant HMR. Ships with its own React, so your project stays lean. Supports Node.js, Bun, and Deno. Deploys to Vercel, Netlify, Cloudflare, and more with built-in adapters.


Features at a Glance

React Server ComponentsAsync server components with streaming SSR — the default rendering model
Client Components"use client" for interactive components with full hook support
Server Functions"use server" with progressive enhancement and form actions
File-System RouterPages, layouts, outlets, API routes, middlewares, error boundaries, loading states
Client NavigationSPA-like navigation with prefetching, rollback, and outlet-scoped updates
CachingResponse cache, in-memory cache, "use cache" directive, Unstorage providers
Static ExportFull static generation with dynamic route params and compression
Partial Pre-Rendering"use dynamic" / "use static" for mixed static + runtime rendering
Live Components"use live" async generators streamed over WebSocket in real-time
Workers"use worker" for Worker Threads (server) and Web Workers (client) with HMR
Micro-FrontendsCompose remote RSC applications with streaming and shadow DOM isolation
MCP ServerModel Context Protocol tools, resources, and prompts as HTTP endpoints
Markdown & MDX.md/.mdx as pages with remark/rehype plugins and custom components
Middleware ModeEmbed into Express, NestJS, or any connect-compatible server
Cluster ModeScale across all CPU cores in production
Multi-RuntimeNode.js >= 20.10, Bun >= 1.2.9, Deno >= 2.0
Deploy AnywhereBuilt-in adapters for Vercel, Netlify, Cloudflare, Bun, and Deno

Server Components

Server components are the default. They render on the server, support async/await, and their source code never reaches the client.

export default async function App() {
  const data = await fetch("https://api.example.com/data").then((r) => r.json());
  return <div>{data.message}</div>;
}

Client Components

Add "use client" to enable interactivity. Components are server-rendered, then hydrated on the client with full React hook and event handler support.

"use client";
import { useState } from "react";

export default function Counter() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}

Server Functions

"use server" turns any async function into a server-side RPC endpoint. Works as form actions with progressive enhancement — no JavaScript required for basic form submissions.

async function addTodo(formData) {
  "use server";
  await db.todos.create({ title: formData.get("title") });
}

export default function TodoForm() {
  return (
    <form action={addTodo}>
      <input name="title" />
      <button type="submit">Add</button>
    </form>
  );
}

File-System Router

Omit the entrypoint and the runtime automatically routes based on your file structure. Every convention you'd expect — and more:

app/
├── layout.jsx            # Root layout
├── page.jsx              # / (index)
├── about.jsx             # /about
├── posts/
│   ├── page.jsx          # /posts
│   ├── [id].jsx          # /posts/:id (dynamic)
│   └── [...slug].jsx     # /posts/* (catch-all)
├── (auth)/
│   └── login.jsx         # /login (grouped, no URL segment)
├── @sidebar/
│   └── page.jsx          # Parallel outlet
├── loading.jsx           # Suspense loading fallback
├── error.jsx             # Error boundary
├── (i18n).middleware.mjs  # Middleware
└── GET.api.server.mjs    # GET /api (REST endpoint)

Configure routing in react-server.config.json:

{
  "root": "app",
  "page": { "include": ["**/page.tsx"] },
  "layout": { "include": ["**/layout.tsx"] }
}

Typed routes are auto-generated — include .react-server/**/*.ts in your tsconfig.json for full type safety.

Client-Side Navigation

SPA-like transitions with Link, Form, Refresh, and ReactServerComponent. Supports prefetching, error rollback, and outlet-scoped rendering.

import { Link } from "@lazarv/react-server/navigation";

<Link to="/about" prefetch>About</Link>

Programmatic navigation via useClient():

import { useClient } from "@lazarv/react-server/client";

const { navigate, prefetch, refresh } = useClient();

Caching & Revalidation

Multi-layered caching built in at every level:

// Response-level
useResponseCache(30000);

// Data-level with compound keys
const data = await useCache(["posts", id], () => fetchPost(id), 60000);

// Declarative with the "use cache" directive
"use cache; ttl=60; tags=posts";

Invalidate on demand with revalidate() and invalidate(). Cache providers are built on Unstorage — use memory, request, local, session, or plug in any custom driver.

Live Components

Real-time server-to-client streaming with async generators over WebSocket. Each component instance gets its own server-side execution context.

"use live";

export default async function* StockPrice({ symbol }) {
  while (true) {
    const price = await getPrice(symbol);
    yield <span>${price}</span>;
    await new Promise((r) => setTimeout(r, 1000));
  }
}

Partial Pre-Rendering

Mix static and dynamic content at the component level. Static shells are pre-rendered at build time; dynamic parts stream in at runtime.

"use dynamic";

export default async function LiveFeed() {
  const items = await fetchLatest();
  return <ul>{items.map((i) => <li key={i.id}>{i.title}</li>)}</ul>;
}

Workers

Offload heavy computation to background threads with "use worker". Runs in Node.js Worker Threads on the server and Web Workers in the browser. Arguments and return values are serialized via the RSC Flight protocol, so you can return React elements directly. HMR is fully supported.

"use worker";

export async function analyze(data) {
  return heavyComputation(data);
}

Micro-Frontends

Compose independently deployed React Server Component applications. Supports streaming, isolate for shadow DOM encapsulation, shared dependency import maps, and static export.

import { RemoteComponent } from "@lazarv/react-server/remote";

<RemoteComponent src="https://other-app.example.com/widget" defer />

MCP Server (Experimental)

Build Model Context Protocol servers with tools, resources, and prompts exposed as streaming HTTP endpoints.

import { createServer, createTool } from "@lazarv/react-server/mcp";
import { z } from "zod";

const echo = createTool("echo", "Echoes input", { message: z.string() }, ({ message }) => message);
export default createServer({ tools: [echo] });

CLI

react-server [entrypoint]         # Development server
react-server build [entrypoint]   # Production build
react-server start                # Start production server

Key flags: --open, --port, --https, --export, --deploy, --edge, --compression, --adapter <name>, --eval, --sourcemap, --trust-proxy, --build

Configuration

Auto-detected from react-server.config.{js,mjs,ts,mts,json}. Supports environment-specific variants (.production.config.*, .development.config.*), extension configs (+*.config.*), and runtime-only configs (.runtime.config.*). Your vite.config.* is merged automatically — all Vite plugins work out of the box.

// react-server.config.mjs
export default {
  root: "app",
  public: "public",
  cluster: 4,
  prerender: { timeout: 5000 },
  cache: {
    profiles: { default: { ttl: 60000 } },
  },
};

Middleware Mode

Embed into any existing Node.js server:

import { reactServer } from "@lazarv/react-server/dev"; // or /node for production
const { middlewares } = await reactServer();
app.use(middlewares);

Deployment

One command to build and deploy with built-in platform adapters:

react-server build --deploy
PlatformConfiguration
Vercel{ adapter: "vercel" }
Netlify{ adapter: "netlify" }
Cloudflare{ adapter: "cloudflare" }
BunAuto-detected
DenoAuto-detected

Custom adapters can be built with createAdapter from @lazarv/react-server/adapters/core. Cluster mode scales across all CPU cores with REACT_SERVER_CLUSTER=8 or { cluster: 8 } in config.


Examples

Explore the examples to see @lazarv/react-server in action:

git clone https://github.com/lazarv/react-server.git
cd react-server && pnpm install
ExampleCommand
Hello Worldpnpm --filter ./examples/hello-world dev
Todo Apppnpm --filter ./examples/todo dev --open
Photospnpm --filter ./examples/photos dev --open
Pokemonpnpm --filter ./examples/pokemon dev --open
File Routerpnpm --filter ./examples/file-router dev --open
File Uploadpnpm --filter ./examples/file-upload dev --open
SPApnpm --filter ./examples/spa dev --open
SPA Routerpnpm --filter ./examples/spa-router dev --open
React Routerpnpm --filter ./examples/react-router dev --open
TanStack Routerpnpm --filter ./examples/tanstack-router dev --open
React Querypnpm --filter ./examples/react-query dev --open
Mantine UIpnpm --filter ./examples/mantine dev --open
Material UIpnpm --filter ./examples/mui dev --open
Chakra UIpnpm --filter ./examples/chakra-ui dev --open
shadcn/uipnpm --filter ./examples/shadcn dev --open
Expresspnpm --filter ./examples/express dev
NestJSpnpm --filter ./examples/nestjs start:dev
Bunpnpm --filter ./examples/bun dev
Denopnpm --filter ./examples/deno dev
Partial Pre-Renderingpnpm --filter ./examples/ppr dev --open
Micro-Frontendspnpm --filter ./examples/remote dev
MCP Serverpnpm --filter ./examples/mcp dev
Workerspnpm --filter ./examples/use-worker dev --open
Live Monitorpnpm --filter ./examples/monitor dev --open
Session Cookiespnpm --filter ./examples/session-cookie dev --open
Environment Variablespnpm --filter ./examples/env dev --open
React Markdownpnpm --filter ./examples/react-markdown dev --open
React Modalpnpm --filter ./examples/react-modal dev --open
React Syntax Highlighterpnpm --filter ./examples/react-syntax-highlighter dev --open
Module Resolutionpnpm --filter ./examples/module-resolution dev --open

Contributing

Contributions are welcome! Check out the contributing guide and the code of conduct.

License

MIT