theme-implementer
Implement and test custom color schemes, themes, and visual variants for the emotive-mascot website and demos. Use when applying new color palettes, creating themed variants, or A/B testing visual designs.
$ Installer
git clone https://github.com/joshtol/emotive-engine /tmp/emotive-engine && cp -r /tmp/emotive-engine/skills/theme-implementer ~/.claude/skills/emotive-engine// tip: Run this command in your terminal to install the skill
name: theme-implementer description: Implement and test custom color schemes, themes, and visual variants for the emotive-mascot website and demos. Use when applying new color palettes, creating themed variants, or A/B testing visual designs. trigger: theme, color scheme, visual design, branding, color palette, styling
Theme Implementer
You are an expert in implementing and testing visual themes for the emotive-mascot platform.
When to Use This Skill
- Applying new color schemes to the website
- Creating themed demo variants
- Implementing brand-specific mascot colors
- A/B testing visual designs
- Adapting mascot colors to match client branding
- Creating seasonal or event-specific themes
Available Color Schemes
From the theme-factory skill, we have 3 ready-to-use variants:
1. Warm & Energetic (Orange)
Use for: E-commerce, retail, food & beverage, entertainment Primary: #FF8C42 (Vibrant Orange) Accent: #FF6B35 (Coral)
2. Cool & Professional (Cyan)
Use for: Healthcare, finance, technology, corporate Primary: #06B6D4 (Cyan) Accent: #0891B2 (Darker Cyan)
3. Monochrome & Premium (Gold)
Use for: Luxury, premium products, high-end services Primary: #D4AF37 (Gold) Accent: #B8960F (Rich Gold)
Implementation Pattern
Step 1: CSS Variables Approach
Create theme variants using CSS custom properties:
/* site/src/app/globals.css */
:root {
/* Default theme (Purple/Blue) */
--color-primary: #667eea;
--color-primary-light: #a5b4fc;
--color-primary-dark: #4c51bf;
--color-accent: #764ba2;
--color-accent-light: #9d7cbf;
}
/* Warm theme */
[data-theme='warm'] {
--color-primary: #ff8c42;
--color-primary-light: #ffb088;
--color-primary-dark: #e67a2e;
--color-accent: #ff6b35;
--color-accent-light: #ff9270;
}
/* Cool theme */
[data-theme='cool'] {
--color-primary: #06b6d4;
--color-primary-light: #67e8f9;
--color-primary-dark: #0891b2;
--color-accent: #0e7490;
--color-accent-light: #22d3ee;
}
/* Premium theme */
[data-theme='premium'] {
--color-primary: #d4af37;
--color-primary-light: #f4d03f;
--color-primary-dark: #b8960f;
--color-accent: #8b7500;
--color-accent-light: #e6c200;
}
Step 2: Update Components to Use Variables
Replace hardcoded colors with CSS variables:
// Before (hardcoded)
<div style={{
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
border: '1px solid rgba(102, 126, 234, 0.3)'
}}>
...
</div>
// After (themeable)
<div style={{
background: 'linear-gradient(135deg, var(--color-primary) 0%, var(--color-accent) 100%)',
border: '1px solid rgba(var(--color-primary-rgb), 0.3)'
}}>
...
</div>
Step 3: Theme Switcher Component
// site/src/components/ThemeSwitcher.tsx
'use client';
import { useState, useEffect } from 'react';
type Theme = 'default' | 'warm' | 'cool' | 'premium';
export default function ThemeSwitcher() {
const [theme, setTheme] = useState<Theme>('default');
useEffect(() => {
// Load theme from localStorage
const savedTheme =
(localStorage.getItem('theme') as Theme) || 'default';
setTheme(savedTheme);
document.documentElement.setAttribute('data-theme', savedTheme);
}, []);
const handleThemeChange = (newTheme: Theme) => {
setTheme(newTheme);
document.documentElement.setAttribute('data-theme', newTheme);
localStorage.setItem('theme', newTheme);
};
return (
<div
style={{
position: 'fixed',
top: '20px',
right: '20px',
zIndex: 9999,
display: 'flex',
gap: '0.5rem',
padding: '0.75rem',
background: 'rgba(0, 0, 0, 0.8)',
borderRadius: '12px',
backdropFilter: 'blur(10px)',
}}
>
<button
onClick={() => handleThemeChange('default')}
style={{
width: '40px',
height: '40px',
borderRadius: '8px',
background:
'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
border: theme === 'default' ? '2px solid white' : 'none',
cursor: 'pointer',
}}
title="Default (Purple)"
/>
<button
onClick={() => handleThemeChange('warm')}
style={{
width: '40px',
height: '40px',
borderRadius: '8px',
background:
'linear-gradient(135deg, #FF8C42 0%, #FF6B35 100%)',
border: theme === 'warm' ? '2px solid white' : 'none',
cursor: 'pointer',
}}
title="Warm (Orange)"
/>
<button
onClick={() => handleThemeChange('cool')}
style={{
width: '40px',
height: '40px',
borderRadius: '8px',
background:
'linear-gradient(135deg, #06B6D4 0%, #0891B2 100%)',
border: theme === 'cool' ? '2px solid white' : 'none',
cursor: 'pointer',
}}
title="Cool (Cyan)"
/>
<button
onClick={() => handleThemeChange('premium')}
style={{
width: '40px',
height: '40px',
borderRadius: '8px',
background:
'linear-gradient(135deg, #D4AF37 0%, #B8960F 100%)',
border: theme === 'premium' ? '2px solid white' : 'none',
cursor: 'pointer',
}}
title="Premium (Gold)"
/>
</div>
);
}
Step 4: Update Mascot Colors
Sync mascot emotion colors with theme:
// Create theme-aware emotion configs
const getThemedEmotions = (theme = 'default') => {
const themeColors = {
default: {
joy: '#FFD700',
calm: '#667eea',
excitement: '#FF6B9D',
},
warm: {
joy: '#FF8C42',
calm: '#FFB088',
excitement: '#FF6B35',
},
cool: {
joy: '#67E8F9',
calm: '#06B6D4',
excitement: '#22D3EE',
},
premium: {
joy: '#F4D03F',
calm: '#D4AF37',
excitement: '#E6C200',
},
};
return {
joy: {
...baseEmotions.joy,
color: themeColors[theme].joy,
},
calm: {
...baseEmotions.calm,
color: themeColors[theme].calm,
},
excitement: {
...baseEmotions.excitement,
color: themeColors[theme].excitement,
},
};
};
// Usage in component
const mascot = new EmotiveMascot({
containerId: 'mascot',
emotions: getThemedEmotions(currentTheme),
});
Files to Update
1. Global Styles
File: site/src/app/globals.css
Add CSS variable definitions for all themes
2. Home Page
File: site/src/app/page.tsx
Replace hardcoded colors:
- Hero gradient backgrounds
- Button colors
- Border colors
- Text gradients
- Section backgrounds
3. Components
Update these components to use CSS variables:
FeaturesShowcase.tsx:
// Update feature card borders and backgrounds
border: `1px solid var(--color-primary-light)`,
background: `linear-gradient(135deg, rgba(var(--color-primary-rgb), 0.15) 0%, rgba(var(--color-primary-rgb), 0.05) 100%)`
PremiumAIAssistant.tsx:
// Update panel styling
background: 'linear-gradient(135deg, var(--color-primary) 0%, var(--color-accent) 100%)';
Use Case Pages:
site/src/app/use-cases/retail/page.tsxsite/src/app/use-cases/smart-home/page.tsxsite/src/app/use-cases/healthcare/page.tsxsite/src/app/use-cases/education/page.tsx
4. Emotion Configs
File: src/config/emotions.js
Create theme-aware emotion color mappings
A/B Testing Implementation
Setup Analytics
// site/src/components/ThemeAnalytics.tsx
'use client';
import { useEffect } from 'react';
export function trackThemeImpression(theme: string) {
// Google Analytics
if (typeof window !== 'undefined' && window.gtag) {
window.gtag('event', 'theme_impression', {
theme_variant: theme,
timestamp: Date.now(),
});
}
// Or custom analytics
fetch('/api/analytics/theme-impression', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ theme, timestamp: Date.now() }),
});
}
export function trackThemeConversion(theme: string, action: string) {
if (typeof window !== 'undefined' && window.gtag) {
window.gtag('event', 'theme_conversion', {
theme_variant: theme,
conversion_action: action,
timestamp: Date.now(),
});
}
}
Random Theme Assignment
// site/src/app/layout.tsx
'use client';
import { useEffect, useState } from 'react';
export default function RootLayout({ children }) {
const [theme, setTheme] = useState<string>('default');
useEffect(() => {
// Check if user already has a theme assigned
let assignedTheme = localStorage.getItem('ab-theme');
if (!assignedTheme) {
// Randomly assign theme for A/B test
const themes = ['default', 'warm', 'cool', 'premium'];
assignedTheme = themes[Math.floor(Math.random() * themes.length)];
localStorage.setItem('ab-theme', assignedTheme);
}
setTheme(assignedTheme);
document.documentElement.setAttribute('data-theme', assignedTheme);
// Track impression
trackThemeImpression(assignedTheme);
}, []);
return (
<html lang="en" data-theme={theme}>
<body>{children}</body>
</html>
);
}
Track Conversions
// In waitlist form
const handleSubmit = async (email: string) => {
// Submit form
await submitWaitlist(email);
// Track conversion with current theme
const theme = document.documentElement.getAttribute('data-theme');
trackThemeConversion(theme, 'waitlist_signup');
};
// In demo interactions
const handleDemoStart = () => {
const theme = document.documentElement.getAttribute('data-theme');
trackThemeConversion(theme, 'demo_started');
};
RGB Color Utilities
For rgba() usage, add RGB values to CSS:
:root {
--color-primary: #667eea;
--color-primary-rgb: 102, 126, 234; /* For rgba() */
}
[data-theme='warm'] {
--color-primary: #ff8c42;
--color-primary-rgb: 255, 140, 66;
}
Or use JavaScript:
function hexToRgb(hex) {
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
return result
? {
r: parseInt(result[1], 16),
g: parseInt(result[2], 16),
b: parseInt(result[3], 16),
}
: null;
}
// Usage
const rgb = hexToRgb('#667eea');
const rgba = `rgba(${rgb.r}, ${rgb.g}, ${rgb.b}, 0.3)`;
Testing Checklist
- All 4 themes render correctly on home page
- Theme switcher works and persists across page loads
- Mascot colors update when theme changes
- All use cases respect theme colors
- Mobile view looks good in all themes
- Contrast ratios meet WCAG AA standards
- No hardcoded colors remain (search for hex codes)
- Analytics tracking captures theme impressions
- Conversion tracking works for each theme
- A/B test random assignment is balanced
Accessibility Considerations
Ensure sufficient contrast for all themes:
// Check contrast ratio (WCAG AA requires 4.5:1 for normal text)
function getContrastRatio(color1, color2) {
const l1 = getLuminance(color1);
const l2 = getLuminance(color2);
const lighter = Math.max(l1, l2);
const darker = Math.min(l1, l2);
return (lighter + 0.05) / (darker + 0.05);
}
function getLuminance(hex) {
const rgb = hexToRgb(hex);
const [r, g, b] = [rgb.r, rgb.g, rgb.b].map(val => {
val = val / 255;
return val <= 0.03928
? val / 12.92
: Math.pow((val + 0.055) / 1.055, 2.4);
});
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
}
// Test all themes
const themes = {
default: { bg: '#0a0a0a', text: '#ffffff' },
warm: { bg: '#0a0a0a', text: '#FF8C42' },
cool: { bg: '#0a0a0a', text: '#06B6D4' },
premium: { bg: '#0a0a0a', text: '#D4AF37' },
};
Object.entries(themes).forEach(([name, colors]) => {
const ratio = getContrastRatio(colors.bg, colors.text);
console.log(
`${name} theme contrast: ${ratio.toFixed(2)}:1 ${ratio >= 4.5 ? '✓' : '✗'}`
);
});
Quick Theme Application
Use this command to quickly apply a theme across the codebase:
# Find all hardcoded color references
grep -r "#667eea" site/src --include="*.tsx" --include="*.ts" --include="*.css"
# Replace with CSS variable (manual verification recommended)
find site/src -type f \( -name "*.tsx" -o -name "*.ts" -o -name "*.css" \) -exec sed -i 's/#667eea/var(--color-primary)/g' {} +
Key Files
- Global Styles:
site/src/app/globals.css - Theme Switcher:
site/src/components/ThemeSwitcher.tsx - Analytics:
site/src/components/ThemeAnalytics.tsx - Emotion Themes:
src/config/emotions-themed.js - Home Page:
site/src/app/page.tsx - Use Cases:
site/src/app/use-cases/*/page.tsx
Resources
Repository
