Setup Guide
One-time setup for using BLUEPRINT // 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 BLUEPRINT // NEXT design tokens to your globals.css. These define colors, fonts, and animation tokens used by every component in the theme.
@theme {
/* ── Colors ─────────────────────────────────────── */
--color-bp-bg: #060E1C;
--color-bp-bg-2: #0A1628;
--color-bp-surface: #0D1E38;
--color-bp-border: #1A3A5C;
--color-bp-cyan: #00C8F0;
--color-bp-cyan-dim: #0A7EA0;
--color-bp-cyan-glow: rgba(0,200,240,0.12);
--color-bp-amber: #F5A623;
--color-bp-amber-dim: #B87B18;
--color-bp-text: #E0ECF4;
--color-bp-text-2: #8AAEC8;
--color-bp-muted: #4A6F8A;
--color-bp-faint: #1E3A52;
--color-bp-grid-line: rgba(0,200,240,0.06);
--color-bp-grid-major: rgba(0,200,240,0.10);
/* ── Fonts ───────────────────────────────────────── */
--font-mono: var(--font-space-mono);
--font-body: var(--font-inter);
/* ── Animations ─────────────────────────────────── */
--animate-ticker: bpTicker 40s linear infinite;
}Each component may need its own CSS classes in your globals.css. Copy the styles for the components you use.
/* ─── UI Primitives: Button ──────────────────────── */
.bp-btn {
display: inline-flex;
align-items: center;
justify-content: center;
font-family: var(--font-mono);
font-weight: 700;
letter-spacing: 0.12em;
text-transform: uppercase;
border: 1px solid transparent;
cursor: pointer;
transition: all 0.18s;
white-space: nowrap;
text-decoration: none;
}
.bp-btn-primary {
background: var(--color-bp-amber);
color: var(--color-bp-bg);
border-color: var(--color-bp-amber);
}
.bp-btn-primary:hover { background: var(--color-bp-amber-dim); border-color: var(--color-bp-amber-dim); }
.bp-btn-secondary {
background: transparent;
color: var(--color-bp-cyan);
border-color: var(--color-bp-cyan-dim);
}
.bp-btn-secondary:hover {
background: rgba(0,200,240,0.08);
border-color: var(--color-bp-cyan);
}
.bp-btn-ghost {
background: transparent;
color: var(--color-bp-cyan);
border-color: transparent;
}
.bp-btn-ghost:hover { color: var(--color-bp-text); }
.bp-btn-sm { font-size: 0.6rem; padding: 7px 16px; }
.bp-btn-md { font-size: 0.65rem; padding: 10px 22px; }
.bp-btn-lg { font-size: 0.68rem; padding: 12px 28px; }
.bp-btn:focus-visible {
outline: 2px solid var(--color-bp-cyan);
outline-offset: 2px;
}
.bp-btn[aria-disabled="true"] {
cursor: not-allowed;
opacity: 0.45;
pointer-events: none;
}
.bp-btn[aria-disabled="true"]:focus-visible {
outline: none;
}/* ─── UI Primitives: Badge ───────────────────────── */
.bp-badge {
display: inline-flex;
align-items: center;
font-family: var(--font-mono);
font-size: 0.6rem;
font-weight: 400;
letter-spacing: 0.1em;
text-transform: uppercase;
padding: 3px 10px;
border: 1px solid;
}
.bp-badge-cyan { color: var(--color-bp-cyan); border-color: var(--color-bp-cyan-dim); background: rgba(0,200,240,0.08); }
.bp-badge-amber { color: var(--color-bp-amber); border-color: var(--color-bp-amber-dim); background: rgba(245,166,35,0.08); }
.bp-badge-ghost { color: var(--color-bp-muted); border-color: var(--color-bp-border); background: transparent; }
.bp-badge-surface { color: var(--color-bp-text-2); border-color: var(--color-bp-border); background: var(--color-bp-surface); }
.bp-badge-muted { color: var(--color-bp-faint); border-color: var(--color-bp-faint); background: transparent; }/* ─── Registration Marks ─────────────────────────── */
.bp-reg-mark-br {
position: absolute;
width: 10px;
height: 10px;
border-color: var(--color-bp-cyan);
border-style: solid;
}
.bp-reg-mark-tl { top: -1px; left: -1px; border-width: 1px 0 0 1px; }
.bp-reg-mark-tr { top: -1px; right: -1px; border-width: 1px 1px 0 0; }
.bp-reg-mark-bl { bottom: -1px; left: -1px; border-width: 0 0 1px 1px; }
.bp-reg-mark-br { bottom: -1px; right: -1px; border-width: 0 1px 1px 0; }
/* ─── UI Primitives: Card ────────────────────────── */
.bp-card {
border: 1px dashed var(--color-bp-border);
background: var(--color-bp-surface);
position: relative;
}
.bp-card-header {
padding: 20px 24px 16px;
border-bottom: 1px solid var(--color-bp-faint);
}
.bp-card-body { padding: 24px; }
.bp-card-footer {
padding: 16px 24px 20px;
border-top: 1px solid var(--color-bp-faint);
}/* ─── UI Primitives: Text ────────────────────────── */
.bp-text-body {
font-family: var(--font-body);
font-size: 0.9rem;
line-height: 1.75;
color: var(--color-bp-text-2);
}
.bp-text-caption {
font-family: var(--font-mono);
font-size: 0.68rem;
color: var(--color-bp-muted);
letter-spacing: 0.04em;
}
.bp-text-label {
font-family: var(--font-mono);
font-size: 0.6rem;
font-weight: 700;
letter-spacing: 0.14em;
text-transform: uppercase;
color: var(--color-bp-muted);
}
.bp-text-code {
font-family: var(--font-mono);
font-size: 0.8rem;
color: var(--color-bp-cyan);
letter-spacing: 0.04em;
}Button
Technical dark-mode button with primary, secondary, and ghost variants in three sizes. Renders as a Next.js Link when an href is provided.
Badge
Technical badge for status indicators and tags in the BLUEPRINT dark engineering palette.
Card
Engineering-blueprint card with registration-mark corner accents at all four corners. Composable with any children.
Text
Polymorphic text primitive with body, caption, label, and code variants styled for the BLUEPRINT dark technical palette.