diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..71332ce2 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,79 @@ +# @lazarv/react-server — Contributor Guide + +This is the monorepo for `@lazarv/react-server`, an open React Server Components runtime built on the Vite Environment API. + +## Monorepo Structure + +``` +packages/ + react-server/ # Core runtime (@lazarv/react-server) + rsc/ # RSC serialization (@lazarv/rsc) + create-react-server/ # Project scaffold CLI (@lazarv/create-react-server) +docs/ # Documentation site (react-server.dev), built with react-server itself +examples/ # 33+ example applications +test/ # Integration tests (Vitest + Playwright) +``` + +Package manager: **pnpm** (enforced via `preinstall` check). + +## Key Commands + +```sh +# Install dependencies +pnpm install + +# Run docs dev server +pnpm docs + +# Build docs +pnpm docs-build + +# Run all tests (from root) +pnpm test + +# Run tests from test/ directory +cd test +pnpm test-dev-base # Dev mode tests (excludes app tests) +pnpm test-dev-apps # Dev mode app tests +pnpm test-build-start # Build + start mode tests +pnpm test-dev # All dev mode tests + +# Format code +pnpm format # Uses oxfmt + +# Lint +pnpm lint # Uses oxlint +``` + +## Coding Conventions + +- **ESM only** — all packages use `"type": "module"` +- **No TypeScript in core packages** — pure JavaScript with `.d.ts` type definitions +- **JSX file extensions** — use `.jsx` for React components +- **Config/server files** — use `.mjs` extension +- **Commit messages** — conventional commits (`feat:`, `fix:`, `docs:`, `chore:`, `perf:`, `refactor:`, `test:`, `build:`, `ci:`) + - Format: `type(scope): subject` (e.g., `feat(router): add catch-all routes`) + - Imperative, present tense, no capitalization, no period at end + - Enforced by commitlint + +## Docs Site + +- Built with `@lazarv/react-server` itself (dogfooding) +- MDX pages in `docs/src/pages/en/(pages)/` +- Bilingual: English (`en/`) and Japanese (`ja/`) +- Deployed to Cloudflare +- All pages exported as `.md` for AI consumption +- Config: `docs/react-server.config.mjs` + +## Test Infrastructure + +- **Vitest** for test runner +- **Playwright (Chromium)** for browser-based integration tests +- Two configs: `vitest.config.mjs` (dev mode) and `vitest.config.build.mjs` (build+start mode) +- Test fixtures in `test/fixtures/` +- Test specs in `test/__test__/` + +## Package Exports + +The main `@lazarv/react-server` package has many subpath exports: +`/client`, `/server`, `/config`, `/router`, `/navigation`, `/error-boundary`, `/remote`, `/worker`, `/mcp`, `/cache`, and more. Check `packages/react-server/package.json` exports field for the full list. diff --git a/docs/src/pages/en/(pages)/integrations/claude-code.mdx b/docs/src/pages/en/(pages)/integrations/claude-code.mdx new file mode 100644 index 00000000..54220bdd --- /dev/null +++ b/docs/src/pages/en/(pages)/integrations/claude-code.mdx @@ -0,0 +1,102 @@ +--- +title: Claude Code +category: Integrations +order: 7 +--- + +import Link from "../../../../components/Link.jsx"; + +# Claude Code + +[Claude Code](https://docs.anthropic.com/en/docs/claude-code) is Anthropic's official CLI tool for AI-assisted coding. `@lazarv/react-server` provides an installable Claude Code skill that gives Claude deep knowledge of the runtime's APIs, conventions, and patterns — so you can build react-server applications using agentic coding. + + +## Install the skill + + +Install the skill into your project using `npx skills`: + +```sh +npx skills add lazarv/react-server +``` + +This installs the `react-server` skill from the repository's `skills/` directory into your project's `.claude/skills/` folder. Once installed, the `/react-server` slash command becomes available in Claude Code. + +To install it globally so it's available across all your projects: + +```sh +npx skills add lazarv/react-server --global +``` + + +## Usage + + +Start Claude Code in your project directory and use the `/react-server` slash command to give Claude the full context of the runtime. You can pass additional instructions as arguments: + +```sh +# General react-server context +/react-server + +# With specific instructions +/react-server add a new /api/users route that returns a list of users from the database + +# Scaffold a new feature +/react-server create a live component that streams stock prices +``` + +The skill loads all core patterns, file-system router conventions, use directives, import paths, and component patterns into Claude's context automatically. + + +## Using docs as context + + +Every page on this documentation site is also available as plain markdown. You can paste these URLs directly in a Claude Code conversation for detailed, up-to-date reference on specific features: + +| Topic | URL | +|---|---| +| Server Components | `https://react-server.dev/guide/server-components.md` | +| Client Components | `https://react-server.dev/guide/client-components.md` | +| Server Functions | `https://react-server.dev/guide/server-functions.md` | +| File Router | `https://react-server.dev/router/file-router.md` | +| Configuration | `https://react-server.dev/features/configuration.md` | +| Caching | `https://react-server.dev/features/caching.md` | +| HTTP | `https://react-server.dev/features/http.md` | +| Live Components | `https://react-server.dev/features/live-components.md` | +| Workers | `https://react-server.dev/features/workers.md` | +| MCP | `https://react-server.dev/features/mcp.md` | +| Error Handling | `https://react-server.dev/features/error-handling.md` | +| API Routes | `https://react-server.dev/router/api-routes.md` | +| Middlewares | `https://react-server.dev/router/middlewares.md` | +| Outlets | `https://react-server.dev/router/outlets.md` | +| CLI | `https://react-server.dev/features/cli.md` | + + +## What's included + + +The skill provides Claude Code with comprehensive knowledge of: + +- **Use directives** — `"use client"`, `"use server"`, `"use live"`, `"use worker"`, `"use cache"`, `"use dynamic"`, `"use static"` and their semantics including inline (lexically scoped) usage +- **File-system router** — page, layout, dynamic route, catch-all, outlet, middleware, API route, and MCP endpoint conventions +- **Import paths** — all `@lazarv/react-server/*` subpath exports and their key APIs +- **Component patterns** — server components, client components, server functions, live components, workers, and lexically scoped RSC with arbitrary server/client nesting +- **HTTP hooks** — `useUrl`, `usePathname`, `headers`, `cookie`, `redirect`, `rewrite`, `status`, `after`, and more +- **Caching** — response cache, in-memory cache, cache directive with TTL/tags/profiles, revalidation +- **Configuration** — `defineConfig`, extension configs, mode-specific configs, JSON schema, env variables +- **Navigation** — `Link`, `Refresh`, `ReactServerComponent`, programmatic navigation via `useClient` +- **Error handling** — `ErrorBoundary` component and file-router error/loading conventions +- **Deployment** — all 11 adapter targets (Vercel, Netlify, Cloudflare, AWS, Azure, Bun, Deno, Docker, Firebase, etc.) +- **Advanced features** — micro-frontends with `RemoteComponent`, MCP server with `createServer`/`createTool`/`createResource`/`createPrompt`, MDX support + + +## Updating the skill + + +To update to the latest version of the skill: + +```sh +npx skills add lazarv/react-server +``` + +The skill is maintained alongside the documentation and updated with each release. diff --git a/docs/src/pages/ja/(pages)/integrations/claude-code.mdx b/docs/src/pages/ja/(pages)/integrations/claude-code.mdx new file mode 100644 index 00000000..864b8745 --- /dev/null +++ b/docs/src/pages/ja/(pages)/integrations/claude-code.mdx @@ -0,0 +1,102 @@ +--- +title: Claude Code +category: Integrations +order: 7 +--- + +import Link from "../../../../components/Link.jsx"; + +# Claude Code + +[Claude Code](https://docs.anthropic.com/en/docs/claude-code)はAnthropicが提供するAIコーディング支援の公式CLIツールです。`@lazarv/react-server`はインストール可能なClaude Codeスキルを提供しており、ランタイムのAPI、規約、パターンに関する深い知識をClaudeに与えることで、エージェントコーディングによるreact-serverアプリケーションの構築を支援します。 + + +## スキルのインストール + + +`npx skills`を使用してプロジェクトにスキルをインストールします: + +```sh +npx skills add lazarv/react-server +``` + +これにより、リポジトリの`skills/`ディレクトリから`react-server`スキルがプロジェクトの`.claude/skills/`フォルダにインストールされます。インストール後、Claude Codeで`/react-server`スラッシュコマンドが利用可能になります。 + +すべてのプロジェクトで利用できるようにグローバルにインストールする場合: + +```sh +npx skills add lazarv/react-server --global +``` + + +## 使い方 + + +プロジェクトディレクトリでClaude Codeを起動し、`/react-server`スラッシュコマンドを使用してClaudeにランタイムの完全なコンテキストを提供します。引数として追加の指示を渡すことができます: + +```sh +# react-serverの一般的なコンテキスト +/react-server + +# 具体的な指示を付けて +/react-server データベースからユーザー一覧を返す /api/users ルートを追加して + +# 新機能のスキャフォールド +/react-server 株価をストリーミングするライブコンポーネントを作成して +``` + +スキルはすべてのコアパターン、ファイルシステムルーターの規約、useディレクティブ、インポートパス、コンポーネントパターンをClaudeのコンテキストに自動的に読み込みます。 + + +## ドキュメントをコンテキストとして使用 + + +このドキュメントサイトのすべてのページは、プレーンマークダウンとしても利用できます。特定の機能に関する詳細で最新のリファレンスとして、これらのURLをClaude Codeの会話に直接貼り付けることができます: + +| トピック | URL | +|---|---| +| サーバーコンポーネント | `https://react-server.dev/guide/server-components.md` | +| クライアントコンポーネント | `https://react-server.dev/guide/client-components.md` | +| サーバー関数 | `https://react-server.dev/guide/server-functions.md` | +| ファイルルーター | `https://react-server.dev/router/file-router.md` | +| 設定 | `https://react-server.dev/features/configuration.md` | +| キャッシュ | `https://react-server.dev/features/caching.md` | +| HTTP | `https://react-server.dev/features/http.md` | +| ライブコンポーネント | `https://react-server.dev/features/live-components.md` | +| ワーカー | `https://react-server.dev/features/workers.md` | +| MCP | `https://react-server.dev/features/mcp.md` | +| エラーハンドリング | `https://react-server.dev/features/error-handling.md` | +| APIルート | `https://react-server.dev/router/api-routes.md` | +| ミドルウェア | `https://react-server.dev/router/middlewares.md` | +| アウトレット | `https://react-server.dev/router/outlets.md` | +| CLI | `https://react-server.dev/features/cli.md` | + + +## 含まれる内容 + + +このスキルはClaude Codeに以下の包括的な知識を提供します: + +- **useディレクティブ** — `"use client"`、`"use server"`、`"use live"`、`"use worker"`、`"use cache"`、`"use dynamic"`、`"use static"`のセマンティクスとインライン(レキシカルスコープ)での使用方法 +- **ファイルシステムルーター** — ページ、レイアウト、動的ルート、キャッチオール、アウトレット、ミドルウェア、APIルート、MCPエンドポイントの規約 +- **インポートパス** — すべての`@lazarv/react-server/*`サブパスエクスポートとその主要API +- **コンポーネントパターン** — サーバーコンポーネント、クライアントコンポーネント、サーバー関数、ライブコンポーネント、ワーカー、およびサーバー/クライアントの任意のネストが可能なレキシカルスコープRSC +- **HTTPフック** — `useUrl`、`usePathname`、`headers`、`cookie`、`redirect`、`rewrite`、`status`、`after`など +- **キャッシュ** — レスポンスキャッシュ、インメモリキャッシュ、TTL/タグ/プロファイル付きキャッシュディレクティブ、再検証 +- **設定** — `defineConfig`、拡張設定、モード別設定、JSONスキーマ、環境変数 +- **ナビゲーション** — `Link`、`Refresh`、`ReactServerComponent`、`useClient`によるプログラムナビゲーション +- **エラーハンドリング** — `ErrorBoundary`コンポーネントとファイルルーターのerror/loading規約 +- **デプロイ** — 全11アダプターターゲット(Vercel、Netlify、Cloudflare、AWS、Azure、Bun、Deno、Docker、Firebaseなど) +- **高度な機能** — `RemoteComponent`によるマイクロフロントエンド、`createServer`/`createTool`/`createResource`/`createPrompt`によるMCPサーバー、MDXサポート + + +## スキルの更新 + + +最新バージョンのスキルに更新するには: + +```sh +npx skills add lazarv/react-server +``` + +スキルはドキュメントと同時にメンテナンスされ、各リリースで更新されます。 diff --git a/packages/react-server/config/index.mjs b/packages/react-server/config/index.mjs index b1aee939..af94ebe3 100644 --- a/packages/react-server/config/index.mjs +++ b/packages/react-server/config/index.mjs @@ -175,6 +175,9 @@ export async function loadConfig(initialConfig, options = {}) { config[root] ); + // Remove $schema (JSON Schema reference for IDE validation, not a runtime option) + delete config[CONFIG_ROOT].$schema; + for (const key of configKeys) { if (key === CONFIG_ROOT || key === root) continue; merge( diff --git a/packages/react-server/config/validate.mjs b/packages/react-server/config/validate.mjs index 656b95c6..650efc40 100644 --- a/packages/react-server/config/validate.mjs +++ b/packages/react-server/config/validate.mjs @@ -683,6 +683,9 @@ function validateObject(config, schema, prefix = "") { // Skip symbol keys (like CONFIG_ROOT, CONFIG_PARENT) if (typeof key === "symbol") continue; + // Skip $schema (JSON Schema reference for IDE validation) + if (key === "$schema") continue; + const path = prefix ? `${prefix}.${key}` : key; const validator = schema[key]; diff --git a/skills/react-server/SKILL.md b/skills/react-server/SKILL.md new file mode 100644 index 00000000..4419e060 --- /dev/null +++ b/skills/react-server/SKILL.md @@ -0,0 +1,475 @@ +--- +name: react-server +description: Build applications with @lazarv/react-server — a React Server Components runtime built on Vite. Covers use directives, file-system router, HTTP hooks, caching, live components, workers, MCP, deployment, and all core APIs. +--- + +You are working on a project that uses `@lazarv/react-server` — an open React Server Components runtime (not a framework). It is built on the Vite Environment API and supports Node.js, Bun, and Deno. + +Full documentation: https://react-server.dev +Any docs page as markdown: https://react-server.dev/{path}.md +JSON Schema for configuration: https://react-server.dev/schema.json +Examples: https://github.com/lazarv/react-server/tree/main/examples + +When you need more detail on a specific topic, fetch the relevant markdown page from the docs site. + +## CLI Commands + +```sh +# Development (with explicit entrypoint) +pnpm react-server ./App.jsx + +# Development (file-system router, no entrypoint needed) +pnpm react-server + +# Production build +pnpm react-server build [./App.jsx] + +# Start production server +pnpm react-server start + +# Useful flags +# --open Open browser on start +# --host 0.0.0.0 Listen on all interfaces +# --port 3001 Custom port +# --https Enable HTTPS +``` + +## Use Directives + +These directives go at the top of a file or inside a function body (lexically scoped RSC): + +- `"use client"` — Client component (enables React hooks, event handlers, browser APIs) +- `"use server"` — Server function (callable from client, receives FormData as first arg) +- `"use live"` — Live component (async generator that yields JSX, streams updates via WebSocket) +- `"use worker"` — Worker module (offloads to Worker Thread on server, Web Worker on client) +- `"use cache"` — Cached function with options: `"use cache; ttl=200; tags=todos"` or `"use cache; profile=todos"` or `"use cache: file; tags=todos"` +- `"use dynamic"` — Force dynamic rendering (opt out of static/prerender) +- `"use static"` — Force static rendering at build time + +## File-System Router Conventions + +When no entrypoint is passed to the CLI, the file-system router is used. Default root is `src/pages` (configurable via `root` in config). + +``` +src/pages/ +├── layout.jsx # Root layout (wraps all routes) +├── page.jsx # Index page (/) +├── about.jsx # /about (any .jsx/.tsx file is a page) +├── (group)/ # Route group (no URL segment) +│ └── page.jsx +├── users/ +│ ├── page.jsx # /users +│ ├── [id].page.jsx # /users/:id (dynamic segment) +│ └── [id]/ +│ └── posts.page.jsx # /users/:id/posts +├── docs/ +│ └── [...slug].page.jsx # /docs/* (catch-all, slug is string[]) +├── @sidebar/ # Parallel route / outlet named "sidebar" +│ └── page.jsx +├── loading.page.jsx # Loading fallback (Suspense boundary) +├── error.page.jsx # Error fallback (ErrorBoundary) +├── index.middleware.mjs # Middleware for this route segment +├── GET.posts.server.mjs # API route: GET /posts +└── mcp.server.mjs # MCP endpoint at /mcp +``` + +Key conventions: +- `page.jsx` or `index.jsx` — route page (index route) +- `layout.jsx` — wraps child routes with persistent layout +- `[param]` — dynamic route parameter (passed as prop) +- `[...slug]` — catch-all (param is `string[]`) +- `[[...slug]]` — optional catch-all +- `(name)` — route group / transparent segment (not in URL) +- `@name/` — parallel route outlet +- `*.middleware.{js,mjs,ts,mts}` — middleware +- `*.server.{js,mjs,ts,mts}` — API route handler +- `GET.*.server.mjs` / `POST.*.server.mjs` — HTTP method-specific API route +- `{filename.xml}.server.mjs` — escaped route segment for special characters + +## Imports Quick Reference + +```js +// Core hooks and utilities +import { + useHttpContext, + useUrl, + usePathname, + useSearchParams, + useRequest, + useResponse, + useFormData, + headers, + cookie, + setCookie, + deleteCookie, + status, + redirect, + rewrite, + after, + useCache, + useResponseCache, + withCache, + revalidate, + invalidate, + getRuntime, +} from "@lazarv/react-server"; + +// Configuration helper +import { defineConfig } from "@lazarv/react-server/config"; + +// Navigation (client-side) +import { Link, Refresh, ReactServerComponent } from "@lazarv/react-server/navigation"; +import { useClient } from "@lazarv/react-server/navigation"; +// useClient() returns { navigate, replace, prefetch } + +// Router utilities +import { useMatch } from "@lazarv/react-server/router"; + +// Error handling +import { ErrorBoundary } from "@lazarv/react-server/error-boundary"; + +// Client utilities +import { ClientOnly } from "@lazarv/react-server/client"; + +// Micro-frontends +import RemoteComponent from "@lazarv/react-server/remote"; + +// Workers +import { isWorker } from "@lazarv/react-server/worker"; + +// MCP (Model Context Protocol) +import { createServer, createTool, createResource, createPrompt } from "@lazarv/react-server/mcp"; +``` + +## Component Patterns + +### Server Component (default — no directive needed) + +```jsx +// Server components can be async and access backend resources directly +export default async function Page() { + const data = await db.query("SELECT * FROM posts"); + return ; +} +``` + +### Client Component + +```jsx +"use client"; + +import { useState } from "react"; + +export default function Counter() { + const [count, setCount] = useState(0); + return ; +} +``` + +### Server Function + +```jsx +// File-level directive +"use server"; + +export async function createPost(formData) { + const title = formData.get("title"); + await db.insert({ title }); +} +``` + +```jsx +// Or inline in a server component +export default function Page() { + async function handleSubmit(formData) { + "use server"; + await db.insert({ title: formData.get("title") }); + } + return ( +
+ + +
+ ); +} +``` + +### Live Component (real-time streaming) + +```jsx +"use live"; + +export default async function* LiveClock() { + while (true) { + yield
{new Date().toLocaleTimeString()}
; + await new Promise(r => setTimeout(r, 1000)); + } +} +``` + +### Worker Function + +```jsx +"use worker"; + +// All exports must be async functions +export async function fibonacci(n) { + if (n <= 1) return n; + return fibonacci(n - 1) + fibonacci(n - 2); +} +``` + +### Lexically Scoped RSC (inline directives) + +```jsx +// No file-level directive — this is a server component +export default async function Page() { + const data = await fetchData(); + + // Inline client component — extracted at build time, no separate file needed + function InteractiveList({ items }) { + "use client"; + const [filter, setFilter] = useState(""); + return ( + <> + setFilter(e.target.value)} /> + + + ); + } + + return ; +} +``` + +Server → Client → Server nesting is also supported: + +```jsx +async function getData() { + "use server"; + + function Display({ value }) { + "use client"; + const [show, setShow] = useState(false); + return ; + } + + const value = await db.getSecret(); + return ; +} +``` + +## HTTP Hooks + +Available in server components, middlewares, and API routes: + +```jsx +import { + useUrl, // URL object + usePathname, // string + useSearchParams, // URLSearchParams + useRequest, // Request object + useResponse, // Response object + useFormData, // FormData (POST requests) + useHttpContext, // full context object + headers, // headers(name?) to read, headers({ key: value }) to set + cookie, // cookie(name?) to read, cookie(name, value, opts) to set + setCookie, // setCookie(name, value, opts) + deleteCookie, // deleteCookie(name) + status, // status(code, statusText?) + redirect, // redirect(url, statusCode?) + rewrite, // rewrite(url) + after, // after(callback) — runs after response is sent +} from "@lazarv/react-server"; +``` + +## Caching + +```jsx +import { useResponseCache, useCache, withCache, revalidate, invalidate } from "@lazarv/react-server"; + +// Cache entire HTTP response for 30 seconds +useResponseCache(30_000); + +// HOC form +export default withCache(async function Page() { ... }, 30_000); + +// In-memory cache with compound key +const data = await useCache( + ["posts", category], + () => db.query("SELECT * FROM posts WHERE category = ?", [category]), + 60_000 +); + +// Invalidate +revalidate(["posts", category]); +``` + +Using the cache directive: +```jsx +"use cache; ttl=30000; tags=posts"; + +export async function getPosts() { + return db.query("SELECT * FROM posts"); +} + +// Invalidate by tag +import { invalidate } from "@lazarv/react-server"; +await invalidate(getPosts); +``` + +## Configuration + +```js +// react-server.config.mjs +import { defineConfig } from "@lazarv/react-server/config"; + +export default defineConfig({ + root: "src/pages", // File router root directory + public: "public", // Static assets directory + port: 3000, // Server port + adapter: "vercel", // Deployment adapter + // adapter: ["cloudflare", { serverlessFunctions: false }], + mdx: { // MDX support + remarkPlugins: [], + rehypePlugins: [], + components: "./src/mdx-components.jsx", + }, + cache: { + profiles: { + short: { ttl: 60_000 }, + }, + }, + telemetry: { // OpenTelemetry + enabled: true, + serviceName: "my-app", + }, +}); +``` + +JSON config with schema validation: +```json +{ + "$schema": "https://react-server.dev/schema.json", + "port": 3000, + "adapter": "vercel" +} +``` + +Extension configs are merged: `+tailwind.config.mjs`, `+auth.config.mjs`, etc. +Mode-specific: `.production.config.mjs`, `.development.config.mjs`, `.build.config.mjs`. +Env variables: `VITE_*` and `REACT_SERVER_*` prefixed vars are exposed via `import.meta.env`. + +## Navigation + +```jsx +import { Link, Refresh, ReactServerComponent } from "@lazarv/react-server/navigation"; + +// Client-side navigation +About + +// Re-render current route +Reload + +// Render an outlet +{sidebar} + +// Programmatic navigation (client component only) +import { useClient } from "@lazarv/react-server/navigation"; +const { navigate, replace, prefetch } = useClient(); +``` + +## Error Handling + +```jsx +import { ErrorBoundary } from "@lazarv/react-server/error-boundary"; + +Loading...

} + component={({ error, resetErrorBoundary }) => ( +
+

{error.message}

+ +
+ )} +> + +
+``` + +File router conventions: `error.page.jsx` for error boundaries, `loading.page.jsx` for Suspense fallbacks. + +## Middleware + +```js +// index.middleware.mjs +import { redirect, rewrite, usePathname, useMatch } from "@lazarv/react-server"; + +export default function Middleware() { + if (useMatch("/old-path")) { + redirect("/new-path"); + } +} +``` + +## API Routes + +```js +// GET.posts.server.mjs +import { useSearchParams } from "@lazarv/react-server"; + +export default function GetPosts() { + const params = useSearchParams(); + return Response.json({ posts: [], page: params.get("page") }); +} +``` + +## Deployment Adapters + +Available adapters: `vercel`, `netlify`, `cloudflare`, `aws`, `azure`, `azure-swa`, `bun`, `deno`, `docker`, `firebase`, `singlefile`. + +```js +// react-server.config.mjs +export default { adapter: "vercel" }; +// Or with options: +export default { adapter: ["cloudflare", { serverlessFunctions: false }] }; +``` + +## Micro-Frontends + +```jsx +import RemoteComponent from "@lazarv/react-server/remote"; + +export default function App() { + return ( + + ); +} +``` + +## MCP (Model Context Protocol) + +```js +// mcp.server.mjs +import { createServer, createTool } from "@lazarv/react-server/mcp"; +import { z } from "zod"; + +export default createServer({ + tools: { + search: createTool({ + id: "search", + title: "Search", + description: "Search the database", + inputSchema: { query: z.string() }, + async handler({ query }) { + return await db.search(query); + }, + }), + }, +}); +```