Installation
Install Nyxis in any modern React project.
Nyxis ships through a shadcn-compatible registry. You
install components and recipes with the standard shadcn CLI; they
land as plain TypeScript files in your repo and are yours to edit.
Requirements
- React 18 or 19
- Tailwind CSS v4
- shadcn CLI (already in the shadcn ecosystem — installed on demand
via
npx)
1. Bootstrap your project with shadcn
Start from any modern React-capable project. Then run shadcn’s
initialiser — it writes components.json, lib/utils.ts, the design
tokens, and the TypeScript path alias config Nyxis components rely on:
# Pick the framework starter you prefer:
npx create-next-app@latest # Next.js (App Router)
npm create astro@latest # Astro 5 + React + Tailwind
npx sv create # SvelteKit
npm create vite@latest # Vite + React
# Then, inside the project:
npx shadcn@latest init
shadcn detects the framework automatically and writes the config in the right place. If detection fails (e.g. Astro without React enabled), shadcn prints what’s missing — usually a Tailwind config or the React integration.
Astro gotcha — path aliases. Astro’s default
tsconfig.jsondoesn’t ship withcompilerOptions.paths, soshadcn initfails withCould not find valid path aliases. Add this once and re-run:{ "extends": "astro/tsconfigs/strict", "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["./src/*"] } } }
2. Install your first component
You don’t need to install anything else by hand. Pick a component and the
shadcn CLI will install everything it needs — including @nyxis/core
when applicable — in one go:
npx shadcn@latest add https://nyxisai.vercel.app/r/chat-thread.json
What this single command does, in order:
- Resolves the cascading registry dependencies (
chat-threadpullschat-message, which pullsutils). - Installs every npm dependency declared by those items
(
@nyxis/core,lucide-react, etc.). - Drops the source files into
src/components/nyxis/<name>.tsxandsrc/lib/utils.ts.
Stateless components (e.g. chat-message) don’t need @nyxis/core and
won’t pull it. Stateful ones (chat-thread, agent-roster) declare it
in their manifest, so the CLI installs it for you. You never pnpm add @nyxis/core manually unless you want it without any component.
3. (Optional) Install the theme system
nyxis-ui is a separate, tiny npm package that ships:
- The design tokens stylesheet (
nyxis-ui/styles.css). - The five-mode theme runtime (
light,dark,dim,high-contrast,system) and the FOUC-safe inline script.
Components render fine on shadcn’s default tokens, so nyxis-ui is
optional. Install it when you want the Nyxis brand color, the dim
and high-contrast themes, or the cross-tab theme switcher:
pnpm add nyxis-ui
In your global CSS:
@import 'tailwindcss';
@import 'nyxis-ui/styles.css';
The theme runtime needs a tiny inline script to run before any markup paints, otherwise users see a flash of the wrong theme. Pick the snippet for your framework:
Next.js (App Router)
import { getThemeScript } from 'nyxis-ui/theme';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<head>
<script dangerouslySetInnerHTML={{ __html: getThemeScript() }} suppressHydrationWarning />
</head>
<body>{children}</body>
</html>
);
}
Astro
---
import { getThemeScript } from 'nyxis-ui/theme';
---
<!doctype html>
<html lang="en">
<head>
<script is:inline set:html={getThemeScript()} />
</head>
<body>
<slot />
</body>
</html>
is:inline is required so Astro doesn’t bundle the script — it has to run synchronously before the body paints.
SvelteKit
<!-- Replace %sveltekit.head% wrapper with: -->
<script>%nyxis.theme%</script>
%sveltekit.head%
import { getThemeScript } from 'nyxis-ui/theme';
export async function handle({ event, resolve }) {
return resolve(event, {
transformPageChunk: ({ html }) => html.replace('%nyxis.theme%', getThemeScript()),
});
}
Vite (plain React)
import { getThemeScript } from 'nyxis-ui/theme';
const s = document.createElement('script');
s.textContent = getThemeScript();
document.head.prepend(s);
// then the usual createRoot(...).render(<App />)
The theme switcher itself is a registry item:
npx shadcn@latest add https://nyxisai.vercel.app/r/theme-toggle.json
4. Add more components
Pick anything else you need from the registry catalog:
npx shadcn@latest add https://nyxisai.vercel.app/r/agent-roster.json
npx shadcn@latest add https://nyxisai.vercel.app/r/rag-pipeline.json
Same flow as step 2 — the CLI:
- Resolves cascading registry dependencies (e.g.
agent-rosterpullsagent-card, which pullsagent-status-badge, which pullsutils). - Installs npm
dependenciesdeclared by each item (@nyxis/core,lucide-react,framer-motion, etc.). - Drops source files into
src/components/nyxis/<name>.tsxandsrc/lib/utils.ts.
Then import them as local modules. Next.js / SvelteKit / Vite treat them as ordinary client components:
'use client';
import { ChatMessage } from '@/components/nyxis/chat-message';
import { ChatThread } from '@/components/nyxis/chat-thread';
import { useChat } from '@nyxis/core';
export function Chat() {
const { messages, append } = useChat({ api: '/api/chat' });
return (
<ChatThread messages={messages}>
{messages.map((m) => (
<ChatMessage key={m.id} role={m.role}>
{m.content}
</ChatMessage>
))}
</ChatThread>
);
}
Astro ships zero JS by default, so interactive Nyxis components must be hydrated as islands. Pick the directive that matches your need (client:load for above-the-fold, client:visible for below):
---
import { Chat } from '../components/Chat';
---
<Chat client:load />
This site itself is built on Astro and dogfoods every component it documents — see the live demos on the components pages.
Editing what you installed
Every file the CLI writes is plain TypeScript and plain Tailwind. There is no theming abstraction to fight. Change a class, drop a prop, swap a component — it is your file now.
Next steps
- Read the Registry guide to learn how the catalog is organised and how to install many items at once.
- Read the Theming guide for the five-mode token system.
- Browse the catalog from the sidebar.