# Installation

Install editable component source and the shared styles once.

## Requirements

Use React 19, TypeScript, Tailwind CSS 4, and an `@/*` alias pointing to `src/*`. Follow the complete [Next.js](/docs/installation/nextjs/) or [Vite](/docs/installation/vite/) path for framework configuration. Your coding agent can do this setup and install the skill: send it the [agent prompt](/docs/#set-up-with-your-agent) from Getting started.

## Create components.json

First complete the **Prepare the application** section for [Next.js](/docs/installation/nextjs/) or [Vite](/docs/installation/vite/). Run commands from the application directory.

Write `components.json` yourself instead of running `shadcn init`. It writes a shadcn theme into your global CSS that replaces the kit’s colors, borders and radii, and it installs a second Button and packages the kit does not use. This is the complete file for Next.js:

```json title="components.json"
{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "new-york",
  "rsc": true,
  "tsx": true,
  "tailwind": {
    "config": "",
    "css": "src/app/globals.css",
    "baseColor": "neutral",
    "cssVariables": true,
    "prefix": ""
  },
  "iconLibrary": "lucide",
  "aliases": {
    "components": "@/components",
    "ui": "@/components/ui",
    "lib": "@/lib",
    "hooks": "@/hooks",
    "utils": "@/siteplane/system/utils/cn"
  },
  "registries": {
    "@siteplane": "https://ui.siteplane.io/registry/{name}.json"
  }
}
```

For Vite, `rsc` is `false` and `tailwind.css` is `src/index.css`; the [Vite guide](/docs/installation/vite/#create-componentsjson) shows the complete file. Keep `tailwind.config` empty for Tailwind 4. The aliases must match the TypeScript and bundler configuration. Siteplane UI’s registry declares explicit targets under `src/siteplane`, so changing `aliases.ui` does not relocate its source; keep the documented `src` layout and `@/*` alias.

If your application already uses shadcn, keep its `components.json` and add the Siteplane UI registry to `registries`, next to any entries already there. Siteplane UI’s installed source does not depend on the `style` or `aliases.utils` values it holds.

```json title="components.json"
{
  "registries": {
    "@siteplane": "https://ui.siteplane.io/registry/{name}.json"
  }
}
```

This address uses the documentation site you are reading. Components and their dependencies are available from its registry without an account.

## Add components

```bash
pnpm dlx shadcn@4.18.0 add @siteplane/button @siteplane/input @siteplane/dialog
```

With npm, use `npx shadcn@4.18.0 add @siteplane/button @siteplane/input @siteplane/dialog`. Component pages also let you choose and copy either command.

The registry installs required source and package dependencies transitively under `src/siteplane`. Field is included with Input: install `@siteplane/input`, then import from `@/siteplane/components/field`. Shared base styles, action icons, and locale support are dependencies rather than extra catalog pages.

## Load styles and typography

In a new application, replace the contents of the global CSS with these two lines. The starter styles of `create-next-app` and `create-vite` set their own colors and fonts, which would override the kit’s.

```css title="src/app/globals.css (Next.js)"
@import "../siteplane/system/styles/base.css";
@source "..";
```

For Vite’s `src/index.css`, use `@import "./siteplane/system/styles/base.css";` and `@source ".";`. Import the global CSS once from the application entry.

The kit stylesheet imports Tailwind itself, along with the shared tokens, recipes and motion styles, and its first line sets the order of the cascade layers. In an application with its own styles, make it the first import and remove the separate `@import "tailwindcss"`. A Tailwind import above it sets that order without the kit’s `siteplane` layer, and the kit’s rules then override the utilities you pass in `className`. Keep your own rules below the import and make sure Tailwind scans your application code. A theme in the same file, such as the one `shadcn init` writes, also applies to Siteplane UI components and replaces the kit’s colors, borders and radii.

The kit is set in Inter. Install the font and import it once from the application entry (npm: `npm install @fontsource-variable/inter`):

```bash
pnpm add @fontsource-variable/inter
```

```tsx title="Application entry"
import "@fontsource-variable/inter";
```

To set the kit in another typeface, such as Geist or the system font, follow [Typeface](/docs/customization/theming/#typeface).

## Siteplane UI Pro

Siteplane UI Pro adds ready-made patterns; sections and templates follow. Pro is free for now, and if you get it now, you get all updates. The patterns install with the shadcn CLI and your license key from a separate registry, on top of the setup above. Get a license on the [Pro page](/pricing). After checkout, the license page and your license email show the same steps with your key filled in.

Add the key to `.env.local`, which the Next.js and Vite templates keep out of version control:

```bash title=".env.local"
SITEPLANE_LICENSE_KEY=your-license-key
```

Add the `@siteplane-pro` registry to `components.json`, next to any entries already in `registries`:

```json title="components.json"
{
  "registries": {
    "@siteplane-pro": {
      "url": "https://ui.siteplane.io/api/registry/{name}.json",
      "headers": {
        "Authorization": "Bearer ${SITEPLANE_LICENSE_KEY}"
      }
    }
  }
}
```

The shadcn CLI reads the key from `.env.local`, or from `.env` in a project set up that way, and sends it with each request to this registry. Install a pattern:

```bash
pnpm dlx shadcn@4.18.0 add @siteplane-pro/modal-block
```

Other patterns install the same way under the name in their page address, for example `@siteplane-pro/metric-card` for [Metric Card](/docs/patterns/metric-card/). Each example on a Pattern page installs as its own item, named like the free examples: `@siteplane-pro/metric-card-demo` for the example at the top of the page and `@siteplane-pro/metric-card-<example-id>-example` for the others. Every Pattern page shows these commands, and `pnpm dlx shadcn@4.18.0 search @siteplane-pro` lists every pattern and example in `@siteplane-pro`. The free components a pattern uses install along with it. The source of patterns, sections and templates is licensed under the [Siteplane UI Pro License](/legal/license); the free components use the [Siteplane UI License](/docs/license/).

## Install or copy an example

Install a default example and its component dependencies directly:

```bash
pnpm dlx shadcn@4.18.0 add @siteplane/button-demo
```

Default examples use `<component>-demo`; other examples use `<component>-<example-id>-example`. The three [application examples](/docs/examples/) are also installable; their pages show the command.

To copy manually, open a component page, expand the code below its preview, and copy the complete TSX file. Save it as `src/components/example.tsx`, then render its default export. The page’s Markdown version links the same file as raw TSX.

When copying manually, install the components named in the example’s imports. Registry installation resolves these dependencies for you.

## Stability and deprecations

From 1.0, Siteplane UI versions follow semantic versioning. The stable API is what these docs describe. It covers the registry items, the components with their parts, props and types, the hooks and providers on their pages, the documented `data-slot` attributes and the CSS tokens on the customization pages. Documented aliases, such as the shadcn names `DialogContent` and `AlertDialogContent`, are part of it. Everything else that an installed file exports is internal, for example helpers and class names that other kit files import, and can change in any release.

Minor and patch releases keep the documented API working. When a prop or a part is renamed, the old name stays as a deprecated alias: it keeps working, and your editor marks it as deprecated and names the replacement. A renamed value, such as `variant="brand"` on Badge, which is now `accent`, keeps working too, but TypeScript can't mark a string value, so the component page names the deprecated values. The [changelog](/docs/changelog/) lists every deprecation with its replacement. Deprecated aliases are removed in the next major version, 2.0. Fixes and refinements of the look ship in minor and patch releases. Installed source changes only when you install again, so you decide when a release reaches your application.

## Pin a release

The `@siteplane` namespace always serves the current catalog. To install the fixed source of a release, including its Siteplane UI dependencies, use its versioned URL. The current release is 1.4.2:

```bash
pnpm dlx shadcn@4.18.0 add https://ui.siteplane.io/registry/v/1.4.2/button.json
```

Replace `button` with any item name from the [1.4.2 catalog](/registry/v/1.4.2/registry.json). The [release manifest](/registry/v/1.4.2/manifest.json) records the source commit and SHA-256 hashes for the registry items and public build. Earlier releases remain available under `/registry/v/0.1.0/`, `/registry/v/0.1.1/`, `/registry/v/0.1.2/`, `/registry/v/0.1.3/`, `/registry/v/0.1.4/`, `/registry/v/0.1.5/`, `/registry/v/0.2.0/`, `/registry/v/0.2.1/`, `/registry/v/0.3.0/`, `/registry/v/0.3.1/`, `/registry/v/0.3.2/`, `/registry/v/0.3.3/`, `/registry/v/0.3.4/`, `/registry/v/0.3.5/`, `/registry/v/0.3.6/`, `/registry/v/0.3.7/`, `/registry/v/0.3.8/`, `/registry/v/0.3.9/`, `/registry/v/0.3.10/`, `/registry/v/0.3.11/`, `/registry/v/0.3.12/`, `/registry/v/0.3.13/`, `/registry/v/0.3.14/`, `/registry/v/0.4.0/`, `/registry/v/0.4.1/`, `/registry/v/0.4.2/`, `/registry/v/0.4.3/`, `/registry/v/0.4.4/`, `/registry/v/0.4.5/`, `/registry/v/0.4.6/`, `/registry/v/0.4.7/`, `/registry/v/0.4.8/`, `/registry/v/0.4.9/`, `/registry/v/0.4.10/`, `/registry/v/0.4.11/`, `/registry/v/0.4.12/`, `/registry/v/0.4.13/`, `/registry/v/0.4.14/`, `/registry/v/0.5.0/`, `/registry/v/0.6.0/`, `/registry/v/0.6.1/`, `/registry/v/0.6.2/`, `/registry/v/0.6.3/`, `/registry/v/1.0.0/`, `/registry/v/1.1.0/`, `/registry/v/1.2.0/`, `/registry/v/1.3.0/`, `/registry/v/1.3.1/`, `/registry/v/1.4.0/` and `/registry/v/1.4.1/`. Dependency versions are declared in each item; commit your application lockfile as well as installed source. Future updates use a new release version.

Siteplane UI installs `@base-ui/react` at an exact version. Keep that version, including in automated dependency updates, and upgrade Base UI only when a Siteplane UI release does: Field and the date, time and color controls build on internal Base UI modules, which Base UI may change in any release.

## Content Security Policy

Siteplane UI renders no inline `<script>` or `<style>` element of its own, but React Aria and Motion add a `<style>` element while the page runs. Under a Content Security Policy that allows styles only with a nonce, pass that nonce to `SiteplaneUIProvider`. The provider hands it to React Aria through a `<meta property="csp-nonce">` element in the head, to the kit's lists and swaps that use Motion's `popLayout` mode, and to Base UI's `CSPProvider`, which puts it on any inline element your own Base UI parts render. An application that uses Motion's `popLayout` mode itself passes the same nonce to Motion's `MotionConfig`. Without such a policy, leave the nonce out.

The policy must also allow style attributes, with `style-src-attr 'unsafe-inline'`. Base UI, React Aria and the kit set positions, sizes and visually hidden styles in style attributes, and a nonce covers only `<script>` and `<style>` elements, never an attribute. Without the directive, a Checkbox shows a second, native checkbox beside it and Slider thumbs sit at the start of the track. Scripts and `<style>` elements keep their nonce protection. The directive works from Chrome 75, Firefox 108 and Safari 15.4; older browsers apply `style-src` to style attributes, so the attributes stay blocked there.

In Next.js, the proxy creates a nonce for each request and sends the policy. This is the proxy from the Next.js [Content Security Policy guide](https://nextjs.org/docs/app/guides/content-security-policy) with the `style-src-attr` directive added:

```ts title="src/proxy.ts"
import { NextRequest, NextResponse } from "next/server";

export function proxy(request: NextRequest) {
  const nonce = Buffer.from(crypto.randomUUID()).toString("base64");
  const isDev = process.env.NODE_ENV === "development";
  const cspHeader = `
    default-src 'self';
    script-src 'self' 'nonce-${nonce}' 'strict-dynamic'${isDev ? " 'unsafe-eval'" : ""};
    style-src 'self' 'nonce-${nonce}';
    style-src-attr 'unsafe-inline';
    img-src 'self' blob: data:;
    font-src 'self';
    object-src 'none';
    base-uri 'self';
    form-action 'self';
    frame-ancestors 'none';
    upgrade-insecure-requests;
  `;
  const contentSecurityPolicyHeaderValue = cspHeader
    .replace(/\s{2,}/g, " ")
    .trim();

  const requestHeaders = new Headers(request.headers);
  requestHeaders.set("x-nonce", nonce);
  requestHeaders.set(
    "Content-Security-Policy",
    contentSecurityPolicyHeaderValue,
  );

  const response = NextResponse.next({
    request: {
      headers: requestHeaders,
    },
  });
  response.headers.set(
    "Content-Security-Policy",
    contentSecurityPolicyHeaderValue,
  );

  return response;
}

export const config = {
  matcher: [
    {
      source: "/((?!api|_next/static|_next/image|favicon.ico).*)",
      missing: [
        { type: "header", key: "next-router-prefetch" },
        { type: "header", key: "purpose", value: "prefetch" },
      ],
    },
  ],
};
```

The root layout reads the nonce and passes it to the provider. This is the layout from the [Next.js guide](/docs/installation/nextjs/) with the provider added:

```tsx title="src/app/layout.tsx"
import "@fontsource-variable/inter";
import "./globals.css";
import { headers } from "next/headers";
import { SiteplaneUIProvider } from "@/siteplane/system/provider/siteplane-ui-provider";

export default async function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  const nonce = (await headers()).get("x-nonce") ?? undefined;
  return (
    <html lang="en" data-theme="light">
      <body>
        <SiteplaneUIProvider nonce={nonce}>{children}</SiteplaneUIProvider>
      </body>
    </html>
  );
}
```

Reading the request headers renders every page when it is requested, which a nonce needs: each response carries a new one.

## Updating and manual installation

Installed files belong to your application. Commit or back up your changes, inspect the incoming source, and reconcile local edits before reinstalling with overwrite.

Inspect incoming files without changing your application:

```bash
pnpm dlx shadcn@4.18.0 view @siteplane/button
pnpm dlx shadcn@4.18.0 add @siteplane/button --dry-run
pnpm dlx shadcn@4.18.0 add @siteplane/button --diff
```

After reviewing and saving your local work, apply an intentional replacement:

```bash
pnpm dlx shadcn@4.18.0 add @siteplane/button --overwrite
```

Reinstall every Siteplane UI item you use in the same update: name them all in one `add` command with `--overwrite`. The items of a release work together, and from 1.1 the base stylesheet styles each part through a class that components installed from an earlier release don't render.

Replace `pnpm dlx` with `npx` for npm. Dependencies may also be updated: inspect the entire resulting diff and run your application’s relevant checks. These commands use the current catalog; to stay on a fixed version, [pin a release](#pin-a-release). Keep reviewed source in your own version control to reproduce or roll back your application.

`shadcn add` installs the package dependencies through your package manager. pnpm records the exact versions the kit names, while npm writes its `^` range, such as `^1.7.0`. To keep the exact versions with npm, add `save-exact=true` to the project's `.npmrc` before you install, or set the versions in `package.json` back to the exact numbers after each update.

For a manual install, open the **Registry JSON** link below a component’s install command, such as [Button JSON](/registry/button.json), and the [base support JSON](/registry/base.json). Copy every file to its declared target and install its package dependencies. Repeat for registryDependencies, including base styles. The registry command is the shorter and less error-prone path; copying only the visible component implementation omits required CSS and helpers.

The JSON `files` array contains each file’s `content` and `target`; `dependencies` names npm packages, and `registryDependencies` names additional registry items. Follow those dependencies recursively and preserve the installed LICENSE and TRADEMARKS notices. The **Read the installed source** link on each component page concatenates all files for inspection; do not paste it into one TSX file.
