color-palette
Generate complete, accessible colour palettes from a single brand hex. Produces 11-shade scale (50-950), semantic tokens, dark mode variants, Tailwind v4 CSS output, WCAG contrast checks. Use whenever the user supplies a brand hex and asks for a palette, mentions setting up a design system, wants Tailwind theme colours from a brand colour, or asks to check colour accessibility / contrast.
What this skill does
# Colour Palette Generator
Generate a complete, accessible colour system from a single brand hex. Produces Tailwind v4 CSS ready to paste into your project.
## Workflow
### Step 1: Get the Brand Hex
Ask for the primary brand colour. A single hex like `#0D9488` is enough.
### Step 2: Generate 11-Shade Scale
Convert hex to HSL, then generate shades by varying lightness while keeping hue constant.
#### Hex to HSL Conversion
```javascript
function hexToHSL(hex) {
hex = hex.replace(/^#/, '');
const r = parseInt(hex.substring(0, 2), 16) / 255;
const g = parseInt(hex.substring(2, 4), 16) / 255;
const b = parseInt(hex.substring(4, 6), 16) / 255;
const max = Math.max(r, g, b);
const min = Math.min(r, g, b);
const diff = max - min;
let l = (max + min) / 2;
let s = 0;
if (diff !== 0) {
s = l > 0.5 ? diff / (2 - max - min) : diff / (max + min);
}
let h = 0;
if (diff !== 0) {
if (max === r) h = ((g - b) / diff + (g < b ? 6 : 0)) / 6;
else if (max === g) h = ((b - r) / diff + 2) / 6;
else h = ((r - g) / diff + 4) / 6;
}
return { h: Math.round(h * 360), s: Math.round(s * 100), l: Math.round(l * 100) };
}
```
#### Lightness and Saturation Values
| Shade | Lightness | Saturation Mult | Use Case |
|-------|-----------|-----------------|----------|
| 50 | 97% | 0.80 | Subtle backgrounds |
| 100 | 94% | 0.80 | Hover states |
| 200 | 87% | 0.85 | Borders, dividers |
| 300 | 75% | 0.90 | Disabled states |
| 400 | 62% | 0.95 | Placeholder text |
| 500 | 48% | 1.00 | **Brand colour baseline** |
| 600 | 40% | 1.00 | Primary actions (often the brand colour) |
| 700 | 33% | 1.00 | Hover on primary |
| 800 | 27% | 1.00 | Active states |
| 900 | 20% | 1.00 | Text on light bg |
| 950 | 10% | 1.00 | Darkest accents |
Reduce saturation for lighter shades (50-200 by 15-20%, 300-400 by 5-10%) to prevent overly vibrant pastels. Keep full saturation for 500-950.
#### Complete Scale Generator
```javascript
function generateShadeScale(brandHex) {
const { h, s } = hexToHSL(brandHex);
const shades = {
50: { l: 97, sMul: 0.8 }, 100: { l: 94, sMul: 0.8 },
200: { l: 87, sMul: 0.85 }, 300: { l: 75, sMul: 0.9 },
400: { l: 62, sMul: 0.95 }, 500: { l: 48, sMul: 1.0 },
600: { l: 40, sMul: 1.0 }, 700: { l: 33, sMul: 1.0 },
800: { l: 27, sMul: 1.0 }, 900: { l: 20, sMul: 1.0 },
950: { l: 10, sMul: 1.0 }
};
const result = {};
for (const [shade, { l, sMul }] of Object.entries(shades)) {
result[shade] = `hsl(${h}, ${Math.round(s * sMul)}%, ${l}%)`;
}
return result;
}
```
#### HSL to Hex Conversion
```javascript
function hslToHex(h, s, l) {
s = s / 100; l = l / 100;
const c = (1 - Math.abs(2 * l - 1)) * s;
const x = c * (1 - Math.abs((h / 60) % 2 - 1));
const m = l - c / 2;
let r = 0, g = 0, b = 0;
if (h < 60) { r = c; g = x; }
else if (h < 120) { r = x; g = c; }
else if (h < 180) { g = c; b = x; }
else if (h < 240) { g = x; b = c; }
else if (h < 300) { r = x; b = c; }
else { r = c; b = x; }
r = Math.round((r + m) * 255);
g = Math.round((g + m) * 255);
b = Math.round((b + m) * 255);
return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`.toUpperCase();
}
```
#### Verification
Generated shades should look like the same colour family with smooth progression. Light shades (50-300) usable for backgrounds, dark shades (700-950) usable for text. Brand colour recognisable in 500-700.
---
### Step 3: Map Semantic Tokens
Every background token MUST have a paired foreground token. Never use a background without its pair or dark mode will break.
#### Light Mode Tokens
| Token | Shade | Use Case |
|-------|-------|----------|
| `background` | white | Page backgrounds |
| `foreground` | 950 | Body text |
| `card` | white | Card backgrounds |
| `card-foreground` | 900 | Card text |
| `popover` | white | Dropdown/tooltip backgrounds |
| `popover-foreground` | 950 | Dropdown text |
| `primary` | 600 | Primary buttons, links |
| `primary-foreground` | white | Text on primary buttons |
| `secondary` | 100 | Secondary buttons |
| `secondary-foreground` | 900 | Text on secondary buttons |
| `muted` | 50 | Disabled backgrounds, subtle sections |
| `muted-foreground` | 600 | Muted text, captions |
| `accent` | 100 | Hover states, subtle highlights |
| `accent-foreground` | 900 | Text on accent backgrounds |
| `destructive` | red-600 | Delete buttons, errors |
| `destructive-foreground` | white | Text on destructive buttons |
| `border` | 200 | Input borders, dividers |
| `input` | 200 | Input field borders |
| `ring` | 600 | Focus rings |
#### Dark Mode Tokens
| Token | Shade | Use Case |
|-------|-------|----------|
| `background` | 950 | Page backgrounds |
| `foreground` | 50 | Body text |
| `card` | 900 | Card backgrounds |
| `card-foreground` | 50 | Card text |
| `popover` | 900 | Dropdown backgrounds |
| `popover-foreground` | 50 | Dropdown text |
| `primary` | 500 | Primary buttons (brighter in dark) |
| `primary-foreground` | white | Text on primary buttons |
| `secondary` | 800 | Secondary buttons |
| `secondary-foreground` | 50 | Text on secondary buttons |
| `muted` | 800 | Disabled backgrounds |
| `muted-foreground` | 400 | Muted text |
| `accent` | 800 | Hover states |
| `accent-foreground` | 50 | Text on accent backgrounds |
| `destructive` | red-500 | Delete buttons (brighter) |
| `destructive-foreground` | white | Text on destructive |
| `border` | 800 | Borders |
| `input` | 800 | Input borders |
| `ring` | 500 | Focus rings |
#### Dark Mode Inversion Pattern
Dark mode inverts lightness while preserving hue and saturation. Swap extremes (50 becomes 950, 950 becomes 50), preserve middle (500 stays near 500).
| Light Shade | Dark Equivalent | Role |
|-------------|-----------------|------|
| 50 | 950 | Backgrounds |
| 100 | 900 | Subtle backgrounds |
| 200 | 800 | Borders |
| 500 | 500 (slightly brighter) | Brand baseline |
| 600 | 400 | Primary actions |
| 950 | 50 | Text colour |
Key dark mode principles:
- Use shade 500 (not 600) for primary -- brighter for visibility on dark backgrounds
- Use shade 50 (off-white) for text instead of pure `#FFFFFF` -- easier on eyes
- Borders need ~10-15% lighter than background (e.g. 800 border on 950 background)
- Higher elevation = lighter colour (opposite of light mode shadows)
- Always update foreground when changing background
---
### Step 4: Check Contrast
#### WCAG Minimum Ratios
| Content Type | AA | AAA |
|--------------|-----|-----|
| Normal text (<18px or <14px bold) | 4.5:1 | 7:1 |
| Large text (>=18px or >=14px bold) | 3:1 | 4.5:1 |
| UI components (buttons, borders) | 3:1 | Not defined |
| Graphical objects (icons, charts) | 3:1 | Not defined |
Target AA for most projects, AAA for high-accessibility needs (government, healthcare).
#### Luminance and Contrast Formulas
```javascript
function getLuminance(hex) {
hex = hex.replace(/^#/, '');
const r = parseInt(hex.substring(0, 2), 16) / 255;
const g = parseInt(hex.substring(2, 4), 16) / 255;
const b = parseInt(hex.substring(4, 6), 16) / 255;
const rsRGB = r <= 0.03928 ? r / 12.92 : Math.pow((r + 0.055) / 1.055, 2.4);
const gsRGB = g <= 0.03928 ? g / 12.92 : Math.pow((g + 0.055) / 1.055, 2.4);
const bsRGB = b <= 0.03928 ? b / 12.92 : Math.pow((b + 0.055) / 1.055, 2.4);
return 0.2126 * rsRGB + 0.7152 * gsRGB + 0.0722 * bsRGB;
}
function getContrastRatio(hex1, hex2) {
const lum1 = getLuminance(hex1);
const lum2 = getLuminance(hex2);
const lighter = Math.max(lum1, lum2);
const darker = Math.min(lum1, lum2);
return (lighter + 0.05) / (darker + 0.05);
}
```
#### Quick Check Table -- Light Mode
| Foreground | Background | Ratio | Pass? | Use Case |
|------------|------------|-------|-------|----------|
| 950 | white | 18.5:1 | AAA | Body text |
| 900 | white | 14.2:1 | AAA | Card text |
| 700 | white | 8.1:1 | AAA | Text |
| 600 | white | 5.7:1 | AA | Text, buttons |
| 500 | wRelated in Ads & Marketing
ads
IncludedMulti-platform paid advertising audit and optimization skill. Analyzes Google, Meta, YouTube, LinkedIn, TikTok, Microsoft, and Apple Ads. 250+ checks with scoring, parallel agents, industry templates, and AI creative generation.
banana
IncludedAI image generation Creative Director powered by Google Gemini Nano Banana models. Use this skill for ANY request involving image creation, editing, visual asset production, or creative direction. Triggers on: generate an image, create a photo, edit this picture, design a logo, make a banner, visual for my anything, and all /banana commands. Handles text-to-image, image editing, multi-turn creative sessions, batch workflows, and brand presets.
rpg-migration-analyzer
IncludedAnalyzes legacy RPG (Report Program Generator) programs from AS/400 and IBM i systems for migration to modern Java applications. Extracts business logic from RPG III/IV/ILE source code, identifies data structures (D-specs), file operations (F-specs), program dependencies (CALLB/CALLP), and converts RPG constructs to Java equivalents. Generates migration reports, complexity estimates, and Java implementation strategies with POJO classes, JPA entities, and service methods. Use when modernizing AS/400 or IBM i legacy systems, analyzing RPG source files (.rpg, .rpgle, .RPGLE), converting RPG to Java, mapping data specifications to Java classes, planning legacy system migration, or when user mentions RPG analysis, Report Program Generator, RPG III/IV/ILE, AS/400 modernization, IBM i migration, packed decimal conversion, or mainframe application rewrite.
brand-library-architect
IncludedBuild a complete brand library for a product — visual asset render pipeline, brand documentation set (BRAND, COPY, MANIFESTO, BIOS, FAQ, GLOSSARY, TONE, PRICING), open-source convention files (README, CONTRIBUTING, SECURITY, CODE_OF_CONDUCT), and a self-contained press kit. This skill should be used when the user asks to "build a brand library / brand kit / press kit / brand assets" for a product, "set up a brand library workflow," "create a positioning manifesto plus visual identity," or any combination of brand documentation + visual asset pipeline. Apply phase-by-phase or run end-to-end. Templates are product-agnostic and use {{TOKEN}} placeholders the skill prompts the user to fill.
writing-tech-post
IncludedAuthors engineering blog posts end-to-end: launch deep-dives, incident postmortems, architecture migrations, performance case studies, tutorials, AI/agent system writeups, security disclosures, and research-to-product translations. Picks the correct archetype, plans the abstraction ladder, enforces an evidence cadence (diagrams, benchmarks, profiles, traces, code, ablations), tunes voice against publisher house styles (Datadog, Vercel, GitHub, AWS, Meta, Cloudflare, Jane Street), and runs a pre-publish gate for narrative momentum and disclosure ethics. Use when drafting a new engineering post, restructuring a draft that feels flat, deciding which evidence form belongs where, validating that depth and product context are balanced, or preparing a postmortem, migration, or performance narrative for external publication. Do not use for API reference documentation, README authoring, marketing copy, release notes, generic SEO content, ghost-written executive thought leadership, or non-engineering long-form essays.
blog-google
IncludedGoogle API integration for blog performance: PageSpeed Insights, CrUX Core Web Vitals with 25-week history, Search Console performance, URL Inspection, Indexing API, GA4 organic traffic, NLP entity analysis for E-E-A-T, YouTube video search for embedding, and Google Ads Keyword Planner. Progressive feature availability based on credential tier (API key, OAuth/service account, GA4, Ads). Shares config with claude-seo at ~/.config/claude-seo/google-api.json. Use when user says "google data", "page speed", "core web vitals", "search console", "indexation", "GA4", "keyword research", "nlp entities", "blog performance", "youtube search", "google api setup".