DECK // NEXT

Setup Guide

One-time setup for using DECK // NEXT components. Add these to your project, then copy any component from the theme.

1
Install dependencies

The cn() utility combines clsx and tailwind-merge for conditional class names. Install both packages.

BASH
npm install clsx tailwind-merge
2
Add utility function

Create lib/utils.ts with the cn() helper. Every component imports this for class name merging.

TS
import { type ClassValue, clsx } from 'clsx'
import { twMerge } from 'tailwind-merge'

export function cn(...inputs: ClassValue[]): string {
  return twMerge(clsx(inputs))
}
3
Add design tokens

Add the DECK // NEXT design tokens to your globals.css. These define colors, fonts, and animation tokens used by every component in the theme.

CSS
@theme {
  /* ── Colors ─────────────────────────────────────────── */
  --color-deck-bg:           #0c0b09;
  --color-deck-surface:      #141310;
  --color-deck-lift:         #1c1a16;
  --color-deck-card:         #1f1d19;
  --color-deck-ink:          #ede9e2;
  --color-deck-white:        #f5f1ea;
  --color-deck-muted:        #8a8477;
  --color-deck-dim:          #4a4740;
  --color-deck-orange:       #FF5C00;
  --color-deck-orange-dark:  #cc4a00;
  --color-deck-yellow:       #DEFF00;
  --color-deck-yellow-soft:  rgba(222, 255, 0, 0.10);
  --color-deck-border:       rgba(255, 255, 255, 0.07);
  --color-deck-border-rough: rgba(255, 255, 255, 0.12);

  /* ── Fonts ──────────────────────────────────────────── */
  --font-display: var(--font-permanent-marker, 'Permanent Marker'), cursive;
  --font-mono:    var(--font-ibm-plex-mono, 'IBM Plex Mono'), monospace;
  --font-body:    var(--font-ibm-plex-mono, 'IBM Plex Mono'), monospace;

  /* ── Animations ─────────────────────────────────────── */
  --animate-spray-drip:  spray-drip 2.5s ease-in infinite;
  --animate-grain-shift: grain-shift 0.8s steps(2) infinite;
}
4
Add component styles

Each component may need its own CSS classes in your globals.css. Copy the styles for the components you use.

CSS
/* ─── Buttons ────────────────────────────────────────── */

.btn-base {
  display:         inline-flex;
  align-items:     center;
  justify-content: center;
  gap:             8px;
  font-family:     var(--font-mono);
  font-weight:     700;
  border:          none;
  cursor:          pointer;
  text-decoration: none;
  line-height:     1;
  letter-spacing:  0.06em;
  transition:      transform 0.1s ease, box-shadow 0.1s ease;
  white-space:     nowrap;
  clip-path: polygon(
    0% 3px, 3px 0%, calc(100% - 3px) 0%, 100% 3px,
    100% calc(100% - 3px), calc(100% - 3px) 100%, 3px 100%, 0% calc(100% - 3px)
  );
}

.btn-base:hover  { transform: translate(-2px, -2px); text-decoration: none; }

.btn-base:active { transform: translate(2px, 2px) !important; box-shadow: none !important; }

.btn-sm { font-size: 12px; padding: 8px 16px; }

.btn-md { font-size: 13px; padding: 12px 24px; }

.btn-lg { font-size: 14px; padding: 14px 32px; }

.btn-primary {
  background: var(--color-deck-orange);
  color:      #000;
  box-shadow: 4px 4px 0 rgba(255, 92, 0, 0.25), 8px 8px 0 rgba(0,0,0,0.3);
}

.btn-primary:hover {
  box-shadow: 6px 6px 0 rgba(255, 92, 0, 0.3), 10px 10px 0 rgba(0,0,0,0.3);
  color: #000;
}

.btn-secondary {
  background:  var(--color-deck-lift);
  color:       var(--color-deck-ink);
  border:      1px solid var(--color-deck-border-rough);
  box-shadow:  3px 3px 0 rgba(0,0,0,0.3);
}

.btn-secondary:hover {
  box-shadow: 5px 5px 0 rgba(0,0,0,0.3);
  color: var(--color-deck-ink);
}

.btn-ghost {
  background:  transparent;
  color:       var(--color-deck-ink);
  border:      1.5px solid var(--color-deck-border-rough);
  box-shadow:  none;
}

.btn-ghost:hover {
  border-color: var(--color-deck-orange);
  color:        var(--color-deck-orange);
}
CSS
/* ─── Badges ─────────────────────────────────────────── */

.badge {
  display:        inline-flex;
  align-items:    center;
  gap:            4px;
  font-family:    var(--font-mono);
  font-weight:    700;
  font-size:      10px;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  padding:        3px 10px;
  border:         1px solid transparent;
  clip-path: polygon(
    0% 2px, 2px 0%, calc(100% - 2px) 0%, 100% 2px,
    100% calc(100% - 2px), calc(100% - 2px) 100%, 2px 100%, 0% calc(100% - 2px)
  );
}

.badge--orange { background: rgba(255, 92, 0, 0.12); color: var(--color-deck-orange); border-color: rgba(255, 92, 0, 0.35); }

.badge--yellow { background: rgba(222, 255, 0, 0.08); color: var(--color-deck-yellow); border-color: rgba(222, 255, 0, 0.2); }

.badge--ink    { background: rgba(237, 233, 226, 0.08); color: var(--color-deck-ink);    border-color: rgba(237, 233, 226, 0.15); }

.badge--dim    { background: rgba(74, 71, 64, 0.2);    color: var(--color-deck-muted);  border-color: rgba(74, 71, 64, 0.4); }
CSS
/* ─── Text Variants ──────────────────────────────────── */

.text-body    { font-family: var(--font-mono); font-size: 13px; line-height: 1.7; font-weight: 400; color: var(--color-deck-muted); }

.text-caption { font-family: var(--font-mono); font-size: 12px; font-weight: 400; color: var(--color-deck-dim); }

.text-label   { font-family: var(--font-mono); font-size: 10px; font-weight: 700; letter-spacing: 0.2em; text-transform: uppercase; color: var(--color-deck-dim); }

.text-code    { font-family: var(--font-mono); font-size: 12px; color: var(--color-deck-orange); }
CSS
/* ─── Features Section ───────────────────────────────── */

.deck-card {
  background:  var(--color-deck-card);
  padding:     32px 28px;
  border:      1px solid var(--color-deck-border);
  position:    relative;
  overflow:    hidden;
  transition:  background 0.2s;
}

.deck-card:hover { background: var(--color-deck-lift); }

.deck-card::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 2px;
  background: linear-gradient(90deg, var(--color-deck-orange), transparent);
  opacity: 0;
  transition: opacity 0.2s;
}

.deck-card:hover::before { opacity: 1; }

.card-num {
  position:       absolute;
  top:            16px;
  right:          20px;
  font-family:    var(--font-mono);
  font-size:      10px;
  font-weight:    700;
  color:          var(--color-deck-dim);
  letter-spacing: 0.1em;
}

.card-title {
  font-family:    var(--font-mono);
  font-weight:    700;
  font-size:      13px;
  letter-spacing: 0.06em;
  color:          var(--color-deck-ink);
  margin-bottom:  8px;
}

.card-description {
  font-family: var(--font-mono);
  font-size:   12px;
  color:       var(--color-deck-muted);
  line-height: 1.6;
}
DECK // NEXT Components
DECK // NEXTUI

Button

Skate deck art button with primary, secondary, and ghost variants in three sizes. Rough-cut clip-path corners, spray-paint orange accent. Renders as a Next.js Link when an href is provided.

DECK // NEXTUI

Badge

Spray-paint styled badge with four color variants: orange, yellow, ink, and dim. Suited for category labels, tags, and status indicators.

DECK // NEXTUI

Text

Polymorphic text primitive with body, caption, label, and code variants. IBM Plex Mono body font. Renders as p, span, or div via the `as` prop.

DECK // NEXTUI

Card

Composable card with Card, CardHeader, CardBody, and CardFooter sub-components. Dark woodgrain surfaces with spray-paint accent borders.