# Theme builder

> There are no preset themes. A theme is a set of CSS variables; make one in the theme builder and paste its CSS into your global stylesheet. Every component and template reads the same variables.

Open it: https://www.parthjadhav.com/products/portfolio-kit/themes. Changes apply to the whole docs site as you make them, so you can browse every component in your theme.

## Options

The builder derives both palettes (light and dark) from a few choices, with WCAG contrast guaranteed. Share a theme as a URL: `/themes?` plus any of these parameters (omitted = default).

| Param | Setting | Values | Default |
| --- | --- | --- | --- |
| `a` | Accent hue | 0–359 (named: red 25, orange 45, amber 75, lime 125, green 150, teal 185, sky 230, blue 262, violet 290, pink 350) | `262` |
| `i` | Accent intensity | `soft`, `bold` | `bold` |
| `n` | Neutrals | `neutral`, `stone`, `paper`, `slate`, `sage`, `mauve` | `neutral` |
| `p` | Button fill | `ink`, `accent` | `ink` |
| `r` | Radius (rem) | `0`, `0.25`, `0.5`, `0.75`, `1`, `1.25` | `0.75` |
| `h` | Heading font | `geist` (Geist), `inter` (Inter), `dm-sans` (DM Sans), `space-grotesk` (Space Grotesk), `sora` (Sora), `bricolage` (Bricolage Grotesque), `instrument-serif` (Instrument Serif), `fraunces` (Fraunces), `jetbrains-mono` (JetBrains Mono), `system` (System UI), `system-serif` (System serif) | `geist` |
| `b` | Body font | `geist` (Geist), `inter` (Inter), `dm-sans` (DM Sans), `space-grotesk` (Space Grotesk), `sora` (Sora), `jetbrains-mono` (JetBrains Mono), `system` (System UI) | `geist` |
| `c` | Code font | `geist-mono` (Geist Mono), `jetbrains-mono` (JetBrains Mono), `system-mono` (System mono) | `geist-mono` |
| `w` | Heading weight | 300–700 | `600` |
| `t` | Heading letter-spacing (em) | `-0.05`, `-0.035`, `-0.02`, `0` | `-0.035` |
| `s` | Card shadows | `none`, `subtle`, `lifted`, `hard` | `subtle` |
| `e` | Borders | `subtle`, `strong` (drawn in the text color) | `subtle` |

Example: `/themes?a=38&n=paper&r=0.25&h=instrument-serif&w=400&s=none`.

## Tokens

shadcn/ui's tokens plus the kit's: `--background`, `--foreground`, `--card`, `--card-foreground`, `--popover`, `--popover-foreground`, `--primary`, `--primary-foreground`, `--secondary`, `--secondary-foreground`, `--muted`, `--muted-foreground`, `--accent`, `--accent-foreground`, `--destructive`, `--border`, `--input`, `--ring`, `--highlight`, `--highlight-foreground`, `--highlight-ink`, `--success`, `--card-shadow`, and `--radius`, `--font-body`, `--font-heading`, `--font-code`, `--heading-tracking`, `--heading-weight` (and `--display-scale` for monospace headings). Use `text-highlight-ink` (not `text-highlight`) for accent-colored text.

## The default theme

What you get without changing anything. Replace these blocks in your global CSS with your own, and map the fonts:

```css
:root {
  --radius: 0.75rem;
  --font-body: "Geist Variable", "Geist", ui-sans-serif, system-ui, sans-serif;
  --font-heading: "Geist Variable", "Geist", ui-sans-serif, system-ui, sans-serif;
  --font-code: "Geist Mono Variable", "Geist Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --heading-tracking: -0.035em;
  --heading-weight: 600;
  --background: oklch(1 0 0);
  --foreground: oklch(0.16 0 0);
  --card: oklch(1 0 0);
  --card-foreground: oklch(0.16 0 0);
  --popover: oklch(1 0 0);
  --popover-foreground: oklch(0.16 0 0);
  --primary: oklch(0.2 0 0);
  --primary-foreground: oklch(1 0 0);
  --secondary: oklch(0.955 0 0);
  --secondary-foreground: oklch(0.16 0 0);
  --muted: oklch(0.965 0 0);
  --muted-foreground: oklch(0.52 0 0);
  --accent: oklch(0.95 0 0);
  --accent-foreground: oklch(0.16 0 0);
  --destructive: oklch(0.577 0.245 27.3);
  --border: oklch(0.91 0 0);
  --input: oklch(0.89 0 0);
  --ring: oklch(0.57 0.21 262);
  --highlight: oklch(0.57 0.21 262);
  --highlight-foreground: oklch(1 0 0);
  --highlight-ink: oklch(0.54 0.21 262);
  --success: oklch(0.66 0.17 150);
  --card-shadow: 0 1px 2px 0 oklch(0 0 0 / 0.04), 0 2px 8px -2px oklch(0 0 0 / 0.04);
}

.dark {
  --background: oklch(0.15 0 0);
  --foreground: oklch(0.97 0 0);
  --card: oklch(0.185 0 0);
  --card-foreground: oklch(0.97 0 0);
  --popover: oklch(0.205 0 0);
  --popover-foreground: oklch(0.97 0 0);
  --primary: oklch(0.93 0 0);
  --primary-foreground: oklch(0.15 0 0);
  --secondary: oklch(0.26 0 0);
  --secondary-foreground: oklch(0.97 0 0);
  --muted: oklch(0.235 0 0);
  --muted-foreground: oklch(0.72 0 0);
  --accent: oklch(0.27 0 0);
  --accent-foreground: oklch(0.97 0 0);
  --destructive: oklch(0.704 0.191 22.2);
  --border: oklch(0.29 0 0);
  --input: oklch(0.33 0 0);
  --ring: oklch(0.74 0.134 262);
  --highlight: oklch(0.74 0.134 262);
  --highlight-foreground: oklch(0.15 0 0);
  --highlight-ink: oklch(0.74 0.134 262);
  --success: oklch(0.78 0.17 150);
  --card-shadow: 0 0 0 1px oklch(1 0 0 / 0.02), 0 8px 24px -12px oklch(0 0 0 / 0.6);
}

@theme inline {
  --font-sans: var(--font-body);
  --font-mono: var(--font-code);
}
```

See [Theming](https://www.parthjadhav.com/products/portfolio-kit/docs/theming.md) for how the tokens are used.
