Setup Guide
One-time setup for using FEAST // NEXT components. Add these to your project, then copy any component from the theme.
The cn() utility combines clsx and tailwind-merge for conditional class names. Install both packages.
npm install clsx tailwind-mergeCreate lib/utils.ts with the cn() helper. Every component imports this for class name merging.
import { type ClassValue, clsx } from 'clsx'
import { twMerge } from 'tailwind-merge'
export function cn(...inputs: ClassValue[]): string {
return twMerge(clsx(inputs))
}Add the FEAST // NEXT design tokens to your globals.css. These define colors, fonts, and animation tokens used by every component in the theme.
@theme {
/* ── Colors ─────────────────────────────────────────── */
--color-feast-bg-deep: #0d0b09;
--color-feast-bg-base: #131008;
--color-feast-bg-surface: #1a1510;
--color-feast-bg-card: #201a12;
--color-feast-bg-card-hover: #271f16;
--color-feast-accent: #C8922A;
--color-feast-accent-dim: #a07220;
--color-feast-accent-glow: rgba(200, 146, 42, 0.15);
--color-feast-gold-light: #e8b96a;
--color-feast-text: #f0ebe2;
--color-feast-text-secondary: #b8a98a;
--color-feast-text-muted: #7a6b52;
--color-feast-text-faint: #4a3f2e;
--color-feast-border: rgba(200, 146, 42, 0.18);
--color-feast-border-soft: rgba(200, 146, 42, 0.08);
/* ── Fonts ───────────────────────────────────────────── */
--font-display: 'Playfair Display', georgia, serif;
--font-body: var(--font-dm-sans);
/* ── Animations ──────────────────────────────────────── */
--animate-reveal: feast-reveal 0.6s ease both;
}Each component may need its own CSS classes in your globals.css. Copy the styles for the components you use.
/* ─── Buttons ────────────────────────────────────────── */
.btn-base {
display: inline-flex;
align-items: center;
justify-content: center;
font-family: var(--font-body);
font-weight: 500;
cursor: pointer;
text-decoration: none;
white-space: nowrap;
letter-spacing: 0.06em;
text-transform: uppercase;
border: none;
border-radius: 0;
transition: background 0.2s, color 0.2s, border-color 0.2s;
line-height: 1;
}
.btn-sm { font-size: 0.75rem; padding: 9px 18px; }
.btn-md { font-size: 0.875rem; padding: 13px 28px; }
.btn-lg { font-size: 0.875rem; padding: 16px 36px; }
.btn-primary {
background: var(--color-feast-accent);
color: var(--color-feast-bg-deep);
border: none;
}
.btn-primary:hover { background: var(--color-feast-gold-light); color: var(--color-feast-bg-deep); text-decoration: none; }
.btn-secondary {
background: transparent;
color: var(--color-feast-text-secondary);
border: 1px solid var(--color-feast-border);
}
.btn-secondary:hover { border-color: var(--color-feast-accent); color: var(--color-feast-text); text-decoration: none; }
.btn-ghost {
background: transparent;
color: var(--color-feast-text-secondary);
border: 1px solid var(--color-feast-border);
}
.btn-ghost:hover { border-color: var(--color-feast-accent); color: var(--color-feast-text); text-decoration: none; }/* ─── Badges ─────────────────────────────────────────── */
.feast-badge {
display: inline-flex;
align-items: center;
font-family: var(--font-body);
font-size: 0.6875rem;
font-weight: 500;
letter-spacing: 0.12em;
text-transform: uppercase;
padding: 4px 10px;
border: 1px solid transparent;
border-radius: 0;
}
.feast-badge--gold {
background: rgba(200, 146, 42, 0.12);
color: var(--color-feast-gold-light);
border-color: rgba(200, 146, 42, 0.3);
}
.feast-badge--dark {
background: rgba(240, 235, 226, 0.06);
color: var(--color-feast-text-secondary);
border-color: rgba(240, 235, 226, 0.12);
}
.feast-badge--amber {
background: rgba(200, 146, 42, 0.08);
color: var(--color-feast-accent);
border-color: rgba(200, 146, 42, 0.2);
}
.feast-badge--warm {
background: rgba(122, 107, 82, 0.15);
color: var(--color-feast-text-muted);
border-color: rgba(122, 107, 82, 0.25);
}
.feast-badge--ember {
background: rgba(160, 114, 32, 0.12);
color: var(--color-feast-accent-dim);
border-color: rgba(160, 114, 32, 0.28);
}/* ─── Card ───────────────────────────────────────────── */
.feast-card {
background: var(--color-feast-bg-card);
border: 1px solid var(--color-feast-border-soft);
border-radius: 0;
transition: background 0.25s;
}
.feast-card:hover { background: var(--color-feast-bg-card-hover); }
.feast-card-header {
padding: 20px 24px 16px;
border-bottom: 1px solid var(--color-feast-border-soft);
}
.feast-card-body { padding: 20px 24px; }
.feast-card-footer {
padding: 16px 24px 20px;
border-top: 1px solid var(--color-feast-border-soft);
}/* ─── Text Variants ──────────────────────────────────── */
.feast-text-body {
font-size: 0.9375rem;
font-weight: 300;
line-height: 1.8;
color: var(--color-feast-text-secondary);
}
.feast-text-caption {
font-size: 0.8125rem;
font-weight: 400;
color: var(--color-feast-text-muted);
line-height: 1.6;
}
.feast-text-label {
font-size: 0.6875rem;
font-weight: 500;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--color-feast-text-muted);
}
.feast-text-code {
font-family: monospace;
font-size: 0.85rem;
color: var(--color-feast-accent);
background: rgba(200, 146, 42, 0.08);
padding: 2px 6px;
}Button
Rich dark-mode button with gold-accented primary, secondary, and ghost variants in three sizes. Renders as a Next.js Link when an href is provided.
Badge
Gold-toned badge for category and status labels in the FEAST dark culinary palette.
Card
Composable dark card with header, body, and footer sub-components in the FEAST culinary aesthetic.
Text
Polymorphic text primitive with body, caption, label, and code variants styled for the FEAST dark culinary palette.