There are two ways to install Frontfriend in an application:
- Connect an agent (recommended). Open Connect in Studio, copy one prompt into your coding agent, and it installs, signs in, configures and verifies the project for you.
- Install by hand. Run the same steps yourself from the terminal. Use this when you work without a coding agent or want to control each step.
Both paths produce the same result. Start with the agent unless you have a reason not to.
Before you start
Use Node.js 20.19.0 or newer, a working React or Vue application inside a Git work tree, and Tailwind CSS v4. The React sources target React 19. Create or open a Design System in Studio.
Every project starts from a Design System. There are no registry-only operations without an ff-id. When a project has no ff-id, init, migrate, update, download and the other Design System commands check that first. They stop, explain how to create or connect a Design System, and do not change the project.
Installing tokens, connecting an app, resolving its assigned tag, reading private components, and using MCP require an account with workspace access. If you have no account, sign up through the login page. An invitation gives you access to its workspace. Without an invitation, the Frontfriend team reviews your access and assigns your workspace. Contact support@frontfriend.dev if you need help.
For existing shadcn code, choose the shadcn base to preserve native tokens and components, or plan conversion to Frontfriend. See Adopt Frontfriend.
Connect an agent (recommended)
Studio writes a prompt for your coding agent with your Design System, app and platform already filled in. The agent runs connect, which checks every step and continues from the step that failed when you run it again. You do not copy an ff-id or edit a config file.
- Open your Design System in Studio and select Connect.
- Choose your agent: Claude, Codex, Cursor, OpenClaw or Hermes.
- Choose the app the agent is working in. Pick an existing app, or New app for a project that is not connected yet. A new app is named after the project’s package name, and follows the
baserelease unless you pick another tag. - Copy the prompt and paste it into your agent’s chat, opened in the application directory.
The agent then:
- asks what the app should take from the Design System (design contracts, tokens, components) and, when there is more than one, which release tag it follows;
- checks Git, then signs you in: it shows a code and a link, and waits for you to approve the login in your browser;
- detects the framework and component library, and asks you only if it cannot tell;
- configures the project (
frontfriend.config.js, agent instructions inAGENTS.md) and installs the tokens; - installs the Frontfriend MCP integration for your agent;
- verifies the connection and reports it to the Studio page you have open, which moves to Verify and shows the result.
Next comes design onboarding. The agent splits the codebase into areas and runs ff-setup, then gives you a review URL. A workspace admin reviews the onboarding there; after approval, the agent runs connect again to activate the reviewed snapshot. A connection alone does not mean the design is approved. See Design Skills.
Review the diff the agent leaves, and check that the build plugin and style imports from Connect the build are in place. Then add a component.
Install by hand
Use these steps when you work without a coding agent, in a script, or when you want to run each step yourself. Follow them in order.
1. Install the package
pnpm add @frontfriend/sdk@1.3.0 tw-animate-css
pnpm add -D typescript
The SDK includes the frontfriend executable. pnpm exec frontfriend runs your installed version. For npm, use npm install @frontfriend/sdk@1.3.0 tw-animate-css, install the parser with npm install -D typescript, and then use npx frontfriend. Do not install a separate package named frontfriend.
2. Declare your project target
Copy the ff-id of your Design System from Studio, then create frontfriend.config.js at the application root:
export default {
'ff-id': 'YOUR_DESIGN_SYSTEM_ID',
name: 'my-app',
framework: 'react',
primitive: 'base',
tag: 'base',
aliases: { ui: '@/components/ui' },
};
Use radix, base, or aria for React; use framework: 'vue' and primitive: 'reka' for Vue. Choose one target per application and keep its config, registry namespace and CLI flags aligned. For a CommonJS project, use module.exports.
Give each distinct app in the workspace a different name. Reusing a name connects to the same app identity; it does not create a second app entry. Multiple checkouts of the same app can keep that identity. For a new app, confirm its name in the Connect flow before you run the command.
You can also let the CLI write this file. Sign in, then connect the Design System:
pnpm exec frontfriend login
pnpm exec frontfriend connect --ff-id YOUR_DESIGN_SYSTEM_ID --name my-app --framework react --primitive base --tag base --agent codex
connect detects the framework and component library, and asks only if it cannot tell. A new app follows base. To get this command with your Design System, framework, component library, tag and adoption levels already filled in, open Connect in Studio, choose your agent and app, and expand Do it by hand. An explicit target also supports a new React or Vue app without running shadcn setup first. Existing apps keep their configured target and tag.
Run connect inside a Git work tree. It reports whether design onboarding is still needed. Follow the reported steps before using design and audit runs; a connection alone does not mean the design is approved. The lower-level setup command configures the project without completing this flow.
3. Initialize tokens
pnpm exec frontfriend init
This installs the tokens for the Release in frontfriend.lock.json, or the tag selected for your app. To select a tag explicitly, run pnpm exec frontfriend init --tag <tag-name>. Signed in as a person, init also registers your app on its tag. When the app adopts contracts, it writes them to .frontfriend/design/.
init requires a login and reads tokens from Studio. It keeps a verified local copy and restores it while Studio is unreachable. A login request, access refusal, invalid response, or invalid artifact stops initialization; a cached copy does not override that response.
4. Connect the build
For Vite, keep your existing framework and Tailwind plugins and add Frontfriend:
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';
import frontfriend from '@frontfriend/sdk/vite';
export default defineConfig({
plugins: [react(), tailwindcss(), frontfriend()],
});
For Vue, replace react() with your existing vue() plugin. For Next.js, preserve your configuration options and use the wrapper:
import frontfriend from '@frontfriend/sdk/next';
export default frontfriend({});
Import the styles in your application CSS, in this order:
@import 'tailwindcss';
@import '@frontfriend/sdk/theme.css';
@import 'tw-animate-css';
5. Add a component
pnpm exec frontfriend download button -f react --primitive base
First preview with pnpm exec frontfriend download button --dry-run. The downloader writes component source into your configured UI directory, records the adoption lock and installs missing npm dependencies. Use --no-install to record dependencies without installing them. Review the generated diff. Run your project’s typecheck and build before committing.
import { Button } from '@/components/ui/button';
export function Welcome() {
return <Button variant="main">Make it yours</Button>;
}
Build in CI and Docker
Builds authenticate with a machine credential, not a person’s login. A workspace owner or admin creates one in Studio, with the components:read permission, on the workspace API keys page. Store it in your CI secret store as FF_AUTH_TOKEN. Never commit it or print it in build logs.
--no-register skips App registration; it does not authenticate. An API key with components:read is required even when registration is disabled. Keep credentials outside image layers and build logs.
For a repeatable build, commit frontfriend.lock.json and run frontfriend init without a tag override. It reads the pinned Release. Use an explicit tag only when the build is intended to select the tag’s current Release.
For local Docker development, mount node_modules/.cache rather than node_modules/.cache/frontfriend. Token installation replaces the frontfriend directory atomically. A direct mount can refuse replacement with EBUSY, EACCES or EPERM. Check the directory ownership; do not change permissions recursively as a workaround.
Select the tag that the build ships:
FF_AUTH_TOKEN=<machine credential> pnpm exec frontfriend init --tag <tag-name>
A machine credential is read-only for the app. init installs the tokens of the requested tag and prints Build mode: App registration skipped (machine credential). It never registers the app or changes its release tag in Studio. A preview build on next therefore leaves a production app on base. To get the same behavior with any credential, pass --no-register. Studio never changes an app for a machine credential either. Builds with an earlier SDK version also install the requested tag, and the app keeps its own tag.
To connect an app or change its tag, sign in as a person with frontfriend login, or change the tag in Studio. connect refuses a machine credential. update also stops when it would move the app to another tag.
adopt updates installed components. If none are installed, select them with frontfriend download <component>. Use frontfriend download all only when the full catalogue is intended.
Projects that still use https://app.v4.frontfriend.dev must change api-url in their configuration and agent installation to https://app.frontfriend.dev, then run frontfriend login --api-url https://app.frontfriend.dev. The client does not forward credentials through redirects.
Check your setup
pnpm exec frontfriend status
pnpm exec frontfriend init --force
If a component is unstyled, check the imports, build plugin and cached configuration first. See Troubleshooting and Primitive targets.