Skip to main content

Creating a Theme

Use createTheme() to create a custom theme by overriding defaults:
import { createTheme } from '@frontmcp/ui';

const myTheme = createTheme({
  name: 'my-brand',
  colors: {
    semantic: {
      primary: '#4f46e5',   // Indigo
      accent: '#8b5cf6',    // Purple
    },
  },
});
The createTheme() function deep-merges your overrides with the default theme.

Full Theme Example

import { createTheme } from '@frontmcp/ui';

const brandTheme = createTheme({
  name: 'brand-theme',

  colors: {
    semantic: {
      primary: '#2563eb',     // Blue-600
      secondary: '#4b5563',   // Gray-600
      accent: '#8b5cf6',      // Purple-500
      success: '#059669',     // Emerald-600
      warning: '#d97706',     // Amber-600
      danger: '#dc2626',      // Red-600
      info: '#0284c7',        // Sky-600
    },
    surface: {
      background: '#f8fafc',  // Slate-50
      foreground: '#ffffff',
      muted: '#f1f5f9',       // Slate-100
      subtle: '#e2e8f0',      // Slate-200
    },
    text: {
      primary: '#1e293b',     // Slate-800
      secondary: '#64748b',   // Slate-500
      muted: '#94a3b8',       // Slate-400
      inverse: '#ffffff',
      link: '#2563eb',
    },
    border: {
      default: '#cbd5e1',     // Slate-300
      strong: '#94a3b8',      // Slate-400
      muted: '#e2e8f0',       // Slate-200
    },
  },

  typography: {
    families: {
      sans: '"Inter", -apple-system, sans-serif',
      mono: '"JetBrains Mono", monospace',
      heading: '"Inter", sans-serif',
    },
  },

  radius: {
    md: '0.5rem',
    lg: '0.75rem',
    xl: '1rem',
  },

  cdn: {
    fonts: {
      preconnect: [
        'https://fonts.googleapis.com',
        'https://fonts.gstatic.com',
      ],
      stylesheets: [
        'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap',
        'https://fonts.googleapis.com/css2?family=JetBrains+Mono&display=swap',
      ],
    },
  },
});

Using Custom Themes

In Base Layout

import { baseLayout } from '@frontmcp/ui';

const html = baseLayout({
  content: cardHtml,
  theme: brandTheme,
});

In Tool UI

@Tool({
  name: 'my_tool',
  ui: {
    template: (ctx) => baseLayout({
      content: `<p>${ctx.output.message}</p>`,
      theme: brandTheme,
    }),
  },
})

Theme-Aware Components

Pass theme to layout functions that need it:
import { dashboardLayout } from '@frontmcp/ui';

const html = dashboardLayout({
  title: 'Analytics',
  stats: [...],
  mainContent: '...',
  theme: brandTheme,
});

CDN Configuration

Customize external resources:

Fonts

const theme = createTheme({
  cdn: {
    fonts: {
      preconnect: [
        'https://fonts.googleapis.com',
        'https://fonts.gstatic.com',
      ],
      stylesheets: [
        'https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap',
      ],
    },
  },
});

Scripts

const theme = createTheme({
  cdn: {
    scripts: {
      // Custom Tailwind config
      tailwind: 'https://your-cdn.com/tailwind.min.js',

      // HTMX with integrity hash
      htmx: {
        url: 'https://unpkg.com/[email protected]',
        integrity: 'sha384-...',
      },

      // Alpine.js
      alpine: {
        url: 'https://unpkg.com/[email protected]/dist/cdn.min.js',
        defer: true,
      },
    },
  },
});

Icons

const theme = createTheme({
  cdn: {
    icons: {
      script: {
        url: 'https://unpkg.com/lucide@latest',
        integrity: 'sha384-...',
      },
    },
  },
});

Theme Utilities

buildThemeCss

Generate CSS variables from a theme:
import { buildThemeCss, DEFAULT_THEME } from '@frontmcp/ui';

const css = buildThemeCss(DEFAULT_THEME);
// Returns: ":root { --color-primary: #24292f; ... }"

buildStyleBlock

Generate a complete <style> block:
import { buildStyleBlock, DEFAULT_THEME } from '@frontmcp/ui';

const styleTag = buildStyleBlock(DEFAULT_THEME);
// Returns: "<style>:root { --color-primary: ... }</style>"

buildFontPreconnectFromTheme

Generate font preconnect links:
import { buildFontPreconnectFromTheme, brandTheme } from '@frontmcp/ui';

const preconnect = buildFontPreconnectFromTheme(brandTheme);
// Returns: '<link rel="preconnect" href="https://fonts.googleapis.com">...'

buildFontStylesheetsFromTheme

Generate font stylesheet links:
import { buildFontStylesheetsFromTheme, brandTheme } from '@frontmcp/ui';

const stylesheets = buildFontStylesheetsFromTheme(brandTheme);
// Returns: '<link rel="stylesheet" href="https://fonts.googleapis.com/...">'

buildCdnScriptsFromTheme

Generate script tags:
import { buildCdnScriptsFromTheme, brandTheme } from '@frontmcp/ui';

const scripts = buildCdnScriptsFromTheme(brandTheme, {
  tailwind: true,
  htmx: true,
  alpine: false,
});

Component Tokens

Customize specific components:
const theme = createTheme({
  components: {
    button: {
      borderRadius: '0.5rem',
      fontWeight: '600',
      padding: {
        sm: '0.5rem 1rem',
        md: '0.75rem 1.5rem',
        lg: '1rem 2rem',
      },
    },
    card: {
      borderRadius: '1rem',
      shadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1)',
      padding: '1.5rem',
    },
    input: {
      borderRadius: '0.5rem',
      borderWidth: '2px',
      focusRing: '3px solid var(--color-primary)',
    },
  },
});

Best Practices

  1. Start from defaults - Use createTheme() to inherit sensible defaults
  2. Use semantic colors - Define meaning, not appearance
  3. Test contrast - Ensure text is readable on all backgrounds
  4. Include font preconnects - Improve font loading performance
  5. Use CSS variables - Components automatically use theme variables
  6. Document your theme - Help team members use it correctly

Minimal Light

const minimalLight = createTheme({
  name: 'minimal-light',
  colors: {
    semantic: { primary: '#000000' },
    surface: { background: '#ffffff', foreground: '#ffffff' },
    text: { primary: '#000000', secondary: '#666666' },
    border: { default: '#e5e5e5' },
  },
});

Dark Modern

const darkModern = createTheme({
  name: 'dark-modern',
  colors: {
    semantic: { primary: '#60a5fa', accent: '#a78bfa' },
    surface: { background: '#0f172a', foreground: '#1e293b' },
    text: { primary: '#f1f5f9', secondary: '#94a3b8' },
    border: { default: '#334155' },
  },
});

Nature Green

const natureGreen = createTheme({
  name: 'nature-green',
  colors: {
    semantic: { primary: '#16a34a', accent: '#22c55e' },
    surface: { background: '#f0fdf4', foreground: '#ffffff' },
    text: { primary: '#14532d', secondary: '#166534' },
    border: { default: '#86efac' },
  },
});