# How shadcn/ui Supports React Server Components (RSC) and Server-Side Rendering (SSR)

> Discover how shadcn/ui seamlessly integrates with React Server Components and SSR using a simple rsc flag and router registration for efficient server-side rendering.

- Repository: [shadcn-ui/ui](https://github.com/shadcn-ui/ui)
- Tags: deep-dive
- Published: 2026-02-26

---

**shadcn/ui enables React Server Components and SSR through a single `rsc` configuration flag that controls source-code transformation and a generated router registration that activates server-side rendering.**

The shadcn/ui toolkit treats server rendering as a first-class concern, allowing developers to opt into React Server Components during project initialization and automatically handling the `"use client"` directives that determine component boundaries. This architecture ensures that components can be rendered entirely on the server where appropriate, while still supporting client-side interactivity when needed.

## The RSC Configuration Flag

shadcn/ui introduces RSC support at the schema level through a boolean `rsc` property defined in [`packages/shadcn/src/schema.ts`](https://github.com/shadcn-ui/ui/blob/main/packages/shadcn/src/schema.ts). This property defaults to `false` but can be enabled during project setup:

```typescript
// packages/shadcn/src/schema.ts
export const rawConfigSchema = z.object({
  // ... other fields
  rsc: z.coerce.boolean().default(false),
})

```

When you run `npx shadcn-ui@latest init`, the CLI prompts for RSC support and persists the answer in [`components.json`](https://github.com/shadcn-ui/ui/blob/main/components.json):

```bash
? Are you using React Server Components? (yes/no)  (Y/n) y

```

This configuration is subsequently loaded by `getConfig` in [`packages/shadcn/src/utils/get-config.ts`](https://github.com/shadcn-ui/ui/blob/main/packages/shadcn/src/utils/get-config.ts), making `config.rsc` available throughout the CLI's transformation pipeline.

## Source Code Transformation for RSC

The core mechanism for RSC support resides in [`packages/shadcn/src/utils/transformers/transform-rsc.ts`](https://github.com/shadcn-ui/ui/blob/main/packages/shadcn/src/utils/transformers/transform-rsc.ts). This transformer conditionally removes `"use client"` directives based on the `rsc` configuration:

```typescript
// packages/shadcn/src/utils/transformers/transform-rsc.ts
export const transformRsc: Transformer = async ({ sourceFile, config }) => {
  // If RSC is enabled, preserve the directive (component stays client-side capable)
  if (config.rsc) {
    return sourceFile
  }

  // Otherwise, strip "use client" to make the component server-compatible
  const first = sourceFile.getFirstChildByKind(SyntaxKind.ExpressionStatement)
  if (first && /^["']use client["']$/.test(first.getText())) {
    first.remove()
  }
  return sourceFile
}

```

When `config.rsc` is `true`, the transformer becomes a no-op, preserving any `"use client"` directives that mark interactive components. When `false`, it strips these directives, effectively converting components to server-compatible modules.

This transformer integrates into the file update pipeline in [`packages/shadcn/src/utils/updaters/update-files.ts`](https://github.com/shadcn-ui/ui/blob/main/packages/shadcn/src/utils/updaters/update-files.ts):

```typescript
// packages/shadcn/src/utils/updaters/update-files.ts
const content = await transform(
  { filename: file.path, raw: file.content, config },
  [
    transformImport,
    transformRsc,  // RSC handling
    transformCssVars,
    // ... other transformers
  ]
)

```

## SSR Support in the TanStack Router

For applications using the `start-app` template, shadcn/ui enables SSR through TanStack Router's registration system. The generated route tree in [`templates/start-app/src/routeTree.gen.ts`](https://github.com/shadcn-ui/ui/blob/main/templates/start-app/src/routeTree.gen.ts) declares SSR capability:

```typescript
// templates/start-app/src/routeTree.gen.ts
declare module '@tanstack/react-start' {
  interface Register {
    ssr: true  // Enables server-side rendering
    router: Awaited<ReturnType<typeof getRouter>>
  }
}

```

This `ssr: true` declaration instructs TanStack's runtime to pre-render routes on the server, delivering fully rendered HTML to the client before hydration occurs.

## How RSC and SSR Work Together in shadcn/ui

While RSC and SSR are distinct concepts, shadcn/ui coordinates them through configuration:

| Feature | Configuration | Implementation | Effect |
|---------|--------------|----------------|---------|
| **RSC** | `rsc: true` in [`components.json`](https://github.com/shadcn-ui/ui/blob/main/components.json) | [`transform-rsc.ts`](https://github.com/shadcn-ui/ui/blob/main/transform-rsc.ts) preserves `"use client"` | Components can run on server; client components marked explicitly |
| **SSR** | `ssr: true` in route registration | [`routeTree.gen.ts`](https://github.com/shadcn-ui/ui/blob/main/routeTree.gen.ts) interface | TanStack Router pre-renders pages on server |

The documentation site itself demonstrates this pattern in [`apps/v4/lib/rehype.ts`](https://github.com/shadcn-ui/ui/blob/main/apps/v4/lib/rehype.ts), where a display configuration explicitly sets `rsc: true` for component previews:

```typescript
// apps/v4/lib/rehype.ts
const buildDisplayConfig = (styleName: string) => ({
  $schema: "https://ui.shadcn.com/schema.json",
  style: styleName,
  rsc: true,  // Preview as server component
  tsx: true,
  // ...
})

```

## Summary

- **Configuration-driven**: The `rsc` boolean in [`components.json`](https://github.com/shadcn-ui/ui/blob/main/components.json) (defined in [`packages/shadcn/src/schema.ts`](https://github.com/shadcn-ui/ui/blob/main/packages/shadcn/src/schema.ts)) determines whether components are treated as React Server Components.
- **Automatic transformation**: The `transformRsc` function in [`packages/shadcn/src/utils/transformers/transform-rsc.ts`](https://github.com/shadcn-ui/ui/blob/main/packages/shadcn/src/utils/transformers/transform-rsc.ts) conditionally strips `"use client"` directives based on the RSC configuration.
- **Pipeline integration**: File updates in [`packages/shadcn/src/utils/updaters/update-files.ts`](https://github.com/shadcn-ui/ui/blob/main/packages/shadcn/src/utils/updaters/update-files.ts) execute the RSC transformer alongside other code transformations.
- **SSR registration**: The `start-app` template enables server-side rendering via `ssr: true` in [`templates/start-app/src/routeTree.gen.ts`](https://github.com/shadcn-ui/ui/blob/main/templates/start-app/src/routeTree.gen.ts) for TanStack Router applications.

## Frequently Asked Questions

### What happens if I set `rsc: false` in my shadcn/ui configuration?

When `rsc` is set to `false`, the CLI's transformer ([`transform-rsc.ts`](https://github.com/shadcn-ui/ui/blob/main/transform-rsc.ts)) automatically removes all `"use client"` directives from component files during installation. This converts the components into standard server-compatible modules, though you lose the ability to use client-side React features (like `useState` or `useEffect`) in those specific files unless you manually add the directive back.

### How does shadcn/ui detect if my project supports React Server Components?

The CLI includes project detection logic in [`packages/shadcn/src/utils/get-project-info.ts`](https://github.com/shadcn-ui/ui/blob/main/packages/shadcn/src/utils/get-project-info.ts) that checks for the presence of a Next.js app directory. If the app directory exists (indicating Next.js 13+), the CLI sets `isRSC` to true, which can influence default recommendations during initialization, though the explicit `rsc` flag in [`components.json`](https://github.com/shadcn-ui/ui/blob/main/components.json) remains the authoritative configuration.

### Can I use shadcn/ui with SSR frameworks other than Next.js?

Yes. While the RSC configuration works universally by controlling `"use client"` directives, the explicit SSR registration shown in [`templates/start-app/src/routeTree.gen.ts`](https://github.com/shadcn-ui/ui/blob/main/templates/start-app/src/routeTree.gen.ts) demonstrates TanStack Router integration. For other frameworks (Remix, Astro, etc.), the `rsc` flag still ensures components are generated without client directives when server rendering is desired, though you must configure the framework's own SSR pipeline separately.

### What is the difference between the `rsc` flag and the `ssr` flag in shadcn/ui?

The `rsc` flag controls **component-level** behavior—specifically whether `"use client"` directives are preserved or removed from component files, determining if they can run as React Server Components. The `ssr` flag appears in the TanStack Router template and controls **application-level** server-side rendering, instructing the router to pre-render pages on the server before sending HTML to the client.