Skip to content
Join UI

Installation

Add Join UI to a new or existing app.

Join UI installs through the shadcn CLI. If your project already uses shadcn/ui, you only need to add the registry namespace — skip to registry setup.

Requirements

  • Node.js 20.9 or newer
  • A Next.js project using the App Router
  • Tailwind CSS v4
  • TypeScript (the components are typed, and the prop types are exported)

Quick start

Create a Next.js app

Skip this if you already have a project.

bash
pnpm create next-app@latest my-app --typescript --tailwind --eslint --app
cd my-app

Initialise shadcn

This creates components.json and the cn utility that every Join UI component imports.

bash
pnpm dlx shadcn@latest init

Answer the prompts however you like — Join UI components respect your aliases. neutral is the closest base colour to the tokens you will add in the next step, so it is the least surprising answer there.

Register the @joinui namespace

Add a registries block to components.json:

components.json
{
  "$schema": "https://ui.shadcn.com/schema.json",
  "style": "new-york",
  "rsc": true,
  "tsx": true,
  "tailwind": { "css": "app/globals.css", "baseColor": "neutral", "cssVariables": true },
  "aliases": { "components": "@/components", "utils": "@/lib/utils", "ui": "@/components/ui" },
  "registries": {
    "@joinui": "https://ui.join-way.com/r/{name}.json"
  }
}

Add the design tokens

Join UI components read the neutral ramp and the semantic tokens built on it — --background, --foreground, --muted-foreground, --border, --primary, --accent, --radius, the elevation steps and the motion variables. Copy them into your globals.css; the full block is in theming.

A component that uses colour also reads one of the four hue families — --info, --positive, --caution, --critical — and rounds through the --radius-soft* scale. Those arrive on their own: the registry item declares them, so the CLI appends the ones a component needs, in both themes, the first time you install it. Nothing is hard-coded, so retinting a component to your brand is an override rather than a fork.

Install a component

Substitute the slug you want from the catalog:

pnpm dlx shadcn@latest add @joinui/<component>

The CLI resolves dependencies, installs them with your package manager and writes the component to components/joinui/<component>.tsx.

Use it

app/page.tsx
import { YourComponent } from "@/components/joinui/your-component"

export default function Page() {
  return <YourComponent>Get started</YourComponent>
}

Import paths follow the slug, and every component exports its props interface alongside it.

Installing without a namespace

You do not have to edit components.json at all. Every registry item is a plain JSON file, so the CLI can take its URL directly:

pnpm dlx shadcn@latest add https://ui.join-way.com/r/<component>.json

This is the fastest way to try one component, and it is what the "Installation" tab on every component page shows as a fallback — with the real slug already filled in.

Installing manually

If you would rather not run the CLI, every component page has a Code tab with the complete source and a copy button.

Install the dependencies

Each component page lists its own. Many need nothing at all; the ones that animate typically want:

pnpm add motion

Copy the source

Paste it into components/joinui/<name>.tsx. The import of cn assumes @/lib/utils — adjust it if your alias differs.

Verifying the install

Run your type checker. Join UI components export their prop interfaces, so a missing dependency or a wrong alias surfaces immediately:

bash
pnpm tsc --noEmit