# Add reablocks to my Next.js (App Router) project

You are an expert React engineer. Add **reablocks** — a React UI component library styled with **Tailwind CSS v4** and themed through its `<ThemeProvider>` — to my existing **Next.js (App Router)** project.

Start by installing Reaviz's official AI skills (Step 1) so you have the canonical, up-to-date reablocks knowledge loaded, then follow the remaining steps exactly. Do not substitute a different UI or styling library, and do not change my app architecture beyond what these steps require.

## ALWAYS do

- Install the official reablocks AI skills first (`npx skills add reaviz/skills`) and follow them — they carry Reaviz's canonical, current reablocks + Tailwind v4 guidance.
- Use **Tailwind CSS v4** — the `@import "tailwindcss"` + `@source` + `@theme` syntax. reablocks targets v4, not v3.
- Install only the dependencies listed below.
- Put the reablocks theme token block in the **same stylesheet** that has `@import "tailwindcss"`.
- Wrap the app with `<ThemeProvider theme={theme}>` from `reablocks`.
- Put a `theme-dark` (or `theme-light`) class on the root `<html>` element.
- Use my existing package manager — detect it from the lockfile (npm / pnpm / yarn / bun) and translate the install commands accordingly.

## NEVER do

- Do NOT use Tailwind v3 syntax — no `@tailwind` directives, no `tailwind.config` content globs. reablocks needs v4.
- Do NOT install or scaffold a different component library or design system.
- Do NOT omit the theme token block — without it reablocks components render unstyled.
- Do NOT place `<ThemeProvider>` inside a Server Component (Next.js App Router); it must live in a Client Component.

## Steps

### 1. Install the reablocks AI skills

Install Reaviz's official AI skills so you have the canonical, always-current reablocks API + Tailwind v4 setup knowledge loaded before you start:

```sh
npx skills add reaviz/skills
```

(Team alternative: symlink the `reablocks` skill tree into `.claude/skills/`.) Once installed, follow the skills' guidance — the steps below match it.

### 2. Install dependencies

```sh
npm install reablocks
npm install -D tailwindcss@4 @tailwindcss/postcss
```

(Use the equivalent for your package manager — e.g. `pnpm add` / `pnpm add -D`, `yarn add` / `yarn add -D`, `bun add` / `bun add -d`.)

### 3. Enable the Tailwind v4 PostCSS plugin

Next.js processes CSS through PostCSS, so add the Tailwind v4 plugin to your PostCSS config (`postcss.config.mjs` — create it if missing):

```js
// postcss.config.mjs
return {
  plugins: {
    '@tailwindcss/postcss': {}
  }
};
```

If a `postcss.config.{js,cjs,mjs,ts}` already exists, add the `@tailwindcss/postcss` plugin to that file instead of creating a second config.

### 4. Wire Tailwind v4 + reablocks into your stylesheet

Open `src/app/globals.css` (your main stylesheet) and add this at the very top:

```css
@import "tailwindcss";
@source "../../node_modules/reablocks";
```

**The `@source` path matters.** It is resolved relative to the stylesheet's own location, so count the directories from `src/app/globals.css` up to `node_modules` and use that many `../` segments. The line above is correct for `src/app/globals.css`; recompute it only if you move the stylesheet.

Then paste the reablocks theme token block immediately after the `@source` line. It defines the reablocks color palette, `@custom-variant` rules, and `@theme` tokens:

```css
/* Color palette */
:root,
:host {
  --reablocks-theme: dark;

  /* Primary colors */
  --primary: var(--color-blue-500);
  --primary-active: var(--color-blue-500);
  --primary-hover: var(--color-blue-400);
  --primary-inactive: var(--color-blue-200);

  /* Secondary colors */
  --secondary: var(--color-charade);
  --secondary-active: var(--color-charade);
  --secondary-hover: var(--color-gray-700);
  --secondary-inactive: var(--color-gray-600);

  /* Success colors */
  --success: var(--color-green-500);
  --success-active: var(--color-green-500);
  --success-hover: var(--color-green-400);
  --success-background: var(--color-green-950);

  /* Error colors */
  --error: var(--color-red-500);
  --error-active: var(--color-red-500);
  --error-hover: var(--color-red-400);
  --error-background: var(--color-red-950);

  /* Warning colors */
  --warning: var(--color-orange-500);
  --warning-active: var(--color-orange-500);
  --warning-hover: var(--color-orange-400);
  --warning-background: var(--color-orange-950);

  /* Info colors */
  --info: var(--color-blue-500);
  --info-active: var(--color-blue-500);
  --info-hover: var(--color-blue-400);
  --info-background: var(--color-blue-950);

  /* Panel colors */
  --panel: var(--color-black-pearl);
  --panel-accent: var(--color-charade);

  /* Surface colors */
  --surface: var(--color-charade);
  --surface-accent: var(--color-blue-500);

  /* Text colors */
  --text-primary: var(--color-athens-gray);
  --text-secondary: var(--color-waterloo);

  /* Custom Backgrounds */
  --bottom-border-glow: radial-gradient(
    circle at center,
    var(--color-anakiwa) 0,
    blue,
    transparent 100%
  );
  --button-gradient: linear-gradient(
    283deg,
    #0808a5 0%,
    rgba(8, 8, 165, 0) 100%
  );
  --button-gradient-hover: linear-gradient(
    283deg,
    #44f 0%,
    rgba(23, 23, 255, 0.1) 100%
  );
  --button-gradient-focus: linear-gradient(
    283deg,
    #0d0dd2 0%,
    rgba(23, 23, 255, 0.1) 100%
  );

  .theme-light,
  &.theme-light,
  [data-theme='light'],
  &[data-theme='light'] {
    --reablocks-theme: light;

    /* Primary colors */
    --primary: var(--color-blue-500);
    --primary-active: var(--color-blue-500);
    --primary-hover: var(--color-blue-600);
    --primary-inactive: var(--color-gray-500);

    /* Secondary colors */
    --secondary: var(--color-blue-200);
    --secondary-active: var(--color-blue-200);
    --secondary-hover: var(--color-blue-300);
    --secondary-inactive: var(--color-waterloo);

    /* Success colors */
    --success: var(--color-green-500);
    --success-active: var(--color-green-500);
    --success-hover: var(--color-green-600);
    --success-background: var(--color-green-100);

    /* Error colors */
    --error: var(--color-red-500);
    --error-active: var(--color-red-400);
    --error-hover: var(--color-red-600);
    --error-background: var(--color-red-100);

    /* Warning colors */
    --warning: var(--color-orange-500);
    --warning-active: var(--color-orange-500);
    --warning-hover: var(--color-orange-600);
    --warning-background: var(--color-orange-100);

    /* Info colors */
    --info: var(--color-blue-500);
    --info-active: var(--color-blue-500);
    --info-hover: var(--color-blue-600);
    --info-background: var(--color-blue-100);

    /* Panel colors */
    --panel: var(--color-white);
    --panel-accent: var(--color-mystic);

    /* Surface colors */
    --surface: var(--color-gray-300);
    --surface-accent: var(--color-blue-500);

    /* Text colors */
    --text-primary: var(--color-vulcan);
    --text-secondary: var(--color-gray-700);
  }
}

/* Custom variants */
@custom-variant dark (&:where(.theme-dark, .theme-dark *, [data-theme=dark], [data-theme=dark] *));
@custom-variant light (&:where(.theme-light, .theme-light *, [data-theme=light], [data-theme=light] *));
@custom-variant disabled-within (&:has(input:is(:disabled), textarea:is(:disabled), button:is(:disabled)));

/* Semantic color tokens - use inline because they reference var() */
@theme inline {
  /* Primary colors */
  --color-primary: var(--primary);
  --color-primary-active: var(--primary-active);
  --color-primary-hover: var(--primary-hover);
  --color-primary-inactive: var(--primary-inactive);

  /* Secondary colors */
  --color-secondary: var(--secondary);
  --color-secondary-active: var(--secondary-active);
  --color-secondary-hover: var(--secondary-hover);
  --color-secondary-inactive: var(--secondary-inactive);

  /* Success colors */
  --color-success: var(--success);
  --color-success-active: var(--success-active);
  --color-success-hover: var(--success-hover);
  --color-success-background: var(--success-background);

  /* Error colors */
  --color-error: var(--error);
  --color-error-active: var(--error-active);
  --color-error-hover: var(--error-hover);
  --color-error-background: var(--error-background);

  /* Warning colors */
  --color-warning: var(--warning);
  --color-warning-active: var(--warning-active);
  --color-warning-hover: var(--warning-hover);
  --color-warning-background: var(--warning-background);

  /* Info colors */
  --color-info: var(--info);
  --color-info-active: var(--info-active);
  --color-info-hover: var(--info-hover);
  --color-info-background: var(--info-background);

  /* Panel colors */
  --color-panel: var(--panel);
  --color-panel-accent: var(--panel-accent);

  /* Surface colors */
  --color-surface: var(--surface);
  --color-surface-accent: var(--surface-accent);

  /* Text colors */
  --color-text-primary: var(--text-primary);
  --color-text-secondary: var(--text-secondary);
}

/* Static theme tokens - emits CSS custom properties for runtime access */
@theme static {
  /* Fonts */
  --font-sans: Inter, sans-serif;
  --font-mono: Fira Code, monospace;

  /* Font sizes */
  --text-xs: 0.625rem; /* 10px */
  --text-xs--line-height: 1rem;
  --text-sm: 0.75rem; /* 12px */
  --text-sm--line-height: 1rem;
  --text-base: 0.875rem; /* 14px */
  --text-base--line-height: 1.25rem;
  --text-lg: 1rem; /* 16px */
  --text-lg--line-height: 1.5rem;

  /* Spacing */
  --spacing: 0.25rem;

  /* Border radius */
  --radius-xs: 0.125rem;
  --radius-sm: 0.25rem;
  --radius-md: 0.375rem;
  --radius-lg: 0.5rem;
  --radius-xl: 0.75rem;
  --radius-2xl: 1rem;
  --radius-3xl: 1.5rem;
  --radius-4xl: 2rem;

  /* Shadows */
  --shadow-2xs: 0 1px rgb(0 0 0 / 0.05);
  --shadow-xs: 0 1px 2px 0 rgb(0 0 0 / 0.05);
  --shadow-sm: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
  --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
  --shadow-lg:
    0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
  --shadow-xl:
    0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
  --shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25);

  /* Base colors */
  --color-white: #ffffff;
  --color-black: #000000;

  /* Gray scale */
  --color-gray-*: initial;
  --color-gray-100: #f7f7fa;
  --color-gray-200: #e6e6f0;
  --color-gray-300: #c9c9d6;
  --color-gray-400: #77778c;
  --color-gray-500: #5c5c73;
  --color-gray-600: #3d3d4d;
  --color-gray-700: #242433;
  --color-gray-800: #1e1e2e;
  --color-gray-900: #11111f;
  --color-gray-950: #02020f;

  /* Magenta */
  --color-magenta-*: initial;
  --color-magenta-100: #fae5f6;
  --color-magenta-200: #f1bfe9;
  --color-magenta-300: #e480d3;
  --color-magenta-400: #d740be;
  --color-magenta-500: #c900a8;
  --color-magenta-600: #ab018f;
  --color-magenta-700: #8c0276;
  --color-magenta-800: #6e025c;
  --color-magenta-900: #4f0343;
  --color-magenta-950: #31042a;

  /* Pink */
  --color-pink-*: initial;
  --color-pink-100: #fde5f1;
  --color-pink-200: #f9bfdb;
  --color-pink-300: #f480b7;
  --color-pink-400: #ee4094;
  --color-pink-500: #de006b;
  --color-pink-600: #bb015a;
  --color-pink-700: #98014a;
  --color-pink-800: #740239;
  --color-pink-900: #510229;
  --color-pink-950: #2e0318;

  /* Lime */
  --color-lime-*: initial;
  --color-lime-100: #f4fae5;
  --color-lime-200: #e3f3bf;
  --color-lime-300: #c6e880;
  --color-lime-400: #aadc40;
  --color-lime-500: #8ed000;
  --color-lime-600: #78b001;
  --color-lime-700: #628f01;
  --color-lime-800: #4c6f02;
  --color-lime-900: #364e02;
  --color-lime-950: #202e03;

  /* Teal */
  --color-teal-*: initial;
  --color-teal-100: #e5fbf9;
  --color-teal-200: #bff6f0;
  --color-teal-300: #80ede0;
  --color-teal-400: #40e5d1;
  --color-teal-500: #00dcc2;
  --color-teal-600: #00c2ab;
  --color-teal-700: #019a88;
  --color-teal-800: #017365;
  --color-teal-900: #024b42;
  --color-teal-950: #02231f;

  /* Cyan */
  --color-cyan-*: initial;
  --color-cyan-100: #e5f9fe;
  --color-cyan-200: #bff0fb;
  --color-cyan-300: #80e2f8;
  --color-cyan-400: #40d3f4;
  --color-cyan-500: #00c5f0;
  --color-cyan-600: #01a7cb;
  --color-cyan-700: #0289a6;
  --color-cyan-800: #036b82;
  --color-cyan-900: #044d5d;
  --color-cyan-950: #052f38;

  /* Violet */
  --color-violet-*: initial;
  --color-violet-100: #f0e8fd;
  --color-violet-200: #dac5f9;
  --color-violet-300: #b58bf3;
  --color-violet-400: #9152ee;
  --color-violet-500: #6c18e8;
  --color-violet-600: #5b14c5;
  --color-violet-700: #4b10a1;
  --color-violet-800: #3a0d7e;
  --color-violet-900: #2a095b;
  --color-violet-950: #190537;

  /* Purple */
  --color-purple-*: initial;
  --color-purple-100: #f3e5fc;
  --color-purple-200: #e2bff7;
  --color-purple-300: #c580f0;
  --color-purple-400: #a840e8;
  --color-purple-500: #8b00e0;
  --color-purple-600: #7501bc;
  --color-purple-700: #5f0298;
  --color-purple-800: #490274;
  --color-purple-900: #330350;
  --color-purple-950: #1d042d;

  /* Red */
  --color-red-*: initial;
  --color-red-100: #fce5e6;
  --color-red-200: #f7bfc1;
  --color-red-300: #f08083;
  --color-red-400: #e84045;
  --color-red-500: #e00007;
  --color-red-600: #b70006;
  --color-red-700: #8e0005;
  --color-red-800: #660104;
  --color-red-900: #3d0103;
  --color-red-950: #200204;

  /* Orange */
  --color-orange-*: initial;
  --color-orange-100: #fef3e5;
  --color-orange-200: #fde1bf;
  --color-orange-300: #fbc280;
  --color-orange-400: #f8a340;
  --color-orange-500: #f68500;
  --color-orange-600: #cb6e00;
  --color-orange-700: #9f5701;
  --color-orange-800: #743f01;
  --color-orange-900: #482802;
  --color-orange-950: #251602;

  /* Yellow */
  --color-yellow-*: initial;
  --color-yellow-100: #fff9e5;
  --color-yellow-200: #fff1bf;
  --color-yellow-300: #ffe380;
  --color-yellow-400: #ffd440;
  --color-yellow-500: #ffc600;
  --color-yellow-600: #d2a300;
  --color-yellow-700: #a58001;
  --color-yellow-800: #785e01;
  --color-yellow-900: #4b3b02;
  --color-yellow-950: #261f03;

  /* Green */
  --color-green-*: initial;
  --color-green-100: #eef8e9;
  --color-green-200: #d5efc8;
  --color-green-300: #aadf91;
  --color-green-400: #80ce5b;
  --color-green-500: #55be24;
  --color-green-600: #469d1d;
  --color-green-700: #377c16;
  --color-green-800: #275c10;
  --color-green-900: #183b09;
  --color-green-950: #091a02;

  /* Blue */
  --color-blue-*: initial;
  --color-blue-100: #e7efff;
  --color-blue-200: #c3d7ff;
  --color-blue-300: #87aeff;
  --color-blue-400: #4c86ff;
  --color-blue-500: #105eff;
  --color-blue-600: #0d4ed2;
  --color-blue-700: #0a3da6;
  --color-blue-800: #082d79;
  --color-blue-900: #051c4c;
  --color-blue-950: #041028;

  /* Named colors */
  --color-black-pearl: #02020f;
  --color-athens-gray: #f7f7fa;
  --color-mystic: #e6e6f0;
  --color-vulcan: #11111f;
  --color-charade: #242433;
  --color-waterloo: #77778c;
  --color-anakiwa: #93b6ff;
}
```

### 5. Set the default theme class on `<html>`

In `src/app/layout.tsx`, add the theme class to the root `<html>` tag (set it once):

```tsx
<html lang="en" className="theme-dark">
```

Swap `theme-dark` for `theme-light` to default to light mode.

### 6. Wrap your app with ThemeProvider

Server Components can't host React context, so create a client `Providers` component and use it from your existing `src/app/layout.tsx`. (If you already have a providers file, wrap its contents with `<ThemeProvider>` instead of creating a new one.)

```tsx
// src/app/providers.tsx  — new client component
'use client';

import { ThemeProvider, theme } from 'reablocks';
import type { ReactNode } from 'react';

export function Providers({ children }: { children: ReactNode }) {
  return <ThemeProvider theme={theme}>{children}</ThemeProvider>;
}

// src/app/layout.tsx  — edit your existing layout:
//   1. import the Providers component
//   2. add the theme class to <html>
//   3. wrap {children} with <Providers>
import { Providers } from './providers';

return function RootLayout({ children }: { children: ReactNode }) {
  return (
    <html lang="en" className="theme-dark">
      <body>
        <Providers>{children}</Providers>
      </body>
    </html>
  );
}
```

## Verify

After the changes, confirm each item:

- [ ] `reablocks`, `tailwindcss` (v4) and `@tailwindcss/postcss` are in `package.json`.
- [ ] `src/app/globals.css` starts with `@import "tailwindcss";`, then the `@source` line, then the `--reablocks-theme` token block.
- [ ] `src/app/globals.css` is imported by the app entry so the styles actually load.
- [ ] `src/app/layout.tsx` has `className="theme-dark"` on the `<html>` tag.
- [ ] The app root is wrapped in `<ThemeProvider theme={theme}>`.
- [ ] A `<Button>` imported from `reablocks` renders styled (rounded corners, blue primary fill).

Report each item as ✅ or ❌ when you are done.