Nexus AI

Components Guide

The template ships 70+ components. They fall into a few groups under src/components/. The ui/ folder holds the shadcn/ui primitives; everything else is built on top of them.

Folder map

src/components/
├── ui/          shadcn/ui primitives (button, card, dialog, table, …)
├── layout/      AppShell, Sidebar, Topbar, command palette, logo, user menu
├── common/      StatCard, PageHeader, EmptyState, StatusBadge, ActivityFeed
├── charts/      Line / Area / Bar / Donut / Mixed wrappers + primitives
├── tables/      DataTable (TanStack Table)
├── forms/       PasswordInput, social buttons
├── ai/          ModelSelector, TokenCounter, UsageMeter, AgentStatusIndicator…
└── <page area>/ analytics, prompts, playground, users, billing, settings, …

Common components

StatCard

src/components/common/stat-card.tsx — an animated metric card with optional trend, icon and sparkline.

import { Activity } from "lucide-react";
import { StatCard } from "@/components/common/stat-card";

<StatCard
  label="Total API Calls"
  value={2_418_902}
  change={14.2}            // % vs last period
  icon={Activity}
  sparkline={[12, 18, 14, 22, 30]}
  // invertTrend            // set when "down" is good (e.g. cost)
/>;

PageHeader

src/components/common/page-header.tsx — title, breadcrumbs and an actions slot. Used at the top of every page.

<PageHeader
  title="Users"
  description="Manage everyone in your workspace."
  breadcrumbs={[{ label: "Dashboard", href: "/dashboard" }, { label: "Users" }]}
  actions={<Button>Invite user</Button>}
/>

StatusBadge

src/components/common/status-badge.tsx — maps a status string (active, paused, paid, pro, admin, …) to a consistent color tone automatically.

<StatusBadge status="active" />     {/* green dot + label */}
<StatusBadge status="pro" dot={false} />

EmptyState / ActivityFeed

EmptyState (icon + message + CTA) for empty lists; ActivityFeed renders a vertical timeline of events.

Charts

All wrappers live in src/components/charts/ and use Recharts with shared theming. They accept a data array and a series config.

import { LineChart } from "@/components/charts/line-chart";

<LineChart
  data={apiUsageData}                       // [{ date, calls }, …]
  series={[{ key: "calls", label: "API calls" }]}
  valueFormatter={(v) => v.toLocaleString()}
/>;

Available: LineChart, AreaChart (stacked), StackedBarChart, CategoryBarChart, DonutChart (+ ChartLegend), MixedChart (bars + line). Colors come from the --chart-1…6 tokens; see Customization.

Charts render after mount (via the useMounted hook) to avoid Recharts' 0×0-size warning during server rendering — keep that pattern if you add new chart wrappers.

DataTable

src/components/tables/data-table.tsx — a TanStack Table v8 wrapper with sorting, pagination, column visibility, optional row selection and a bulk-action bar.

import { DataTable } from "@/components/tables/data-table";

<DataTable
  columns={columns}            // TanStack ColumnDef[]
  data={rows}
  pageSize={10}
  enableRowSelection
  onRowClick={(row) => router.push(`/users/${row.id}`)}
  renderBulkActions={(selected, clear) => (
    <Button onClick={() => { /* … */ clear(); }}>Delete {selected.length}</Button>
  )}
  toolbar={<Input placeholder="Search…" />}
/>;

See src/components/users/users-view.tsx and src/components/prompts/prompts-view.tsx for full column examples.

AI components

In src/components/ai/:

  • ModelSelector — dropdown of models with provider dot + per-1K cost.
  • TokenCounter — horizontal usage bar with limit and percentage.
  • UsageMeter — circular quota progress meter.
  • AgentStatusIndicator — colored status pill (active/paused/training/error).
  • CostMetric — currency value with trend.
  • ModelCard — model spec card with set-primary action.

Forms

Forms use React Hook Form + Zod. Pattern (from the auth pages):

const schema = z.object({ email: z.string().email() });
const { register, handleSubmit, formState: { errors } } = useForm({
  resolver: zodResolver(schema),
});

src/components/forms/password-input.tsx provides a show/hide password field.

Adding a component

Put shared UI in the closest matching folder (common/, ai/, charts/…), or a new <page-area>/ folder for page-specific views. Reuse the cn() helper from @/lib/utils for class merging, and keep client-only logic behind "use client".

Next: Mock Data →