GameCraftGameCraft

Design System

Customize colors, typography, and components - make ProductReady match your brand

Design System

ProductReady's design system is built with CSS variables for easy customization. Change colors, fonts, and spacing without touching component code.

For designers & PMs: This guide uses plain English and visual examples. No deep coding required!


Color System

How it Works

Colors are defined as CSS variables in src/app/global.css. Change them once, they apply everywhere.

Example:

:root {
  --color-primary: 220 90% 56%;  /* Blue */
  --color-accent: 142 71% 45%;   /* Green */
}

Format: HSL (Hue, Saturation, Lightness) without the hsl() wrapper.

Why HSL? Easy to create color variations (just change lightness for hover states).


Change Your Brand Colors

Step 1: Pick your colors

Use a tool like Coolors.co or Realtime Colors

Step 2: Convert to HSL

Most tools show HSL values. If you have hex (#3B82F6):

Step 3: Update global.css

Open src/app/global.css and find:

:root {
  /* Change these values! */
  --color-primary: 220 90% 56%;    /* Your main brand color */
  --color-accent: 142 71% 45%;     /* Accent/CTA color */
  --color-background: 0 0% 100%;   /* Page background */
  --color-foreground: 222 47% 11%; /* Text color */
}

Example - Purple brand:

:root {
  --color-primary: 271 81% 56%;   /* Purple */
  --color-accent: 321 82% 56%;    /* Pink */
}

Save → Refresh → Your app is now purple! 🎨


Dark Mode Colors

ProductReady has separate colors for dark mode:

.dark {
  --color-primary: 220 90% 66%;    /* Lighter in dark mode */
  --color-background: 224 71% 4%;  /* Dark background */
  --color-foreground: 213 31% 91%; /* Light text */
}

Tip: Make colors slightly lighter in dark mode for better contrast.


Complete Color Palette

All available color variables:

VariablePurposeLight ModeDark Mode
--color-backgroundPage backgroundWhiteDark
--color-foregroundTextDarkLight
--color-primaryBrand color (buttons, links)BrandLighter brand
--color-accentHighlights, CTAsAccentLighter accent
--color-mutedSubtle backgroundsLight grayDark gray
--color-borderBorders, dividersMedium grayDark gray
--color-successSuccess statesGreenLight green
--color-warningWarningsYellowLight yellow
--color-errorErrorsRedLight red

Typography

Change Fonts

Step 1: Choose fonts from Google Fonts

Example: "Inter" for body, "Playfair Display" for headings

Step 2: Update src/app/layout.tsx

import { Inter, Playfair_Display } from 'next/font/google';

const inter = Inter({ subsets: ['latin'] });
const playfair = Playfair_Display({ subsets: ['latin'] });

export default function RootLayout({ children }) {
  return (
    <html>
      <body className={inter.className}>
        {children}
      </body>
    </html>
  );
}

Step 3: Use heading font

<h1 className={playfair.className}>
  Beautiful Heading
</h1>

Font Sizes

Customize font sizes in global.css:

:root {
  --font-size-xs: 0.75rem;   /* 12px */
  --font-size-sm: 0.875rem;  /* 14px */
  --font-size-base: 1rem;    /* 16px */
  --font-size-lg: 1.125rem;  /* 18px */
  --font-size-xl: 1.25rem;   /* 20px */
  --font-size-2xl: 1.5rem;   /* 24px */
  --font-size-3xl: 1.875rem; /* 30px */
  --font-size-4xl: 2.25rem;  /* 36px */
}

Use in components:

<p className="text-base">Normal text</p>
<h1 className="text-4xl">Big heading</h1>

Spacing

Consistent spacing makes UI feel professional.

Spacing scale (in global.css):

:root {
  --spacing-0: 0;
  --spacing-1: 0.25rem;  /* 4px */
  --spacing-2: 0.5rem;   /* 8px */
  --spacing-3: 0.75rem;  /* 12px */
  --spacing-4: 1rem;     /* 16px */
  --spacing-6: 1.5rem;   /* 24px */
  --spacing-8: 2rem;     /* 32px */
  --spacing-12: 3rem;    /* 48px */
  --spacing-16: 4rem;    /* 64px */
}

Use with Tailwind:

<div className="p-4">Padding 16px</div>
<div className="mt-8 mb-4">Margin top 32px, bottom 16px</div>

Border Radius

Control roundness of cards, buttons, inputs.

:root {
  --radius-sm: 0.25rem;   /* 4px - subtle */
  --radius-md: 0.5rem;    /* 8px - default */
  --radius-lg: 0.75rem;   /* 12px - cards */
  --radius-xl: 1rem;      /* 16px - very round */
  --radius-full: 9999px;  /* Pills, avatars */
}

Make everything more rounded:

:root {
  --radius-md: 0.75rem;  /* Change default */
  --radius-lg: 1rem;
}

Component Customization

Buttons

Buttons use CSS variables. Customize in src/components/ui/button.tsx:

<button className="btn-primary">
  Click Me
</button>

Styles in global.css:

.btn-primary {
  background: hsl(var(--color-primary));
  color: white;
  padding: var(--spacing-3) var(--spacing-6);
  border-radius: var(--radius-md);
  font-weight: 600;
}

.btn-primary:hover {
  background: hsl(var(--color-primary) / 0.9);
}

Change button style globally: Just update the CSS!


Cards

Cards are background containers with borders.

<div className="card">
  <h3>Card Title</h3>
  <p>Card content</p>
</div>

Style:

.card {
  background: hsl(var(--color-background));
  border: 1px solid hsl(var(--color-border));
  border-radius: var(--radius-lg);
  padding: var(--spacing-6);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

Forms & Inputs

Customize input fields:

input, textarea {
  background: hsl(var(--color-background));
  border: 1px solid hsl(var(--color-border));
  border-radius: var(--radius-md);
  padding: var(--spacing-3) var(--spacing-4);
  font-size: var(--font-size-base);
}

input:focus {
  outline: 2px solid hsl(var(--color-primary));
  outline-offset: 2px;
}

Dark Mode

Toggle Dark Mode

ProductReady uses next-themes for dark mode.

Add toggle button:

'use client';

import { useTheme } from 'next-themes';

export function ThemeToggle() {
  const { theme, setTheme } = useTheme();

  return (
    <button onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
      {theme === 'dark' ? '☀️' : '🌙'}
    </button>
  );
}

Customize Dark Mode Colors

Edit .dark section in global.css:

.dark {
  /* Dark backgrounds */
  --color-background: 224 71% 4%;
  --color-card: 224 71% 6%;
  
  /* Light text */
  --color-foreground: 213 31% 91%;
  
  /* Adjust primary for dark mode */
  --color-primary: 220 90% 66%; /* Slightly lighter */
}

Tip: Test contrast with WebAIM Contrast Checker


AI Prompt: Customize Design

Copy-paste this to ChatGPT/Claude/Cursor:

I'm using ProductReady (Next.js boilerplate). Help me customize the design:

Brand Colors:
- Primary: [Your color name/hex]
- Accent: [Your color name/hex]

Typography:
- Body font: [Font name]
- Heading font: [Font name]

Style:
- Rounded corners: [More/Less rounded]
- Spacing: [Tight/Normal/Spacious]
- Dark mode: [Yes/No]

Generate the CSS variables for global.css and show me how to update fonts in layout.tsx

AI will give you copy-paste code!


Using KUI Components

ProductReady uses the KUI component library from the monorepo.

Important: Don't modify packages/kui directly! Create wrapper components instead.

How to Customize KUI Components

Example: Customize Button

  1. Import KUI component
  2. Create wrapper in your app
  3. Add custom styles
// src/components/ui/custom-button.tsx
import { Button } from 'kui/button';
import './custom-button.css';

export function CustomButton({ children, ...props }) {
  return (
    <Button className="custom-button" {...props}>
      {children}
    </Button>
  );
}
/* src/components/ui/custom-button.css */
.custom-button {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border: none;
  padding: 12px 24px;
  font-weight: 700;
}

Now use <CustomButton> instead of <Button> in your app!


Responsive Design

ProductReady is mobile-first. Use Tailwind breakpoints:

<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3">
  {/* 1 column on mobile, 2 on tablet, 3 on desktop */}
</div>

Breakpoints:

  • sm: - 640px+
  • md: - 768px+
  • lg: - 1024px+
  • xl: - 1280px+
  • 2xl: - 1536px+

Example - Responsive padding:

<div className="p-4 md:p-8 lg:p-12">
  {/* 16px mobile, 32px tablet, 48px desktop */}
</div>

Accessibility

Color Contrast

Ensure text is readable:

Minimum contrast ratios:

  • Normal text: 4.5:1
  • Large text (18px+): 3:1

Test with WebAIM Contrast Checker

Focus States

Always show focus for keyboard navigation:

button:focus-visible {
  outline: 2px solid hsl(var(--color-primary));
  outline-offset: 2px;
}

Semantic HTML

Use proper HTML elements:

<button>Click Me</button>
<div onClick={...}>Click Me</div>

<nav>...</nav>
<div className="nav">...</div>

Design Tokens Cheat Sheet

Quick reference for all design tokens:

Colors

--color-background
--color-foreground
--color-primary
--color-accent
--color-muted
--color-border
--color-success
--color-warning
--color-error

Spacing

--spacing-1 through --spacing-16
/* Use with: p-4, mt-8, gap-6, etc. */

Typography

--font-size-xs through --font-size-4xl
--font-weight-normal (400)
--font-weight-medium (500)
--font-weight-semibold (600)
--font-weight-bold (700)

Border Radius

--radius-sm, --radius-md, --radius-lg, --radius-xl, --radius-full

Best Practices

✅ Do

  • Use CSS variables for consistency
  • Test both light and dark modes
  • Check color contrast for accessibility
  • Use semantic HTML elements
  • Keep spacing consistent (stick to scale)
  • Test on mobile devices

❌ Don't

  • Hardcode colors in components
  • Modify packages/kui directly
  • Use too many different font sizes
  • Ignore dark mode styles
  • Skip focus states
  • Use <div> for everything

Quick Customization Recipes

Recipe 1: Minimalist B&W

:root {
  --color-primary: 0 0% 9%;      /* Black */
  --color-accent: 0 0% 45%;      /* Gray */
  --color-background: 0 0% 100%; /* White */
  --color-foreground: 0 0% 9%;   /* Black */
}

.dark {
  --color-primary: 0 0% 98%;     /* White */
  --color-background: 0 0% 9%;   /* Black */
  --color-foreground: 0 0% 98%;  /* White */
}

Recipe 2: Vibrant Startup

:root {
  --color-primary: 271 81% 56%;   /* Purple */
  --color-accent: 346 77% 50%;    /* Pink */
  --radius-md: 1rem;              /* Extra rounded */
  --radius-lg: 1.5rem;
}

Recipe 3: Professional SaaS

:root {
  --color-primary: 220 90% 56%;   /* Blue */
  --color-accent: 142 71% 45%;    /* Green */
  --radius-md: 0.5rem;            /* Subtle rounding */
  --radius-lg: 0.75rem;
}

Next Steps

🎨 Make it yours! The best designs are unique to your brand.

On this page