AI-ready resources

Copy-paste prompt templates for Claude, Cursor, ChatGPT, GitHub Copilot, and v0.dev. Each prompt gives your AI assistant the exact context it needs to wire up salt-theme-gen correctly — no back-and-forth, no hallucinated API.

/llms.txt · Machine-readable API spec for AI assistants

Token name cheatsheet

These are the CSS variable names your AI assistant should use. Paste the table below as context when working in any file.

Category CSS variable pattern Examples
Colors var(--color-{name}) --color-primary, --color-background, --color-text, --color-muted, --color-border, --color-danger, --color-success, --color-on-primary
Spacing var(--space-{size}) --space-xs (4px), --space-sm (8px), --space-md (16px), --space-lg (24px), --space-xl (32px), --space-xxl (48px)
Radius var(--radius-{size}) --radius-sm (4px), --radius-md (8px), --radius-lg (12px), --radius-xl (16px), --radius-pill (9999px)
Font sizes var(--text-{size}) --text-xs (12px), --text-sm (14px), --text-md (16px), --text-lg (18px), --text-xl (20px), --text-xxl (24px), --text-3xl (30px)
Surfaces var(--surface-{name}) --surface-base, --surface-raised, --surface-card, --surface-overlay
States var(--state-{intent}-{state}) --state-primary-hover, --state-primary-pressed, --state-primary-focused, --state-primary-disabled, --state-danger-hover

Generic setup prompt

Works with any framework. Paste this into Claude, Cursor, or ChatGPT when starting a new project or adding tokens to an existing one.

Add salt-theme-gen design tokens to this project.

INSTALL
npm install salt-theme-gen

GENERATE THEME
Create src/theme.ts (or src/theme.js):
  import { generateTheme } from 'salt-theme-gen';
  export const theme = generateTheme({
    preset: 'ocean',      // one of 20 built-in presets, or a hex color like '#6366f1'
    spacing:  'default',  // 'compact' | 'default' | 'spacious'
    radius:   'default',  // 'sharp' | 'default' | 'rounded' | 'pill'
    fontSize: 'default',  // 'compact' | 'default' | 'large'
  });

INJECT CSS VARIABLES INTO <head>
Create a function that converts theme.light and theme.dark into CSS custom properties:

  function kebab(str) {
    return str.replace(/([A-Z])/g, '-$1').toLowerCase();
  }

  function modeToCSS(mode, selector) {
    const lines = [];
    for (const [k, v] of Object.entries(mode.colors))
      lines.push(`  --color-${kebab(k)}: ${v};`);
    for (const [k, v] of Object.entries(mode.surfaceElevation))
      lines.push(`  --surface-${k}: ${v};`);
    for (const [k, v] of Object.entries(mode.spacing))
      lines.push(`  --space-${k}: ${v}px;`);
    for (const [k, v] of Object.entries(mode.radius))
      lines.push(`  --radius-${k}: ${v}px;`);
    for (const [k, v] of Object.entries(mode.fontSizes))
      lines.push(`  --text-${k}: ${v}px;`);
    for (const [intent, states] of Object.entries(mode.states))
      for (const [state, val] of Object.entries(states))
        lines.push(`  --state-${intent}-${state}: ${val};`);
    return `${selector} {
${lines.join('
')}
}`;
  }

  const css = [
    modeToCSS(theme.light, ':root'),
    modeToCSS(theme.dark,  ':root[data-theme="dark"]'),
  ].join('

');

DARK MODE
- Toggle dark mode by setting data-theme="dark" on <html>
- Persist with localStorage.setItem('theme', 'dark')
- Read preference on page load with a synchronous inline script (before CSS loads)

REPLACE ALL HARDCODED VALUES
Replace every hex/rgb/hsl color with the appropriate CSS variable:
  - Brand/action colors → var(--color-primary), var(--color-secondary)
  - Page background → var(--color-background)
  - Card/panel background → var(--color-surface) or var(--surface-card)
  - Body text → var(--color-text)
  - Secondary text → var(--color-muted)
  - Dividers/borders → var(--color-border)
  - Error states → var(--color-danger)
  - Success states → var(--color-success)
  - Padding/gap/margin → var(--space-sm), var(--space-md), etc.
  - Border radius → var(--radius-md), var(--radius-lg)
  - Font size → var(--text-sm), var(--text-md), etc.
  - Hover state → var(--state-primary-hover)
  - Focus ring → var(--state-primary-focused)
  - Disabled → var(--state-primary-disabled)

DO NOT hardcode any color, spacing, or font size value anywhere.

Framework-specific prompts

Each prompt is self-contained — it assumes salt-theme-gen is already installed and provides the full implementation pattern for that framework.

React ThemeContext + CSS injection
Wire up salt-theme-gen in this React project:

1. Create src/theme/index.ts — call generateTheme({ preset: 'ocean' })

2. In src/main.tsx, before ReactDOM.createRoot, inject CSS vars into document.head:
   - Build a <style> tag from theme.light (for :root) and theme.dark (for :root[data-theme="dark"])
   - Token names: --color-*, --space-*, --radius-*, --text-*, --surface-*, --state-*

3. Add an inline <script> in index.html <head> (synchronous, no defer/async):
   var s = localStorage.getItem('theme');
   if (s) document.documentElement.setAttribute('data-theme', s);

4. Create src/theme/ThemeContext.tsx:
   - Context with { isDark, toggle } (or 'light'|'dark'|'system' preference)
   - Reads localStorage on init, matches OS with matchMedia('(prefers-color-scheme: dark)')
   - On toggle: sets data-theme on document.documentElement + saves to localStorage
   - Export useTheme() hook

5. Wrap <App /> in ThemeProvider in main.tsx

6. Replace all hardcoded colors/spacing with CSS variables throughout
Next.js App Router, no FOUC
Add salt-theme-gen to this Next.js App Router project:

1. Create src/lib/theme.ts — generateTheme({ preset: 'ocean' })

2. In app/layout.tsx (root layout):
   - Build themeCSS string from theme.light (:root) and theme.dark (:root[data-theme="dark"])
   - Inject via <style dangerouslySetInnerHTML={{ __html: themeCSS }} />
   - Add suppressHydrationWarning to <html>
   - Add inline <script> in <head> that reads localStorage and sets data-theme synchronously:
     (function(){var t=localStorage.getItem('theme');if(t)document.documentElement.setAttribute('data-theme',t);})();

3. Create src/components/ThemeProvider.tsx as a Client Component ('use client'):
   - Manages isDark state, syncs to data-theme attribute
   - Exports useTheme() hook via context

4. Wrap children in RootLayout with ThemeProvider

5. Replace all hardcoded colors with CSS variables
Vue 3 Composable + provide/inject
Add salt-theme-gen to this Vue 3 project:

1. Create src/theme/index.ts — generateTheme({ preset: 'ocean' })

2. In src/main.ts, before app.mount():
   - Build CSS string from theme.light + theme.dark
   - Inject via document.createElement('style') into document.head
   - Read localStorage and set data-theme on document.documentElement

3. Create src/composables/useThemeMode.ts:
   - module-level ref isDark (shared state, not per-component)
   - toggle() function: flips isDark, sets data-theme, saves localStorage
   - Returns { isDark, toggle }

4. In App.vue, provide('theme', { isDark, toggle }) for deep component access

5. Inject in child components with useTheme() composable that wraps inject('theme')

6. Replace hardcoded values with CSS variables — use :style binding for dynamic values
SvelteKit Writable store + svelte:head
Add salt-theme-gen to this SvelteKit project:

1. Create src/lib/theme.ts — generateTheme({ preset: 'ocean' })

2. Create src/lib/stores/theme.ts:
   - writable<'light'|'dark'>('light') store
   - init() reads localStorage and matchMedia on client
   - subscribe to update data-theme attribute on document.documentElement

3. In src/routes/+layout.svelte:
   - Call init() in onMount
   - Use {@html themeCSS} inside <svelte:head> for CSS injection
   - Or: generate static/theme.css via a script and <link> it in app.html

4. Add synchronous inline script to src/app.html <head>:
   <script>
     var t = localStorage.getItem('theme');
     if (t) document.documentElement.setAttribute('data-theme', t);
   </script>

5. In components, import { theme } from '$lib/stores/theme' and use $theme for reactivity
Angular Injectable service + signals
Add salt-theme-gen to this Angular project:

1. Create src/app/theme/theme.service.ts:
   - @Injectable({ providedIn: 'root' })
   - Inject DOCUMENT
   - isDark = signal(false)
   - In constructor: read localStorage, call applyMode()
   - applyMode(dark: boolean): sets data-theme attribute, calls injectCSS()
   - injectCSS(): creates <style id="salt-theme"> with CSS vars from theme.light/.dark
   - toggle(): isDark.set(!isDark()), calls applyMode, saves localStorage

2. In src/main.ts, after bootstrapApplication:
   appRef.injector.get(ThemeService); // eager instantiation

3. CSS variables work through ViewEncapsulation.Emulated — add ::ng-deep or
   use :host-context([data-theme="dark"]) for dark-mode overrides in component styles

4. Inject ThemeService in components that need the toggle button
Tailwind CSS Extend config with CSS vars
Wire salt-theme-gen tokens into this Tailwind CSS project:

1. Generate theme and inject CSS variables into <head> first (see generic prompt)

2. Update tailwind.config.ts:
   darkMode: ['attribute', '[data-theme="dark"]'],
   theme: {
     extend: {
       colors: {
         primary:    'var(--color-primary)',
         secondary:  'var(--color-secondary)',
         background: 'var(--color-background)',
         surface:    'var(--color-surface)',
         text:       'var(--color-text)',
         muted:      'var(--color-muted)',
         border:     'var(--color-border)',
         danger:     'var(--color-danger)',
         success:    'var(--color-success)',
         warning:    'var(--color-warning)',
         info:       'var(--color-info)',
       },
       spacing: {
         xs: 'var(--space-xs)', sm: 'var(--space-sm)',
         md: 'var(--space-md)', lg: 'var(--space-lg)',
         xl: 'var(--space-xl)', xxl: 'var(--space-xxl)',
       },
       borderRadius: {
         sm: 'var(--radius-sm)', DEFAULT: 'var(--radius-md)',
         lg: 'var(--radius-lg)', xl: 'var(--radius-xl)', pill: 'var(--radius-pill)',
       },
     },
   },

3. Replace arbitrary Tailwind values (bg-[#2563eb]) with token classes (bg-primary)
4. Dark mode: data-theme="dark" toggles automatically — rarely need dark: variants
React Native No CSS variables — JS objects
Add salt-theme-gen to this React Native project:

IMPORTANT: React Native does not support CSS custom properties.
Use the GeneratedThemeMode JS object directly.

1. Create src/theme/index.ts:
   import { generateTheme } from 'salt-theme-gen';
   export const theme = generateTheme({ preset: 'ocean' });

2. Create src/theme/ThemeContext.tsx:
   - Context with mode: GeneratedThemeMode, isDark: boolean, toggle()
   - useColorScheme() from react-native for OS preference
   - AsyncStorage for persistence (@react-native-async-storage/async-storage)
   - Preference: 'light' | 'dark' | 'system'

3. Wrap app root with ThemeProvider

4. In screens/components:
   const { mode } = useTheme();
   const styles = useMemo(() => StyleSheet.create({
     container: { backgroundColor: mode.colors.background },
     text:       { color: mode.colors.text, fontSize: mode.fontSizes.md },
     card:       { backgroundColor: mode.surfaceElevation.card,
                   borderRadius: mode.radius.lg, padding: mode.spacing.xl },
   }), [mode]);

5. Always use useMemo([mode]) — avoids recreating StyleSheet on every render
Astro Fragment set:html + is:inline script
Add salt-theme-gen to this Astro project:

1. Create src/lib/theme.ts:
   import { generateTheme } from 'salt-theme-gen';
   export const theme = generateTheme({ preset: 'ocean' });
   export const themeCSS = buildThemeCSS(theme); // build the CSS string

2. In src/layouts/BaseLayout.astro <head>:
   <Fragment set:html={`<style>${themeCSS}</style>`} />

   IMPORTANT: Use Fragment set:html, NOT a regular <style> tag.
   A regular <style> gets scoped by Astro and loses :root[data-theme="dark"] selectors.

3. Add a synchronous inline script for FOUC prevention:
   <script is:inline>
     var t = localStorage.getItem('theme');
     if (t) document.documentElement.setAttribute('data-theme', t);
   </script>

4. For typed token access in React/Vue islands, generate theme server-side and
   pass as props: <ReactIsland lightColors={theme.light.colors} />

5. Use CSS variables (var(--color-primary)) in all .astro component <style> blocks

Using with Claude Code

Claude Code has full access to your file system and can run npm install. These prompts work in both interactive chat and /loop mode.

Add tokens to an existing project
Install salt-theme-gen and add its design tokens to this project.
Run: npm install salt-theme-gen
Then wire up the theme following the pattern for this project's framework.
Use the ocean preset. Replace all hardcoded color values with CSS variables.
Do not touch any existing business logic — only replace style values.
Change preset
Change the salt-theme-gen preset from ocean to rose.
Find the generateTheme() call and update the preset argument only.
No other changes needed — token names stay the same, values update automatically.
Audit hardcoded values
Audit this project for hardcoded color values.
Search for: hex colors (#xxx, #xxxxxx), rgb(), rgba(), hsl(), hsla()
List every file and line where they appear.
Then replace each one with the appropriate salt-theme-gen CSS variable.
Map: brand/primary colors → var(--color-primary), backgrounds → var(--color-background), etc.
Add dark mode toggle component
Add a dark mode toggle button to this project that uses salt-theme-gen.
The button should:
- Toggle data-theme="dark" on document.documentElement
- Persist preference in localStorage under key 'theme'
- Show sun/moon icons for current state
- Apply the toggle without a full page reload
Assume CSS variables for light/dark are already injected via salt-theme-gen.

Cursor rules / Copilot instructions

Add these rules to .cursorrules, .cursor/rules/*.mdc, or .github/copilot-instructions.md to enforce token usage project-wide.

# Design token rules — salt-theme-gen

This project uses salt-theme-gen CSS custom properties for all design values.

## REQUIRED in all files
- Colors: var(--color-primary), var(--color-secondary), var(--color-background),
  var(--color-surface), var(--color-text), var(--color-muted), var(--color-border),
  var(--color-danger), var(--color-success), var(--color-warning), var(--color-info)
- On-color: var(--color-on-primary), var(--color-on-danger), var(--color-on-success)
- Spacing: var(--space-xs) var(--space-sm) var(--space-md) var(--space-lg) var(--space-xl) var(--space-xxl)
- Radius: var(--radius-sm) var(--radius-md) var(--radius-lg) var(--radius-xl) var(--radius-pill)
- Font size: var(--text-xs) var(--text-sm) var(--text-md) var(--text-lg) var(--text-xl) var(--text-xxl) var(--text-3xl)
- Interaction states: var(--state-primary-hover), var(--state-primary-focused),
  var(--state-primary-pressed), var(--state-primary-disabled)
  (also -danger-, -success-, -warning-, -info- variants)

## NEVER
- Do not write hex values, rgb(), rgba(), hsl(), hsla() in any stylesheet or inline style
- Do not write hardcoded pixel sizes for colors, spacing, or font sizes
- Do not add new design values — use the existing token set

## Dark mode
- Toggle by setting data-theme="dark" on <html>
- Never duplicate CSS rules for dark mode — use the CSS variable system
- Token values automatically update between light/dark modes

For Cursor, save as .cursor/rules/design-tokens.mdc with alwaysApply: true to enforce tokens in every file the AI touches.

/llms.txt

A machine-readable spec at /llms.txt documents the full salt-theme-gen API for AI assistants. Load it into your context when working on complex integrations.

Load in Claude
Read the file at https://learn.esalt.net/llms.txt for the complete salt-theme-gen API reference, then help me [task].
Load in Cursor
@https://learn.esalt.net/llms.txt Help me wire up salt-theme-gen in this project.
Load in ChatGPT
Here is the salt-theme-gen API reference: [paste contents of /llms.txt]
Now help me [task].