> For the complete documentation index, see [llms.txt](https://beamline.gitbook.io/beamline-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://beamline.gitbook.io/beamline-docs/getting-started/install-beamline.md).

# Install Beamline

Install local editable source or compiled package archives into a React 19 app: commands, the one stylesheet, UIRoot and Tailwind v4 setup.

> The original of this page is on beamline.io: [beamline.io/docs/install](https://beamline.io/docs/install).

> Beamline code and your custom style files stay in your repo; your app has no Beamline runtime dependency. This documentation ships with the complete system (docs/INSTALL.md in the kit). Use [local kit tools](https://beamline.io/docs/install) or [connect an agent](https://beamline.io/connect) to install parts.

Use the tools and release descriptor from the same delivered release. React 19 belongs to the app. For 0.2 releases, select compiled packages or full editable source. Every Beamline file your app uses can be source in your repo, including the runtime, foundation and selected looks; font assets stay local too. Keep customer brand files, presets and wrappers in the app, outside the managed source folder.

## Choose your route

Beamline is a React UI library for developers; a coding agent is optional. Use the documented commands and React imports below directly, or let a connected agent select and install the same parts. It supplies UI code, not a hosted application, database, model service or voice provider.

**Public npm packages, 13 October 2026:** publication is still incomplete. Use the Beamline CLI/archive or shadcn source routes below for a complete install; bare `npm install @beamline/settings` can fail on missing dependencies.

| Route                                                      | Use it when                                                  | Important boundary                                                                |
| ---------------------------------------------------------- | ------------------------------------------------------------ | --------------------------------------------------------------------------------- |
| [Compiled packages](#selected-02-packages)                 | You want selected components and looks with generated CSS    | No Tailwind is needed for Beamline styling; keep the local archives with the app. |
| [Full editable source](#full-editable-source)              | You want to edit components and the shared base in your repo | Tailwind v4 is required; managed upgrades need the recorded baselines.            |
| [shadcn registry](#with-the-shadcn-cli)                    | You already use the shadcn CLI                               | Registry replacement does not provide Beamline's managed three-way upgrades.      |
| [Optional coding-agent setup](https://beamline.io/connect) | You want an agent to find, install and inspect parts         | Hosted MCP helps installation; installed components do not call it at runtime.    |

### Add Beamline beside existing UI

Start with one screen or region inside the documented `UIRoot`, using its actual imports below. Compiled styles are scoped and need no host Tailwind setup. Keep the app's routing, data, authentication and save handlers. Source mode shares the app's Tailwind build: read its theme instructions before combining it with existing styles.

A scoped root is a styling boundary, not a guarantee that every third-party component, global reset, portal or CSS rule will coexist unchanged. Check the real combined screen and its open menus/dialogs. The [documented install results](#package-managers-checked-11-october-2026) name the combinations exercised; [known limitations](https://beamline.io/docs/limitations) names the gaps. Runtime independence also makes no security guarantee: your application still owns permissions, secret handling, backend calls and dependency updates.

For a first hands-on check, follow [Try it in 30 minutes](https://beamline.io/docs/try-in-30): save and reload Settings, recover a failed save, check the phone layout and build your own style.

## Package managers: checked 11 October 2026

The local `0.2.0-compat2.1` candidate was installed in fresh **Next.js 16.4.0 App Router (webpack)** and **Vite 8.3.4** apps with Node 24.21.0, React/ReactDOM 19.3.0 and TypeScript 6.0.3. Source consumers used Tailwind 4.3.3. Every cell below passed installation, strict typecheck (`skipLibCheck: false`), a production build and three Settings URLs in Chromium 153.0.8010.12 on Linux at 1512×982, including save/reload, Button actions and Dialog focus/Escape.

| Package manager                   | Packaged CLI / compiled | Full source | shadcn 4.21.4 registry | Public sample source |
| --------------------------------- | ----------------------- | ----------- | ---------------------- | -------------------- |
| Bun 1.4.3                         | Next + Vite             | Next + Vite | Next + Vite            | Next + Vite          |
| Yarn Classic 1.22.22              | Next + Vite             | Next + Vite | Next + Vite            | Next + Vite          |
| Yarn Berry 4.18.1, `node-modules` | Next + Vite             | Next + Vite | Next + Vite            | Next + Vite          |
| Yarn Berry 4.18.1, PnP            | Next + Vite             | Next + Vite | Next + Vite            | Next + Vite          |

These are 32 named profiles using Settings, Button and Dialog, not the full catalog or every framework option. Registry checks used the candidate's generated registry on loopback; they do not qualify live paid-key authorization. The sample cells used the unchanged `ui/` from the [public snapshot](https://github.com/dprvda/beamline/tree/c2392c13c8154017b354b5cea97d84b901ceff89) in fresh framework apps; that older source is separate from the candidate.

Six additional Next 16.4.0 profiles passed with **Turbopack**: full source and generated registry with Bun, Yarn Classic and Yarn Berry's `node-modules` linker. The candidate keeps CSS Module `composes` declarations at the top level while visual rules stay in `@layer components`; no custom Turbopack loader or CSS bypass is needed. Turbopack with PnP was not checked. The older public sample still needs webpack; see [Known limitations](https://beamline.io/docs/limitations).

The installer follows `package.json#packageManager` or the app's lockfile. Run the packaged CLI with the same manager:

```sh
# Bun
bun x --package https://mcp.beamline.io/cli.tgz beamline install button dialog --release /path/to/release/release.json

# Yarn Berry: an archive URL needs an explicit package name.
yarn dlx --package beamline@https://mcp.beamline.io/cli.tgz beamline install button dialog --release /path/to/release/release.json

# Yarn Classic has no dlx: install the tool locally, then run it.
yarn add --dev https://mcp.beamline.io/cli.tgz
yarn beamline install button dialog --release /path/to/release/release.json
```

For full source, replace `install` with `source` and append `--install`. The same native runners can run `shadcn@4.21.4` for the registry path. Berry supports `nodeLinker: pnp` and `nodeLinker: node-modules` in `.yarnrc.yml`; use `yarn run build` and `yarn run typecheck` so PnP is active. Concurrent Yarn Classic apps should use separate `YARN_CACHE_FOLDER` directories: sharing one empty cache produced tar extraction `EEXIST`/`ENOENT` errors before Beamline ran.

## Selected 0.2 packages

From a React app with a `package.json`:

```bash
node /path/to/release/tools/beamline.mjs install button dialog \
  --release /path/to/release/release.json --preset prism
```

A local HTTP `release.json` URL works too. The tool verifies the descriptor's graph and selected package archives, then uses the app's npm, pnpm, Yarn or Bun. It does not download component source for this path. The descriptor names registry dependencies; an offline Beamline bundle includes its own package archives but still needs those declared registry dependencies or an existing package-manager cache.

The app's `package.json` lists only what was chosen: the selected components, looks, fonts and effects, plus `@beamline/runtime` and `@beamline/foundation`, each pointing at its verified archive in the app's root `.beamline/packages/` cache. The internal Beamline units they use resolve through `overrides` (npm/Bun), Yarn `resolutions`, or version-qualified pnpm overrides, and their registry dependencies (Radix, Motion, d3-shape for chart curves) come with the units instead of entering the app's manifest. React stays the app's: an existing `react`/`react-dom` range is never changed, and the tool stops with a message when it does not allow React 19. Dependencies the tool added earlier and no longer needs are removed; nothing else in the manifest changes.

What your own code imports belongs in your `package.json`: your icon library, and anything a component's props are typed with. The summary names the latter with the release's range (Form takes your `react-hook-form` `useForm`: `react-hook-form@^7.89.0`); add it at that range so your app and the components share one copy. With pnpm an import the app does not declare fails to resolve; npm may hoist it into reach, but declare it anyway.

For pnpm, the installer recognizes the app's `packageManager`, its lockfile, or its enclosing pnpm workspace. It adds version-qualified archive overrides through pnpm's own project configuration command so transitive Beamline dependencies resolve to the included files. Existing workspace members, settings and unrelated overrides remain. Previous workspace configuration bytes are retained under `.beamline/package-manager/`. Keep the root `.beamline/` folder with the app (commit it): its manifest, lockfile and overrides reference the archives there, and its `package-selection.json` records what was chosen at which release. A compiled install writes nothing under `src/` except the one stylesheet. This path is exercised with pnpm 11.22.0.

The tool writes one stylesheet, `src/styles/beamline/beamline.css`, that imports fonts, foundation, the selected looks, an applied custom style and every selected component in cascade order. Import it once in the app's entry. One entry lets the bundler include each Beamline file once; separate per-component imports each bring foundation again. The file is regenerated while it holds what the tool last wrote; once you edit it, the tool keeps your file and prints the imports it would have added. Each component's own `styles.css` still works on its own for an app that uses a single component.

```tsx
// src/main.tsx — in a new Vite app, replace the starter's index.css (it centres #root at 1126 px and paints its own
// background) with the one-line page reset below.
import { createRoot } from "react-dom/client";
import "./styles/beamline/beamline.css";
import "./index.css";
import { App } from "./App";

createRoot(document.getElementById("root")!).render(<App />);
```

```css
/* src/index.css — the app's own page reset; Beamline never resets the host page */
body {
  margin: 0;
}
```

```tsx
// src/App.tsx
import { UIRoot } from "@beamline/runtime";
import { Button } from "@beamline/button";
import { prism } from "@beamline/look-prism";

export function App() {
  return (
    // A full-page app: look-page paints the look's page edge to edge, in dark and light.
    <UIRoot preset={prism} theme="dark" brand="oklch(0.64 0.16 155)" className="look-page" style={{ minHeight: "100dvh" }}>
      <Button onClick={() => console.log("Connect the app's save operation")}>Save</Button>
    </UIRoot>
  );
}
```

To follow the reader's device, pass `theme="system"`; it changes with the device setting. On a server-rendered page (Next.js), set the page's theme before the first paint so it never flashes the other one: make `<html className="pui">` the scope, give it `suppressHydrationWarning`, and put `<ThemeScript nonce={nonce} />` in `<head>`. With a strict Content-Security-Policy, pass the request's nonce, or allow the script by hash: `import { themeScriptHash } from "@beamline/runtime/theme-script"` and add `await themeScriptHash()` to `script-src`. `storageKey` lets a stored choice ("light" or "dark") win over the device.

`UIRoot` paints nothing behind its children unless asked, so a root embedded in an existing page keeps that page's background; App shell paints its own page. Give a full-page root `className="look-page"` and the viewport's height, and remove the browser's default body margin, as above.

Some looks need explicit SVG definitions. The CLI's selected look setup and that look's README provide the exact runtime import. For example, use `import { setup } from "@beamline/look-mono/runtime";` and call `setup()` in the application's browser entry, retaining its returned cleanup for teardown. In a React client boundary, `useEffect(() => setup(), [])` pairs acquisition and cleanup. Multiple roots share the definitions. Importing the look reference or mounting a chart never initializes other looks. Soft has no runtime setup. Glass's setup adds the lens that bends what is behind its controls and menus (Chromium browsers; elsewhere Glass keeps its frost) and lights a press from the point pressed; without it Glass still renders, frosted and unbent.

Adding compiled roots unions them at the recorded release, and so do `--preset`, `--fonts` and `--effects`: `install --preset glass` adds Glass to an app that has Soft, with no entry ids needed. Remove one explicitly with `remove --preset glass`; the tool refuses while the app still imports `@beamline/look-glass`, and keeps at least one look. Move roots explicitly with `install <id…> --upgrade --release <target>`. Exact imports, package versions and setup come from the artifact. Fonts are optional and selected explicitly with `--fonts <id>`. A compiled package app does not need Tailwind to style Beamline. The aggregate is an explicit release selection; do not combine a legacy 0.1 aggregate with split 0.2 units.

Every command prints a short summary; add `--json` for the full machine-readable result and nothing else on standard output (package-manager output goes to standard error). `--dry-run` shows the planned manifest and stylesheet without changing the app.

## Full editable source

```bash
node /path/to/release/tools/beamline.mjs source settings data-grid \
  --release /path/to/release/release.json --preset prism --install
```

`source` means `add --full-source`. A new source-only app also gets this mode with plain `add`. Existing source installs retain their recorded mode on `add` and `upgrade`; their current imports keep working.

Everything Beamline contributes lands in the managed folder, `src/ui/beamline` by default:

| Path inside that folder                    | What you can edit                                                                   |
| ------------------------------------------ | ----------------------------------------------------------------------------------- |
| `components/`, `blocks/`, `hooks/`, `lib/` | The selected entries and the source they use                                        |
| `runtime/`                                 | UIRoot, shared appearance context, types and selected look setup functions          |
| `styles/`                                  | Tokens, theme, base and utility CSS, selected look CSS and the `beamline.css` entry |
| `looks/`                                   | Pure references for the selected looks                                              |
| `fonts/`                                   | Selected font CSS, local font files and their OFL notices                           |
| `LICENSE.md`, `NOTICE`, `licenses/`        | Beamline terms and included licence notices                                         |
| `beamline-ui.lock.json`, `.beamline/`      | Accepted release, source baselines and recoverable upgrade state; commit these too  |

The app's `package.json` has no `@beamline/*` entries. Radix, Motion and other third-party dependencies remain ordinary npm packages. Installation retrieves the selected release files and verified font/theme archives; after installation, building and running the app needs no connection to beamline.io. Updates fetch a release only when explicitly requested. The free sample's runtime, foundation and Prism source are MIT-licensed; fonts carry SIL OFL 1.1, and paid parts retain the Beamline licence. See [LICENSE.md](https://beamline.io/docs/licence), section 4.

Use `--app /path/to/app` when running elsewhere, or `--to src/ui/another-folder` for a different managed subdirectory. Internal imports become relative paths. **Keep your existing `@/` alias**: no app aliases or bundler configuration are changed. Import the local runtime and look, as well as the selected component:

```tsx
// src/App.tsx (adjust relative paths for another caller location)
"use client"; // Next.js App Router: this example has an interactive button.
import { UIRoot } from "./ui/beamline/runtime/appearance";
import { prism } from "./ui/beamline/looks/prism";
import { Button } from "./ui/beamline/components/button/button";

export function App() {
  return (
    <UIRoot preset={prism} theme="dark" className="look-page" style={{ minHeight: "100dvh" }}>
      <Button onClick={() => console.log("Connect the app's save operation")}>Save</Button>
    </UIRoot>
  );
}
```

Source components use Tailwind v4. Keep the app's existing integration. For Vite without one, install `tailwindcss` and `@tailwindcss/vite`, and add `tailwindcss()` alongside the React plugin. For Next.js App Router, use `@tailwindcss/postcss` in the app's PostCSS configuration. Import one stylesheet from the app entry (`app/layout.tsx` in Next.js):

```css
/* src/index.css; adjust the relative path when the stylesheet is elsewhere. */
@import "tailwindcss";
@import "./ui/beamline/styles/beamline.css";
body { margin: 0; }
```

The managed entry imports fonts, the source theme, foundation and chosen looks, and declares Tailwind's source scan. CSS modules travel with their components. The source theme keeps host Tailwind values outside a Beamline root; inside, shared names such as `text-sm` and `rounded-md` read Beamline tokens. Host `@theme inline` declarations can still override shared names inside the root. Use plain `@import "tailwindcss"`, without `theme(inline)`.

Some looks need browser setup. The installer prints its local path. For Mono, import `setup` from `./ui/beamline/runtime/presets/mono` and call `useEffect(() => setup(), [])` in a React client boundary. This pairs setup with cleanup. Importing a look reference alone has no side effects.

`--install` installs third-party dependencies only after the source transaction is accepted. Without it, run `deps --install` later. If the package manager fails, accepted source remains recorded and the error explains how to retry. Adding entries unions the roots at the accepted release; only `upgrade --release <target>` changes that release. Removing an entry recomputes the closure and keeps files still needed by another root or local import. [UPGRADE.md](https://beamline.io/docs/upgrade) explains merges and recovery for components **and the base**.

The skill installer uses the same path:

```bash
node /path/to/release/agents/skills/beamline-ui/scripts/install.mjs \
  --app /path/to/app --release /path/to/release/release.json \
  --source --full-source --entries settings,data-grid --preset prism
```

Use `--no-install` to prepare source without installing dependencies. The hosted MCP tool accepts `beamline_install` with `source: true` and returns the full-source command and local import guidance. Omit `--source` in the skill, or `source` in MCP, for compiled packages.

### Existing source installs with a packaged base

`add --shared-base` retains the earlier arrangement: selected components go under `src/ui/beamline`, while runtime, foundation, looks and fonts are installed as `@beamline/*` packages. Existing locks without a full-source marker keep this arrangement automatically, including on upgrade. Their existing package CSS and runtime imports remain valid.

To move an existing app to full source, first replace its app-owned `@beamline/*` imports with the local paths above and remove Beamline dependencies/overrides from its manifest. Then rerun `add <entries> --full-source` with your existing entry selection at the accepted release, resolve any source merge conflicts, and install dependencies. The installer refuses to mix full source with Beamline packages because a second runtime context would split roots from their children. Customer brand files and wrappers remain outside the managed folder.

## With the shadcn CLI

Beamline is also a shadcn registry. In a project shadcn already knows (a `components.json`), a free element needs no setup:

```sh
npx shadcn@latest add https://beamline.io/registry/segmented-control.json
```

To use the short names, and shadcn's search and MCP server, add the registry once:

```sh
npx shadcn@latest registry add @beamline=https://beamline.io/registry/{name}.json
npx shadcn@latest add @beamline/segmented-control
```

A paid element needs your key. Create one on your account page (beamline.io/account, "Keys for shadcn"), put it in `.env.local` as `BEAMLINE_KEY`, and name the registry with the key in `components.json`:

```json
{
  "registries": {
    "@beamline": {
      "url": "https://beamline.io/registry/{name}.json",
      "headers": { "Authorization": "Bearer ${BEAMLINE_KEY}" }
    }
  }
}
```

Each element's source lands in `src/ui/beamline`, including its free runtime/foundation base. The default Prism look and fonts are source registry items too; no `@beamline/*` packages or hosted runtime dependencies are installed. shadcn registry files are text, so the font bytes are embedded in local editable font CSS with their OFL notices.

After Tailwind, import `src/ui/beamline/styles/beamline.css` once, then `src/ui/beamline/styles/look-prism.css`, using paths relative to your app stylesheet. The shared base must precede every look and must not repeat between looks. Wrap the app in `<UIRoot preset={prism}>`. Import UIRoot from `src/ui/beamline/runtime/appearance` and Prism from `src/ui/beamline/looks/prism`, using paths relative to your caller. The CLI prints these steps after installation.

`@beamline/setup` is the free source base. `@beamline/look-metal` adds Metal; the other available looks use the same `look-<name>` pattern, with paid looks requiring your key. Import each chosen `styles/look-<name>.css`; a look with browser setup names its local setup function in the install result.

shadcn adds or replaces source files and does not create Beamline's managed upgrade baselines. Use the Beamline source CLI from the start when you want three-way upgrades that preserve edits. Existing shadcn apps keep their previously installed base packages until you explicitly migrate their imports and dependencies; overwriting a registry item is not a managed migration.

## Existing 0.1 packages

A 0.1 bundle remains installable using its own original package instructions:

```bash
npm i /path/to/beamline-ui-0.1.x/package/beamline-ui-0.1.x.tgz
```

Use `@beamline/ui/<id>`, import `@beamline/ui/styles.css`, and render inside its `UIRoot` from `@beamline/ui/ui-root`. Do not apply 0.2 setup to 0.1 bytes. A legacy source lock containing only hashes needs its original baseline bundle and a manual migration; the new source tool refuses to invent missing baselines.

## Check the actual app

Render the selected Button on a dark branded root, activate its app handler, and open the selected Dialog. Confirm the browser console is clear, existing navigation and styles still work, and customer alias/brand files are unchanged. Blocks need a sized parent. These are consumer checks; the included gallery is separate evidence.

[Knowledge: sourced answers](https://beamline.io/knowledge.md): concise answers with their original sources.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://beamline.gitbook.io/beamline-docs/getting-started/install-beamline.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
