UNPKG

@rsc-kit/mcp

Version:

An MCP server over what an rsc-kit build decided: the routes, why each one is static or not, and what it costs the browser.

124 lines (101 loc) • 4.55 kB
# Introduction > React Server Components as a Vite plugin, deployed wherever you like. `rsc-kit` is a Vite plugin that gives you React Server Components. You write pages, layouts and server actions the way you would in the Next.js App Router; it renders them, streams the HTML, and turns links into navigations that replace only the part of the page that changed. It brings no build system of its own — it is a Vite plugin — and it does not write a server for you either. [Nitro](https://nitro.build) builds one around your route tree, so where an app runs is a preset: Bun, Node, a Cloudflare Worker, Vercel, Netlify, Deno. ## What an app looks like ```text src/app/ layout.tsx the document — <html>, <head>, <body> loading.tsx Suspense fallback for everything below page.tsx GET / posts/ [slug]/ page.tsx GET /posts/:slug @modal/ default.tsx a parallel slot, empty until something fills it ``` Nothing registers those files. The plugin reads the directory at build time and generates the entry that knows about them. ```tsx title="src/app/posts/[slug]/page.tsx" import { findPost } from '../../../data' export default async function PostPage({ params }: { params: Promise<{ slug: string }> }) { const { slug } = await params const post = await findPost(slug) if (!post) return <h1>No such post</h1> return ( <article> <h1>{post.title}</h1> <p>{post.body}</p> </article> ) } ``` A server component is an ordinary async function. It imports its data module directly, and neither the module nor its secrets reach the browser. ## What you get <CardGrid> <Card title="Streaming, not waterfalls" icon="ph:waves"> The shell paints before the data resolves. Suspense boundaries fill in as they finish, in whatever order they finish. </Card> <Card title="Navigations that keep the page" icon="ph:arrows-left-right"> A navigation sends the layout chain it already has, and the server answers with only the part that changed. Scroll, focus and half-typed forms survive. </Card> <Card title="Parallel routes and interception" icon="ph:frame-corners"> `@slot` directories render alongside the page. `(.)folder` opens a route as a modal over the page you were on, and as a real page on refresh. </Card> <Card title="Server actions" icon="ph:lightning"> `"use server"` makes an async function callable from a client component. The body never ships; the call becomes one POST. </Card> <Card title="Queries, without an endpoint" icon="ph:magnifying-glass"> `query()` marks a read. It travels as a GET, so it can be cached and prefetched — and reads that happen together leave as one request. </Card> <Card title="Frozen where it can be" icon="ph:snowflake"> Pages that ask for nothing dynamic are rendered at build time. Pages that do get their shell frozen and their data streamed. </Card> <Card title="An export target" icon="ph:folder-open"> The same app can build to a directory of files and be served by anything — including a CDN with no origin at all. </Card> </CardGrid> ## Where it runs You do not write a server. [Nitro](https://nitro.build) builds one from your route tree, and where it runs is one line in your Vite config: ```ts title="vite.config.ts" nitro({ preset: 'bun' }) ``` Swap the preset for `node`, `cloudflare_module`, `vercel`, `netlify` or `deno` and the same app deploys there instead. The build produces a `.output` directory; nothing else changes. With a backend behind it — Laravel, Go, anything answering one endpoint — the app is a **BAP**, [Backend-Answered Pages](/hosts/backend-answered-pages): the page is rendered in front of the backend rather than by it. ## What it is not <Aside type="note" title="No data layer, no CSS pipeline, no dev server of its own"> The build runs your project's Vite config, so Tailwind, PostCSS and the rest are configured the way they are in any Vite app. Data access is an import. There is no `getServerSideProps` equivalent, and no request context to learn. </Aside> ## Where to go next <CardGrid> <Card title="Getting started" icon="ph:play"> [Build and deploy your first app →](/getting-started) </Card> <Card title="Routing" icon="ph:tree-structure"> [Pages, layouts, slots and navigation →](/guides/routing) </Card> <Card title="How it works" icon="ph:gear"> [What happens between a request and a page →](/reference/how-it-works) </Card> </CardGrid>