LocallyGrown Theming System
Understanding design tokens, theme architecture, and creating custom themes for your market
Overview
LocallyGrown's theming system is built on a foundation of standardized design tokens that ensure consistency across components while allowing for unique market personalities. This system bridges the gap between design and code, making themes both visually distinctive and technically maintainable.
🎨 How Themes Work
Every LocallyGrown theme follows a three-layer architecture:
- Design Tokens - Core variables that all themes must implement
- Theme Files - CSS files that define specific color palettes and styles
- Component Styles - UI elements that reference theme variables
This approach means you can completely transform your market's appearance by changing just the theme file, while all components automatically adapt to the new design.
Design Token Reference
Design tokens are the building blocks of our theming system. These CSS custom properties define colors, typography, spacing, and visual effects that components use throughout the application.
Required Theme Variables
All themes MUST implement these core variables for proper functionality:
Primary Brand Colors
--lg-primary
Main brand color used for primary actions and headers
--lg-primary-hover
Darker variant for hover states
--lg-primary-dark
Extra dark variant for pressed states and strong emphasis
--lg-primary-light
Semi-transparent version for backgrounds (rgba with 0.1 alpha)
--lg-primary-medium
Semi-transparent version for overlays (rgba with 0.2 alpha)
Secondary & Accent Colors
--lg-secondary
Supporting brand color
--lg-secondary-hover
Hover state for secondary elements
--lg-accent
Highlight color for special elements
--lg-accent-hover
Accent hover state
Standardized Accent Palette
These six accent colors provide consistent component styling across all themes:
--lg-accent-1
Lightest accent - used for subtle highlights
--lg-accent-2
Light accent - often vibrant/contrasting
--lg-accent-3
Medium-light accent - balanced tone
--lg-accent-4
Medium accent - matches primary theme tone
--lg-accent-5
Medium-dark accent - deeper variant
--lg-accent-6
Darkest accent - for maximum contrast
Neutral Gray Scale
Nine-step neutral scale (50-900) that adapts to your theme's color temperature:
--lg-gray-50
--lg-gray-100
--lg-gray-200
--lg-gray-300
--lg-gray-400
--lg-gray-500
--lg-gray-600
--lg-gray-700
--lg-gray-800
--lg-gray-900
Status Colors
--lg-success
Success states, confirmations
--lg-warning
Warnings, attention needed
--lg-error
Errors, critical states
--lg-info
Information, neutral alerts
Background Colors
--lg-bg-primary
Main page background
--lg-bg-secondary
Secondary surfaces, cards
--lg-bg-tertiary
Subtle surfaces, overlays
--lg-bg-accent
Accent backgrounds
Text Colors
--lg-text-primary
Main body text, headings
--lg-text-secondary
Secondary text, descriptions
--lg-text-muted
Muted text, placeholders
--lg-text-light
Light text, subtle elements
Visual Effects
--lg-gradient-primary
Main gradient for headers, hero sections
--lg-gradient-secondary
Secondary gradient for accents
--lg-gradient-accent
Subtle accent gradient
--lg-pattern-primary
Main pattern (typically dots)
--lg-pattern-secondary
Secondary pattern (typically grid)
--lg-shadow-primary
Main shadow for cards, buttons
--lg-shadow-secondary
Special effect shadow (often glow)
Optional Variables
These variables can be overridden but have sensible defaults from the design tokens:
- Typography: Font families, sizes, weights, line heights
- Spacing: Margins, paddings, gaps (--lg-space-* scale)
- Border Radius: Corner rounding (--lg-radius-* scale)
- Transitions: Animation timings and easing functions
- Shadows: Traditional shadow scale (--lg-shadow-xs through --lg-shadow-2xl)
Theme Examples
Let's explore how different themes express their personality through the standardized variables:
🍂 Fall Theme
Warm autumn colors with rich browns and golden accents
Gradients: Sunset oranges to deep browns
Neutrals: Warm, earthy tones with cream highlights
🌊 Ocean Theme
Coastal blues with seafoam greens and sandy neutrals
Gradients: Ocean waves from seafoam to deep blue
Neutrals: Cool blue-grays with sandy background warmth
🌱 Spring Theme
Fresh greens with light, renewal-focused colors
Gradients: Light greens to vibrant growth colors
Neutrals: Clean, fresh tones with subtle green warmth
Creating a Custom Theme
Follow this step-by-step guide to create your own market theme:
Step 1: Plan Your Color Palette
🎨 Color Selection Guidelines
- Primary: Your main brand color - should be strong and recognizable
- Secondary: Complements primary, often darker or more muted
- Accent: Contrasts with primary/secondary, adds visual interest
- Neutrals: Should have same color temperature as your brand colors
- Accessibility: Ensure sufficient contrast for text readability
Step 2: Create Your Theme File
Create a new CSS file in the themes directory:
/* === Your Market Theme === */
/* Brief description of the theme's personality and inspiration */
:root {
/* === Primary Brand Colors === */
--lg-primary: #your-primary-color;
--lg-primary-hover: #darker-primary;
--lg-primary-dark: #darkest-primary;
--lg-primary-light: rgba(your-primary-rgb, 0.1);
--lg-primary-medium: rgba(your-primary-rgb, 0.2);
--lg-secondary: #your-secondary-color;
--lg-secondary-hover: #darker-secondary;
--lg-secondary-light: rgba(your-secondary-rgb, 0.1);
--lg-accent: #your-accent-color;
--lg-accent-hover: #darker-accent;
--lg-accent-light: rgba(your-accent-rgb, 0.05);
--lg-accent-medium: rgba(your-accent-rgb, 0.1);
--lg-accent-strong: rgba(your-accent-rgb, 0.2);
/* === Standardized Accent Palette === */
/* Choose 6 colors that work with your theme */
--lg-accent-1: #lightest-accent;
--lg-accent-2: #light-accent;
--lg-accent-3: #medium-light-accent;
--lg-accent-4: #medium-accent;
--lg-accent-5: #medium-dark-accent;
--lg-accent-6: #darkest-accent;
/* Continue with all required variables... */
}
Step 3: Define Your Gray Scale
Create a neutral scale that matches your theme's color temperature:
/* === Neutral Scale === */
/* Adjust these to be warm/cool to match your brand */
--lg-gray-50: #your-lightest-neutral; /* Almost white */
--lg-gray-100: #your-very-light-neutral; /* Very light */
--lg-gray-200: #your-light-neutral; /* Light */
--lg-gray-300: #your-medium-light; /* Medium-light */
--lg-gray-400: #your-medium; /* Medium */
--lg-gray-500: #your-medium-dark; /* Medium-dark */
--lg-gray-600: #your-dark; /* Dark */
--lg-gray-700: #your-very-dark; /* Very dark */
--lg-gray-800: #your-almost-black; /* Almost black */
--lg-gray-900: #your-darkest; /* Darkest text */
Step 4: Create Visual Effects
Design gradients, patterns, and shadows that reflect your theme's personality:
/* === Visual Effects === */
--lg-gradient-primary: linear-gradient(135deg,
var(--lg-primary) 0%,
var(--lg-secondary) 100%);
--lg-gradient-secondary: linear-gradient(180deg,
var(--lg-accent) 0%,
var(--lg-primary) 100%);
--lg-pattern-primary: radial-gradient(circle,
rgba(your-accent-rgb, 0.12) 1px,
transparent 1px);
--lg-shadow-primary: 0 4px 6px -1px rgba(your-primary-rgb, 0.15),
0 2px 4px -1px rgba(your-primary-rgb, 0.08);
Step 5: Test Your Theme
- Test on multiple screen sizes (desktop, tablet, mobile)
- Verify text contrast meets WCAG AA standards
- Check that all UI components look consistent
- Test both light and dark system preferences
- Ensure buttons, links, and interactive elements are clear
- Validate that status colors (success, warning, error) are distinct
Live Theme Demonstration
See how theme variables affect real components:
Primary Button
Uses --lg-primarySecondary Button
Uses --lg-secondaryAccent Elements
Text Hierarchy
Primary Text Heading
Secondary descriptive text
Muted supporting textTechnical Implementation
Understanding how themes are loaded and applied in LocallyGrown:
Theme Loading Process
- Design Tokens: Base design-tokens.css loads first with defaults
- Market Assignment: Each market is assigned a theme in database
- Theme CSS: Specific theme file overrides design token variables
- Component Rendering: All components reference the CSS variables
CSS Custom Property Cascading
The system uses CSS custom property inheritance to ensure themes work consistently:
/* Design tokens set defaults */
:root {
--lg-primary: #466d4d; /* Default green */
}
/* Theme overrides the default */
:root {
--lg-primary: #715b31; /* Fall theme brown */
}
/* Components use the variable */
.button-primary {
background-color: var(--lg-primary);
}
Market-Specific Theme Assignment
Themes are applied at the subdomain level:
- Database Setting: Each market has a theme field
- HTTP Request: Server identifies market from subdomain
- CSS Loading: Appropriate theme CSS is served
- Cache Headers: Themes are cached for performance
Component Integration
All modern UI components are designed to work with any theme:
/* Component always references theme variables */
.card {
background-color: var(--lg-bg-secondary);
border: 1px solid var(--lg-gray-300);
box-shadow: var(--lg-shadow-primary);
color: var(--lg-text-primary);
}
.card:hover {
background-color: var(--lg-bg-tertiary);
box-shadow: var(--lg-shadow-secondary);
}
Best Practices
Color Selection
- Brand Consistency: Use colors that align with your market's existing brand
- Community Reflection: Consider colors that represent your local area or season
- Accessibility First: Ensure sufficient contrast ratios for all text
- Cultural Sensitivity: Be mindful of color meanings in your community
Visual Hierarchy
- Primary Color: Use for the most important actions and branding
- Secondary Color: Support primary without competing
- Accent Color: Add personality and draw attention to special elements
- Neutrals: Create calm backgrounds that let content shine
Performance Considerations
- CSS Variables: More efficient than class-based theming
- Minimal Overrides: Only override necessary variables
- Gradient Performance: Use simple gradients to avoid rendering issues
- Shadow Complexity: Keep shadows subtle for better performance
Maintenance
- Document Decisions: Comment your color choices and reasoning
- Version Control: Track theme changes and test thoroughly
- User Feedback: Monitor how your community responds to theme changes
- Seasonal Updates: Consider if your theme works year-round
Advanced Techniques
Color Mathematics
Using OKLCH color space for better color manipulation:
/* OKLCH provides better color transitions */
--lg-primary: oklch(0.5263 0.1579 243.1579); /* Deep blue */
--lg-primary-hover: oklch(0.4421 0.1579 243.1579); /* Same hue, darker */
--lg-primary-dark: oklch(0.3579 0.1579 243.1579); /* Same hue, darkest */
/* Easy to create variations */
--lg-primary-light: oklch(0.7368 0.1579 243.1579); /* Same hue, lighter */
Semantic Color Naming
Using descriptive names for theme-specific colors:
/* Ocean theme semantic colors */
--ocean-deep: #1e6ba8; /* Deep ocean blue */
--ocean-wave: #5b9bc6; /* Wave blue */
--seafoam: #88c5cc; /* Seafoam green */
--coral-accent: #ff7f7f; /* Coral pink */
--kelp-green: #5a7a47; /* Kelp green */
--sandy-beige: #f5e6d3; /* Sandy background */
/* Map to standard variables */
--lg-primary: var(--ocean-deep);
--lg-secondary: var(--ocean-wave);
--lg-accent: var(--seafoam);
Responsive Theme Adjustments
Adapting themes for different screen sizes:
/* Adjust shadow intensity on mobile */
@media (max-width: 768px) {
:root {
--lg-shadow-primary: 0 2px 4px -1px rgba(0, 0, 0, 0.1);
--lg-shadow-secondary: 0 0 15px rgba(136, 197, 204, 0.2);
}
}
/* Simplify patterns on small screens */
@media (max-width: 480px) {
:root {
--lg-pattern-primary: none;
--lg-pattern-secondary: none;
}
}