# Install Beamline

> Part of the documentation that comes with Beamline's complete system (docs/INSTALL.md in the kit). Your coding agent can do all of this for you through Beamline's MCP server: [connect it](https://beamline.io/connect).

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 editable source; both share `@beamline/runtime` and `@beamline/foundation`. Keep customer brand files, presets and wrappers in the app, outside the managed source folder.

## 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 npm or pnpm. 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) 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>
  );
}
```

`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.

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. Yarn and Bun are outside this release's qualified installer path.

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.

## Selected editable source

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

The default managed destination is `src/ui/beamline`. Use `--app /path/to/app` when running elsewhere or `--to src/ui/another-folder` for a different managed subdirectory. Retrieval reads the descriptor, verified graph and selected source files directly. It never retrieves the whole source kit first.

The source tool rewrites declared internal imports to relative paths and declared runtime imports to the canonical packages. **Keep your existing `@/` alias.** The tool does not change app aliases, Vite configuration, customer brand files or wrappers. Import a copied component relative to the file using it, for example:

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

Use the runtime/root and selected package styles as above. Editable components still use Tailwind v4 utilities, so enable the app's existing Tailwind v4 integration and scan the managed folder. For a Vite app with no existing integration:

```bash
npm i -D tailwindcss @tailwindcss/vite
```

```ts
// Add tailwindcss() alongside the existing React plugin in vite.config.ts.
import tailwindcss from "@tailwindcss/vite";
```

```css
/* In the app's own entry stylesheet; paths are relative to this stylesheet. */
@import "tailwindcss";
@import "@beamline/foundation/source-theme.css";
@import "@beamline/foundation/styles.css";
@import "@beamline/look-prism/styles.css";
@source "./ui/beamline";
```

The release's foundation and selected look styles provide Beamline's scoped visual roles. Source CSS modules travel with their selected components. The source theme declares the utility aliases used by editable components, such as `bg-surface`; include it in the existing stylesheet without copying producer configuration. If the app defines the same utility names for another design system, use the compiled package path or resolve that utility-name overlap in the app. The package's optional `tailwind.css` uses prefixed host aliases such as `bg-pui-surface`.

`--install` installs declared packages only after the source transaction is accepted. Without it, the tool prints setup and dependencies; run `deps --install` later. Package-manager failure leaves truthful accepted source bytes and reports the install failure; npm/pnpm lockfiles remain authoritative for actual package resolution. A pending source proposal never installs its proposed packages beneath live callers.

Adding more entries unions the roots at the accepted release:

```bash
node /path/to/release/tools/beamline.mjs add input --app /path/to/app
node /path/to/release/tools/beamline.mjs status --app /path/to/app
```

Only `upgrade --release <target>` changes that release. `remove <id>` removes an intended root and recomputes shared dependencies; files still required by another root or a local import are retained. See [UPGRADE.md](https://beamline.io/docs/upgrade) for local changes and recovery.

The skill installer uses the same code path:

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

Omit `--source` for selected compiled packages; use `--no-install` for source preparation without dependency installation.

## 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.
