From e3102cb7ede8c5edbb0ac7011e4f7098e54f98c0 Mon Sep 17 00:00:00 2001 From: Jens Date: Sun, 15 Mar 2026 11:08:47 +0100 Subject: [PATCH 01/50] Improve design system output with Unicode borders, ANSI color swatches, extended palette, and dark/light mode Upgrade the design system terminal output from basic ASCII to Unicode box-drawing characters, add ANSI true color swatches with graceful fallback, expand the color palette from 5 to 10 colors (Primary, On Primary, Secondary, Accent, Background, Foreground, Muted, Border, Destructive, Ring) with CSS variable names, and surface Light/Dark mode support from styles.csv. Co-Authored-By: Claude Opus 4.6 --- cli/assets/scripts/core.py | 12 +- cli/assets/scripts/design_system.py | 219 ++++++++++++++------- src/ui-ux-pro-max/scripts/core.py | 2 +- src/ui-ux-pro-max/scripts/design_system.py | 219 ++++++++++++++------- 4 files changed, 310 insertions(+), 142 deletions(-) diff --git a/cli/assets/scripts/core.py b/cli/assets/scripts/core.py index a173cceae..ad200d139 100644 --- a/cli/assets/scripts/core.py +++ b/cli/assets/scripts/core.py @@ -18,7 +18,7 @@ "style": { "file": "styles.csv", "search_cols": ["Style Category", "Keywords", "Best For", "Type", "AI Prompt Keywords"], - "output_cols": ["Style Category", "Type", "Keywords", "Primary Colors", "Effects & Animation", "Best For", "Performance", "Accessibility", "Framework Compatibility", "Complexity", "AI Prompt Keywords", "CSS/Technical Keywords", "Implementation Checklist", "Design System Variables"] + "output_cols": ["Style Category", "Type", "Keywords", "Primary Colors", "Effects & Animation", "Best For", "Light Mode ✓", "Dark Mode ✓", "Performance", "Accessibility", "Framework Compatibility", "Complexity", "AI Prompt Keywords", "CSS/Technical Keywords", "Implementation Checklist", "Design System Variables"] }, "color": { "file": "colors.csv", @@ -64,6 +64,11 @@ "file": "app-interface.csv", "search_cols": ["Category", "Issue", "Keywords", "Description"], "output_cols": ["Category", "Issue", "Platform", "Description", "Do", "Don't", "Code Example Good", "Code Example Bad", "Severity"] + }, + "google-fonts": { + "file": "google-fonts.csv", + "search_cols": ["Family", "Category", "Stroke", "Classifications", "Keywords", "Subsets", "Designers"], + "output_cols": ["Family", "Category", "Stroke", "Classifications", "Styles", "Variable Axes", "Subsets", "Designers", "Popularity Rank", "Google Fonts URL"] } } @@ -186,13 +191,14 @@ def detect_domain(query): "product": ["saas", "ecommerce", "e-commerce", "fintech", "healthcare", "gaming", "portfolio", "crypto", "dashboard", "fitness", "restaurant", "hotel", "travel", "music", "education", "learning", "legal", "insurance", "medical", "beauty", "pharmacy", "dental", "pet", "dating", "wedding", "recipe", "delivery", "ride", "booking", "calendar", "timer", "tracker", "diary", "note", "chat", "messenger", "crm", "invoice", "parking", "transit", "vpn", "alarm", "weather", "sleep", "meditation", "fasting", "habit", "grocery", "meme", "wardrobe", "plant care", "reading", "flashcard", "puzzle", "trivia", "arcade", "photography", "streaming", "podcast", "newsletter", "marketplace", "freelancer", "coworking", "airline", "museum", "theater", "church", "non-profit", "charity", "kindergarten", "daycare", "senior care", "veterinary", "florist", "bakery", "brewery", "construction", "automotive", "real estate", "logistics", "agriculture", "coding bootcamp"], "style": ["style", "design", "ui", "minimalism", "glassmorphism", "neumorphism", "brutalism", "dark mode", "flat", "aurora", "prompt", "css", "implementation", "variable", "checklist", "tailwind"], "ux": ["ux", "usability", "accessibility", "wcag", "touch", "scroll", "animation", "keyboard", "navigation", "mobile"], - "typography": ["font", "typography", "heading", "serif", "sans"], + "typography": ["font pairing", "typography pairing", "heading font", "body font"], + "google-fonts": ["google font", "font family", "font weight", "font style", "variable font", "noto", "font for", "find font", "font subset", "font language", "monospace font", "serif font", "sans serif font", "display font", "handwriting font", "font", "typography", "serif", "sans"], "icons": ["icon", "icons", "lucide", "heroicons", "symbol", "glyph", "pictogram", "svg icon"], "react": ["react", "next.js", "nextjs", "suspense", "memo", "usecallback", "useeffect", "rerender", "bundle", "waterfall", "barrel", "dynamic import", "rsc", "server component"], "web": ["aria", "focus", "outline", "semantic", "virtualize", "autocomplete", "form", "input type", "preconnect"] } - scores = {domain: sum(1 for kw in keywords if kw in query_lower) for domain, keywords in domain_keywords.items()} + scores = {domain: sum(1 for kw in keywords if re.search(r'\b' + re.escape(kw) + r'\b', query_lower)) for domain, keywords in domain_keywords.items()} best = max(scores, key=scores.get) return best if scores[best] > 0 else "style" diff --git a/cli/assets/scripts/design_system.py b/cli/assets/scripts/design_system.py index 209de2073..d3152e5fb 100644 --- a/cli/assets/scripts/design_system.py +++ b/cli/assets/scripts/design_system.py @@ -211,15 +211,25 @@ def generate(self, query: str, project_name: str = None) -> dict: "keywords": best_style.get("Keywords", ""), "best_for": best_style.get("Best For", ""), "performance": best_style.get("Performance", ""), - "accessibility": best_style.get("Accessibility", "") + "accessibility": best_style.get("Accessibility", ""), + "light_mode": best_style.get("Light Mode ✓", ""), + "dark_mode": best_style.get("Dark Mode ✓", ""), }, "colors": { - "primary": best_color.get("Primary (Hex)", "#2563EB"), - "secondary": best_color.get("Secondary (Hex)", "#3B82F6"), - "cta": best_color.get("CTA (Hex)", "#F97316"), - "background": best_color.get("Background (Hex)", "#F8FAFC"), - "text": best_color.get("Text (Hex)", "#1E293B"), - "notes": best_color.get("Notes", "") + "primary": best_color.get("Primary", "#2563EB"), + "on_primary": best_color.get("On Primary", ""), + "secondary": best_color.get("Secondary", "#3B82F6"), + "accent": best_color.get("Accent", "#F97316"), + "background": best_color.get("Background", "#F8FAFC"), + "foreground": best_color.get("Foreground", "#1E293B"), + "muted": best_color.get("Muted", ""), + "border": best_color.get("Border", ""), + "destructive": best_color.get("Destructive", ""), + "ring": best_color.get("Ring", ""), + "notes": best_color.get("Notes", ""), + # Keep legacy keys for backward compat in MASTER.md + "cta": best_color.get("Accent", "#F97316"), + "text": best_color.get("Foreground", "#1E293B"), }, "typography": { "heading": best_typography.get("Heading Font", "Inter"), @@ -239,8 +249,38 @@ def generate(self, query: str, project_name: str = None) -> dict: # ============ OUTPUT FORMATTERS ============ BOX_WIDTH = 90 # Wider box for more content + +def hex_to_ansi(hex_color: str) -> str: + """Convert hex color to ANSI True Color swatch (██) with fallback.""" + if not hex_color or not hex_color.startswith('#'): + return "" + colorterm = os.environ.get('COLORTERM', '') + if colorterm not in ('truecolor', '24bit'): + return "" + hex_color = hex_color.lstrip('#') + if len(hex_color) != 6: + return "" + r, g, b = int(hex_color[0:2], 16), int(hex_color[2:4], 16), int(hex_color[4:6], 16) + return f"\033[38;2;{r};{g};{b}m██\033[0m " + + +def ansi_ljust(s: str, width: int) -> str: + """Like str.ljust but accounts for zero-width ANSI escape sequences.""" + import re + visible_len = len(re.sub(r'\033\[[0-9;]*m', '', s)) + pad = width - visible_len + return s + (" " * max(0, pad)) + + +def section_header(name: str, width: int) -> str: + """Create a Unicode section separator: ├─── NAME ───...┤""" + label = f"─── {name} " + fill = "─" * (width - len(label) - 1) + return f"├{label}{fill}┤" + + def format_ascii_box(design_system: dict) -> str: - """Format design system as ASCII box with emojis (MCP-style).""" + """Format design system as Unicode box with ANSI color swatches.""" project = design_system.get("project_name", "PROJECT") pattern = design_system.get("pattern", {}) style = design_system.get("style", {}) @@ -275,77 +315,93 @@ def wrap_text(text: str, prefix: str, width: int) -> list: lines = [] w = BOX_WIDTH - 1 - lines.append("+" + "-" * w + "+") - lines.append(f"| TARGET: {project} - RECOMMENDED DESIGN SYSTEM".ljust(BOX_WIDTH) + "|") - lines.append("+" + "-" * w + "+") - lines.append("|" + " " * BOX_WIDTH + "|") + # Header with double-line box + lines.append("╔" + "═" * w + "╗") + lines.append(ansi_ljust(f"║ TARGET: {project} - RECOMMENDED DESIGN SYSTEM", BOX_WIDTH) + "║") + lines.append("╚" + "═" * w + "╝") + lines.append("┌" + "─" * w + "┐") # Pattern section - lines.append(f"| PATTERN: {pattern.get('name', '')}".ljust(BOX_WIDTH) + "|") + lines.append(section_header("PATTERN", BOX_WIDTH + 1)) + lines.append(f"│ Name: {pattern.get('name', '')}".ljust(BOX_WIDTH) + "│") if pattern.get('conversion'): - lines.append(f"| Conversion: {pattern.get('conversion', '')}".ljust(BOX_WIDTH) + "|") + lines.append(f"│ Conversion: {pattern.get('conversion', '')}".ljust(BOX_WIDTH) + "│") if pattern.get('cta_placement'): - lines.append(f"| CTA: {pattern.get('cta_placement', '')}".ljust(BOX_WIDTH) + "|") - lines.append("| Sections:".ljust(BOX_WIDTH) + "|") + lines.append(f"│ CTA: {pattern.get('cta_placement', '')}".ljust(BOX_WIDTH) + "│") + lines.append("│ Sections:".ljust(BOX_WIDTH) + "│") for i, section in enumerate(sections, 1): - lines.append(f"| {i}. {section}".ljust(BOX_WIDTH) + "|") - lines.append("|" + " " * BOX_WIDTH + "|") + lines.append(f"│ {i}. {section}".ljust(BOX_WIDTH) + "│") # Style section - lines.append(f"| STYLE: {style.get('name', '')}".ljust(BOX_WIDTH) + "|") + lines.append(section_header("STYLE", BOX_WIDTH + 1)) + lines.append(f"│ Name: {style.get('name', '')}".ljust(BOX_WIDTH) + "│") + light = style.get("light_mode", "") + dark = style.get("dark_mode", "") + if light or dark: + lines.append(f"│ Mode Support: Light {light} Dark {dark}".ljust(BOX_WIDTH) + "│") if style.get("keywords"): - for line in wrap_text(f"Keywords: {style.get('keywords', '')}", "| ", BOX_WIDTH): - lines.append(line.ljust(BOX_WIDTH) + "|") + for line in wrap_text(f"Keywords: {style.get('keywords', '')}", "│ ", BOX_WIDTH): + lines.append(line.ljust(BOX_WIDTH) + "│") if style.get("best_for"): - for line in wrap_text(f"Best For: {style.get('best_for', '')}", "| ", BOX_WIDTH): - lines.append(line.ljust(BOX_WIDTH) + "|") + for line in wrap_text(f"Best For: {style.get('best_for', '')}", "│ ", BOX_WIDTH): + lines.append(line.ljust(BOX_WIDTH) + "│") if style.get("performance") or style.get("accessibility"): perf_a11y = f"Performance: {style.get('performance', '')} | Accessibility: {style.get('accessibility', '')}" - lines.append(f"| {perf_a11y}".ljust(BOX_WIDTH) + "|") - lines.append("|" + " " * BOX_WIDTH + "|") - - # Colors section - lines.append("| COLORS:".ljust(BOX_WIDTH) + "|") - lines.append(f"| Primary: {colors.get('primary', '')}".ljust(BOX_WIDTH) + "|") - lines.append(f"| Secondary: {colors.get('secondary', '')}".ljust(BOX_WIDTH) + "|") - lines.append(f"| CTA: {colors.get('cta', '')}".ljust(BOX_WIDTH) + "|") - lines.append(f"| Background: {colors.get('background', '')}".ljust(BOX_WIDTH) + "|") - lines.append(f"| Text: {colors.get('text', '')}".ljust(BOX_WIDTH) + "|") + lines.append(f"│ {perf_a11y}".ljust(BOX_WIDTH) + "│") + + # Colors section (extended palette with ANSI swatches) + lines.append(section_header("COLORS", BOX_WIDTH + 1)) + color_entries = [ + ("Primary", "primary", "--color-primary"), + ("On Primary", "on_primary", "--color-on-primary"), + ("Secondary", "secondary", "--color-secondary"), + ("Accent/CTA", "accent", "--color-accent"), + ("Background", "background", "--color-background"), + ("Foreground", "foreground", "--color-foreground"), + ("Muted", "muted", "--color-muted"), + ("Border", "border", "--color-border"), + ("Destructive", "destructive", "--color-destructive"), + ("Ring", "ring", "--color-ring"), + ] + for label, key, css_var in color_entries: + hex_val = colors.get(key, "") + if not hex_val: + continue + swatch = hex_to_ansi(hex_val) + content = f"│ {swatch}{label + ':':14s} {hex_val:10s} ({css_var})" + lines.append(ansi_ljust(content, BOX_WIDTH) + "│") if colors.get("notes"): - for line in wrap_text(f"Notes: {colors.get('notes', '')}", "| ", BOX_WIDTH): - lines.append(line.ljust(BOX_WIDTH) + "|") - lines.append("|" + " " * BOX_WIDTH + "|") + for line in wrap_text(f"Notes: {colors.get('notes', '')}", "│ ", BOX_WIDTH): + lines.append(line.ljust(BOX_WIDTH) + "│") # Typography section - lines.append(f"| TYPOGRAPHY: {typography.get('heading', '')} / {typography.get('body', '')}".ljust(BOX_WIDTH) + "|") + lines.append(section_header("TYPOGRAPHY", BOX_WIDTH + 1)) + lines.append(f"│ {typography.get('heading', '')} / {typography.get('body', '')}".ljust(BOX_WIDTH) + "│") if typography.get("mood"): - for line in wrap_text(f"Mood: {typography.get('mood', '')}", "| ", BOX_WIDTH): - lines.append(line.ljust(BOX_WIDTH) + "|") + for line in wrap_text(f"Mood: {typography.get('mood', '')}", "│ ", BOX_WIDTH): + lines.append(line.ljust(BOX_WIDTH) + "│") if typography.get("best_for"): - for line in wrap_text(f"Best For: {typography.get('best_for', '')}", "| ", BOX_WIDTH): - lines.append(line.ljust(BOX_WIDTH) + "|") + for line in wrap_text(f"Best For: {typography.get('best_for', '')}", "│ ", BOX_WIDTH): + lines.append(line.ljust(BOX_WIDTH) + "│") if typography.get("google_fonts_url"): - lines.append(f"| Google Fonts: {typography.get('google_fonts_url', '')}".ljust(BOX_WIDTH) + "|") + lines.append(f"│ Google Fonts: {typography.get('google_fonts_url', '')}".ljust(BOX_WIDTH) + "│") if typography.get("css_import"): - lines.append(f"| CSS Import: {typography.get('css_import', '')[:70]}...".ljust(BOX_WIDTH) + "|") - lines.append("|" + " " * BOX_WIDTH + "|") + lines.append(f"│ CSS Import: {typography.get('css_import', '')[:70]}...".ljust(BOX_WIDTH) + "│") # Key Effects section if effects: - lines.append("| KEY EFFECTS:".ljust(BOX_WIDTH) + "|") - for line in wrap_text(effects, "| ", BOX_WIDTH): - lines.append(line.ljust(BOX_WIDTH) + "|") - lines.append("|" + " " * BOX_WIDTH + "|") + lines.append(section_header("KEY EFFECTS", BOX_WIDTH + 1)) + for line in wrap_text(effects, "│ ", BOX_WIDTH): + lines.append(line.ljust(BOX_WIDTH) + "│") # Anti-patterns section if anti_patterns: - lines.append("| AVOID (Anti-patterns):".ljust(BOX_WIDTH) + "|") - for line in wrap_text(anti_patterns, "| ", BOX_WIDTH): - lines.append(line.ljust(BOX_WIDTH) + "|") - lines.append("|" + " " * BOX_WIDTH + "|") + lines.append(section_header("AVOID", BOX_WIDTH + 1)) + for line in wrap_text(anti_patterns, "│ ", BOX_WIDTH): + lines.append(line.ljust(BOX_WIDTH) + "│") # Pre-Delivery Checklist section - lines.append("| PRE-DELIVERY CHECKLIST:".ljust(BOX_WIDTH) + "|") + lines.append(section_header("PRE-DELIVERY CHECKLIST", BOX_WIDTH + 1)) checklist_items = [ "[ ] No emojis as icons (use SVG: Heroicons/Lucide)", "[ ] cursor-pointer on all clickable elements", @@ -356,10 +412,9 @@ def wrap_text(text: str, prefix: str, width: int) -> list: "[ ] Responsive: 375px, 768px, 1024px, 1440px" ] for item in checklist_items: - lines.append(f"| {item}".ljust(BOX_WIDTH) + "|") - lines.append("|" + " " * BOX_WIDTH + "|") + lines.append(f"│ {item}".ljust(BOX_WIDTH) + "│") - lines.append("+" + "-" * w + "+") + lines.append("└" + "─" * w + "┘") return "\n".join(lines) @@ -393,6 +448,10 @@ def format_markdown(design_system: dict) -> str: # Style section lines.append("### Style") lines.append(f"- **Name:** {style.get('name', '')}") + light = style.get("light_mode", "") + dark = style.get("dark_mode", "") + if light or dark: + lines.append(f"- **Mode Support:** Light {light} | Dark {dark}") if style.get('keywords'): lines.append(f"- **Keywords:** {style.get('keywords', '')}") if style.get('best_for'): @@ -401,15 +460,26 @@ def format_markdown(design_system: dict) -> str: lines.append(f"- **Performance:** {style.get('performance', '')} | **Accessibility:** {style.get('accessibility', '')}") lines.append("") - # Colors section + # Colors section (extended palette) lines.append("### Colors") - lines.append(f"| Role | Hex |") - lines.append(f"|------|-----|") - lines.append(f"| Primary | {colors.get('primary', '')} |") - lines.append(f"| Secondary | {colors.get('secondary', '')} |") - lines.append(f"| CTA | {colors.get('cta', '')} |") - lines.append(f"| Background | {colors.get('background', '')} |") - lines.append(f"| Text | {colors.get('text', '')} |") + lines.append("| Role | Hex | CSS Variable |") + lines.append("|------|-----|--------------|") + md_color_entries = [ + ("Primary", "primary", "--color-primary"), + ("On Primary", "on_primary", "--color-on-primary"), + ("Secondary", "secondary", "--color-secondary"), + ("Accent/CTA", "accent", "--color-accent"), + ("Background", "background", "--color-background"), + ("Foreground", "foreground", "--color-foreground"), + ("Muted", "muted", "--color-muted"), + ("Border", "border", "--color-border"), + ("Destructive", "destructive", "--color-destructive"), + ("Ring", "ring", "--color-ring"), + ] + for label, key, css_var in md_color_entries: + hex_val = colors.get(key, "") + if hex_val: + lines.append(f"| {label} | `{hex_val}` | `{css_var}` |") if colors.get("notes"): lines.append(f"\n*Notes: {colors.get('notes', '')}*") lines.append("") @@ -578,11 +648,22 @@ def format_master_md(design_system: dict) -> str: lines.append("") lines.append("| Role | Hex | CSS Variable |") lines.append("|------|-----|--------------|") - lines.append(f"| Primary | `{colors.get('primary', '#2563EB')}` | `--color-primary` |") - lines.append(f"| Secondary | `{colors.get('secondary', '#3B82F6')}` | `--color-secondary` |") - lines.append(f"| CTA/Accent | `{colors.get('cta', '#F97316')}` | `--color-cta` |") - lines.append(f"| Background | `{colors.get('background', '#F8FAFC')}` | `--color-background` |") - lines.append(f"| Text | `{colors.get('text', '#1E293B')}` | `--color-text` |") + master_color_entries = [ + ("Primary", "primary", "--color-primary"), + ("On Primary", "on_primary", "--color-on-primary"), + ("Secondary", "secondary", "--color-secondary"), + ("Accent/CTA", "accent", "--color-accent"), + ("Background", "background", "--color-background"), + ("Foreground", "foreground", "--color-foreground"), + ("Muted", "muted", "--color-muted"), + ("Border", "border", "--color-border"), + ("Destructive", "destructive", "--color-destructive"), + ("Ring", "ring", "--color-ring"), + ] + for label, key, css_var in master_color_entries: + hex_val = colors.get(key, "") + if hex_val: + lines.append(f"| {label} | `{hex_val}` | `{css_var}` |") lines.append("") if colors.get("notes"): lines.append(f"**Color Notes:** {colors.get('notes', '')}") diff --git a/src/ui-ux-pro-max/scripts/core.py b/src/ui-ux-pro-max/scripts/core.py index f3286f8d3..ad200d139 100644 --- a/src/ui-ux-pro-max/scripts/core.py +++ b/src/ui-ux-pro-max/scripts/core.py @@ -18,7 +18,7 @@ "style": { "file": "styles.csv", "search_cols": ["Style Category", "Keywords", "Best For", "Type", "AI Prompt Keywords"], - "output_cols": ["Style Category", "Type", "Keywords", "Primary Colors", "Effects & Animation", "Best For", "Performance", "Accessibility", "Framework Compatibility", "Complexity", "AI Prompt Keywords", "CSS/Technical Keywords", "Implementation Checklist", "Design System Variables"] + "output_cols": ["Style Category", "Type", "Keywords", "Primary Colors", "Effects & Animation", "Best For", "Light Mode ✓", "Dark Mode ✓", "Performance", "Accessibility", "Framework Compatibility", "Complexity", "AI Prompt Keywords", "CSS/Technical Keywords", "Implementation Checklist", "Design System Variables"] }, "color": { "file": "colors.csv", diff --git a/src/ui-ux-pro-max/scripts/design_system.py b/src/ui-ux-pro-max/scripts/design_system.py index 209de2073..d3152e5fb 100644 --- a/src/ui-ux-pro-max/scripts/design_system.py +++ b/src/ui-ux-pro-max/scripts/design_system.py @@ -211,15 +211,25 @@ def generate(self, query: str, project_name: str = None) -> dict: "keywords": best_style.get("Keywords", ""), "best_for": best_style.get("Best For", ""), "performance": best_style.get("Performance", ""), - "accessibility": best_style.get("Accessibility", "") + "accessibility": best_style.get("Accessibility", ""), + "light_mode": best_style.get("Light Mode ✓", ""), + "dark_mode": best_style.get("Dark Mode ✓", ""), }, "colors": { - "primary": best_color.get("Primary (Hex)", "#2563EB"), - "secondary": best_color.get("Secondary (Hex)", "#3B82F6"), - "cta": best_color.get("CTA (Hex)", "#F97316"), - "background": best_color.get("Background (Hex)", "#F8FAFC"), - "text": best_color.get("Text (Hex)", "#1E293B"), - "notes": best_color.get("Notes", "") + "primary": best_color.get("Primary", "#2563EB"), + "on_primary": best_color.get("On Primary", ""), + "secondary": best_color.get("Secondary", "#3B82F6"), + "accent": best_color.get("Accent", "#F97316"), + "background": best_color.get("Background", "#F8FAFC"), + "foreground": best_color.get("Foreground", "#1E293B"), + "muted": best_color.get("Muted", ""), + "border": best_color.get("Border", ""), + "destructive": best_color.get("Destructive", ""), + "ring": best_color.get("Ring", ""), + "notes": best_color.get("Notes", ""), + # Keep legacy keys for backward compat in MASTER.md + "cta": best_color.get("Accent", "#F97316"), + "text": best_color.get("Foreground", "#1E293B"), }, "typography": { "heading": best_typography.get("Heading Font", "Inter"), @@ -239,8 +249,38 @@ def generate(self, query: str, project_name: str = None) -> dict: # ============ OUTPUT FORMATTERS ============ BOX_WIDTH = 90 # Wider box for more content + +def hex_to_ansi(hex_color: str) -> str: + """Convert hex color to ANSI True Color swatch (██) with fallback.""" + if not hex_color or not hex_color.startswith('#'): + return "" + colorterm = os.environ.get('COLORTERM', '') + if colorterm not in ('truecolor', '24bit'): + return "" + hex_color = hex_color.lstrip('#') + if len(hex_color) != 6: + return "" + r, g, b = int(hex_color[0:2], 16), int(hex_color[2:4], 16), int(hex_color[4:6], 16) + return f"\033[38;2;{r};{g};{b}m██\033[0m " + + +def ansi_ljust(s: str, width: int) -> str: + """Like str.ljust but accounts for zero-width ANSI escape sequences.""" + import re + visible_len = len(re.sub(r'\033\[[0-9;]*m', '', s)) + pad = width - visible_len + return s + (" " * max(0, pad)) + + +def section_header(name: str, width: int) -> str: + """Create a Unicode section separator: ├─── NAME ───...┤""" + label = f"─── {name} " + fill = "─" * (width - len(label) - 1) + return f"├{label}{fill}┤" + + def format_ascii_box(design_system: dict) -> str: - """Format design system as ASCII box with emojis (MCP-style).""" + """Format design system as Unicode box with ANSI color swatches.""" project = design_system.get("project_name", "PROJECT") pattern = design_system.get("pattern", {}) style = design_system.get("style", {}) @@ -275,77 +315,93 @@ def wrap_text(text: str, prefix: str, width: int) -> list: lines = [] w = BOX_WIDTH - 1 - lines.append("+" + "-" * w + "+") - lines.append(f"| TARGET: {project} - RECOMMENDED DESIGN SYSTEM".ljust(BOX_WIDTH) + "|") - lines.append("+" + "-" * w + "+") - lines.append("|" + " " * BOX_WIDTH + "|") + # Header with double-line box + lines.append("╔" + "═" * w + "╗") + lines.append(ansi_ljust(f"║ TARGET: {project} - RECOMMENDED DESIGN SYSTEM", BOX_WIDTH) + "║") + lines.append("╚" + "═" * w + "╝") + lines.append("┌" + "─" * w + "┐") # Pattern section - lines.append(f"| PATTERN: {pattern.get('name', '')}".ljust(BOX_WIDTH) + "|") + lines.append(section_header("PATTERN", BOX_WIDTH + 1)) + lines.append(f"│ Name: {pattern.get('name', '')}".ljust(BOX_WIDTH) + "│") if pattern.get('conversion'): - lines.append(f"| Conversion: {pattern.get('conversion', '')}".ljust(BOX_WIDTH) + "|") + lines.append(f"│ Conversion: {pattern.get('conversion', '')}".ljust(BOX_WIDTH) + "│") if pattern.get('cta_placement'): - lines.append(f"| CTA: {pattern.get('cta_placement', '')}".ljust(BOX_WIDTH) + "|") - lines.append("| Sections:".ljust(BOX_WIDTH) + "|") + lines.append(f"│ CTA: {pattern.get('cta_placement', '')}".ljust(BOX_WIDTH) + "│") + lines.append("│ Sections:".ljust(BOX_WIDTH) + "│") for i, section in enumerate(sections, 1): - lines.append(f"| {i}. {section}".ljust(BOX_WIDTH) + "|") - lines.append("|" + " " * BOX_WIDTH + "|") + lines.append(f"│ {i}. {section}".ljust(BOX_WIDTH) + "│") # Style section - lines.append(f"| STYLE: {style.get('name', '')}".ljust(BOX_WIDTH) + "|") + lines.append(section_header("STYLE", BOX_WIDTH + 1)) + lines.append(f"│ Name: {style.get('name', '')}".ljust(BOX_WIDTH) + "│") + light = style.get("light_mode", "") + dark = style.get("dark_mode", "") + if light or dark: + lines.append(f"│ Mode Support: Light {light} Dark {dark}".ljust(BOX_WIDTH) + "│") if style.get("keywords"): - for line in wrap_text(f"Keywords: {style.get('keywords', '')}", "| ", BOX_WIDTH): - lines.append(line.ljust(BOX_WIDTH) + "|") + for line in wrap_text(f"Keywords: {style.get('keywords', '')}", "│ ", BOX_WIDTH): + lines.append(line.ljust(BOX_WIDTH) + "│") if style.get("best_for"): - for line in wrap_text(f"Best For: {style.get('best_for', '')}", "| ", BOX_WIDTH): - lines.append(line.ljust(BOX_WIDTH) + "|") + for line in wrap_text(f"Best For: {style.get('best_for', '')}", "│ ", BOX_WIDTH): + lines.append(line.ljust(BOX_WIDTH) + "│") if style.get("performance") or style.get("accessibility"): perf_a11y = f"Performance: {style.get('performance', '')} | Accessibility: {style.get('accessibility', '')}" - lines.append(f"| {perf_a11y}".ljust(BOX_WIDTH) + "|") - lines.append("|" + " " * BOX_WIDTH + "|") - - # Colors section - lines.append("| COLORS:".ljust(BOX_WIDTH) + "|") - lines.append(f"| Primary: {colors.get('primary', '')}".ljust(BOX_WIDTH) + "|") - lines.append(f"| Secondary: {colors.get('secondary', '')}".ljust(BOX_WIDTH) + "|") - lines.append(f"| CTA: {colors.get('cta', '')}".ljust(BOX_WIDTH) + "|") - lines.append(f"| Background: {colors.get('background', '')}".ljust(BOX_WIDTH) + "|") - lines.append(f"| Text: {colors.get('text', '')}".ljust(BOX_WIDTH) + "|") + lines.append(f"│ {perf_a11y}".ljust(BOX_WIDTH) + "│") + + # Colors section (extended palette with ANSI swatches) + lines.append(section_header("COLORS", BOX_WIDTH + 1)) + color_entries = [ + ("Primary", "primary", "--color-primary"), + ("On Primary", "on_primary", "--color-on-primary"), + ("Secondary", "secondary", "--color-secondary"), + ("Accent/CTA", "accent", "--color-accent"), + ("Background", "background", "--color-background"), + ("Foreground", "foreground", "--color-foreground"), + ("Muted", "muted", "--color-muted"), + ("Border", "border", "--color-border"), + ("Destructive", "destructive", "--color-destructive"), + ("Ring", "ring", "--color-ring"), + ] + for label, key, css_var in color_entries: + hex_val = colors.get(key, "") + if not hex_val: + continue + swatch = hex_to_ansi(hex_val) + content = f"│ {swatch}{label + ':':14s} {hex_val:10s} ({css_var})" + lines.append(ansi_ljust(content, BOX_WIDTH) + "│") if colors.get("notes"): - for line in wrap_text(f"Notes: {colors.get('notes', '')}", "| ", BOX_WIDTH): - lines.append(line.ljust(BOX_WIDTH) + "|") - lines.append("|" + " " * BOX_WIDTH + "|") + for line in wrap_text(f"Notes: {colors.get('notes', '')}", "│ ", BOX_WIDTH): + lines.append(line.ljust(BOX_WIDTH) + "│") # Typography section - lines.append(f"| TYPOGRAPHY: {typography.get('heading', '')} / {typography.get('body', '')}".ljust(BOX_WIDTH) + "|") + lines.append(section_header("TYPOGRAPHY", BOX_WIDTH + 1)) + lines.append(f"│ {typography.get('heading', '')} / {typography.get('body', '')}".ljust(BOX_WIDTH) + "│") if typography.get("mood"): - for line in wrap_text(f"Mood: {typography.get('mood', '')}", "| ", BOX_WIDTH): - lines.append(line.ljust(BOX_WIDTH) + "|") + for line in wrap_text(f"Mood: {typography.get('mood', '')}", "│ ", BOX_WIDTH): + lines.append(line.ljust(BOX_WIDTH) + "│") if typography.get("best_for"): - for line in wrap_text(f"Best For: {typography.get('best_for', '')}", "| ", BOX_WIDTH): - lines.append(line.ljust(BOX_WIDTH) + "|") + for line in wrap_text(f"Best For: {typography.get('best_for', '')}", "│ ", BOX_WIDTH): + lines.append(line.ljust(BOX_WIDTH) + "│") if typography.get("google_fonts_url"): - lines.append(f"| Google Fonts: {typography.get('google_fonts_url', '')}".ljust(BOX_WIDTH) + "|") + lines.append(f"│ Google Fonts: {typography.get('google_fonts_url', '')}".ljust(BOX_WIDTH) + "│") if typography.get("css_import"): - lines.append(f"| CSS Import: {typography.get('css_import', '')[:70]}...".ljust(BOX_WIDTH) + "|") - lines.append("|" + " " * BOX_WIDTH + "|") + lines.append(f"│ CSS Import: {typography.get('css_import', '')[:70]}...".ljust(BOX_WIDTH) + "│") # Key Effects section if effects: - lines.append("| KEY EFFECTS:".ljust(BOX_WIDTH) + "|") - for line in wrap_text(effects, "| ", BOX_WIDTH): - lines.append(line.ljust(BOX_WIDTH) + "|") - lines.append("|" + " " * BOX_WIDTH + "|") + lines.append(section_header("KEY EFFECTS", BOX_WIDTH + 1)) + for line in wrap_text(effects, "│ ", BOX_WIDTH): + lines.append(line.ljust(BOX_WIDTH) + "│") # Anti-patterns section if anti_patterns: - lines.append("| AVOID (Anti-patterns):".ljust(BOX_WIDTH) + "|") - for line in wrap_text(anti_patterns, "| ", BOX_WIDTH): - lines.append(line.ljust(BOX_WIDTH) + "|") - lines.append("|" + " " * BOX_WIDTH + "|") + lines.append(section_header("AVOID", BOX_WIDTH + 1)) + for line in wrap_text(anti_patterns, "│ ", BOX_WIDTH): + lines.append(line.ljust(BOX_WIDTH) + "│") # Pre-Delivery Checklist section - lines.append("| PRE-DELIVERY CHECKLIST:".ljust(BOX_WIDTH) + "|") + lines.append(section_header("PRE-DELIVERY CHECKLIST", BOX_WIDTH + 1)) checklist_items = [ "[ ] No emojis as icons (use SVG: Heroicons/Lucide)", "[ ] cursor-pointer on all clickable elements", @@ -356,10 +412,9 @@ def wrap_text(text: str, prefix: str, width: int) -> list: "[ ] Responsive: 375px, 768px, 1024px, 1440px" ] for item in checklist_items: - lines.append(f"| {item}".ljust(BOX_WIDTH) + "|") - lines.append("|" + " " * BOX_WIDTH + "|") + lines.append(f"│ {item}".ljust(BOX_WIDTH) + "│") - lines.append("+" + "-" * w + "+") + lines.append("└" + "─" * w + "┘") return "\n".join(lines) @@ -393,6 +448,10 @@ def format_markdown(design_system: dict) -> str: # Style section lines.append("### Style") lines.append(f"- **Name:** {style.get('name', '')}") + light = style.get("light_mode", "") + dark = style.get("dark_mode", "") + if light or dark: + lines.append(f"- **Mode Support:** Light {light} | Dark {dark}") if style.get('keywords'): lines.append(f"- **Keywords:** {style.get('keywords', '')}") if style.get('best_for'): @@ -401,15 +460,26 @@ def format_markdown(design_system: dict) -> str: lines.append(f"- **Performance:** {style.get('performance', '')} | **Accessibility:** {style.get('accessibility', '')}") lines.append("") - # Colors section + # Colors section (extended palette) lines.append("### Colors") - lines.append(f"| Role | Hex |") - lines.append(f"|------|-----|") - lines.append(f"| Primary | {colors.get('primary', '')} |") - lines.append(f"| Secondary | {colors.get('secondary', '')} |") - lines.append(f"| CTA | {colors.get('cta', '')} |") - lines.append(f"| Background | {colors.get('background', '')} |") - lines.append(f"| Text | {colors.get('text', '')} |") + lines.append("| Role | Hex | CSS Variable |") + lines.append("|------|-----|--------------|") + md_color_entries = [ + ("Primary", "primary", "--color-primary"), + ("On Primary", "on_primary", "--color-on-primary"), + ("Secondary", "secondary", "--color-secondary"), + ("Accent/CTA", "accent", "--color-accent"), + ("Background", "background", "--color-background"), + ("Foreground", "foreground", "--color-foreground"), + ("Muted", "muted", "--color-muted"), + ("Border", "border", "--color-border"), + ("Destructive", "destructive", "--color-destructive"), + ("Ring", "ring", "--color-ring"), + ] + for label, key, css_var in md_color_entries: + hex_val = colors.get(key, "") + if hex_val: + lines.append(f"| {label} | `{hex_val}` | `{css_var}` |") if colors.get("notes"): lines.append(f"\n*Notes: {colors.get('notes', '')}*") lines.append("") @@ -578,11 +648,22 @@ def format_master_md(design_system: dict) -> str: lines.append("") lines.append("| Role | Hex | CSS Variable |") lines.append("|------|-----|--------------|") - lines.append(f"| Primary | `{colors.get('primary', '#2563EB')}` | `--color-primary` |") - lines.append(f"| Secondary | `{colors.get('secondary', '#3B82F6')}` | `--color-secondary` |") - lines.append(f"| CTA/Accent | `{colors.get('cta', '#F97316')}` | `--color-cta` |") - lines.append(f"| Background | `{colors.get('background', '#F8FAFC')}` | `--color-background` |") - lines.append(f"| Text | `{colors.get('text', '#1E293B')}` | `--color-text` |") + master_color_entries = [ + ("Primary", "primary", "--color-primary"), + ("On Primary", "on_primary", "--color-on-primary"), + ("Secondary", "secondary", "--color-secondary"), + ("Accent/CTA", "accent", "--color-accent"), + ("Background", "background", "--color-background"), + ("Foreground", "foreground", "--color-foreground"), + ("Muted", "muted", "--color-muted"), + ("Border", "border", "--color-border"), + ("Destructive", "destructive", "--color-destructive"), + ("Ring", "ring", "--color-ring"), + ] + for label, key, css_var in master_color_entries: + hex_val = colors.get(key, "") + if hex_val: + lines.append(f"| {label} | `{hex_val}` | `{css_var}` |") lines.append("") if colors.get("notes"): lines.append(f"**Color Notes:** {colors.get('notes', '')}") From 83692f7b2a8d1d85c1a7f1f40dc3f8ad57717fe5 Mon Sep 17 00:00:00 2001 From: amyragan3297 Date: Tue, 17 Mar 2026 15:55:21 -0500 Subject: [PATCH 02/50] Create python-package-conda.yml --- .github/workflows/python-package-conda.yml | 34 ++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 .github/workflows/python-package-conda.yml diff --git a/.github/workflows/python-package-conda.yml b/.github/workflows/python-package-conda.yml new file mode 100644 index 000000000..f3586044a --- /dev/null +++ b/.github/workflows/python-package-conda.yml @@ -0,0 +1,34 @@ +name: Python Package using Conda + +on: [push] + +jobs: + build-linux: + runs-on: ubuntu-latest + strategy: + max-parallel: 5 + + steps: + - uses: actions/checkout@v4 + - name: Set up Python 3.10 + uses: actions/setup-python@v3 + with: + python-version: '3.10' + - name: Add conda to system path + run: | + # $CONDA is an environment variable pointing to the root of the miniconda directory + echo $CONDA/bin >> $GITHUB_PATH + - name: Install dependencies + run: | + conda env update --file environment.yml --name base + - name: Lint with flake8 + run: | + conda install flake8 + # stop the build if there are Python syntax errors or undefined names + flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide + flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + - name: Test with pytest + run: | + conda install pytest + pytest From fdc0a45c55019be57922fead570d676f466e7d76 Mon Sep 17 00:00:00 2001 From: icaruszxk Date: Sun, 21 Jun 2026 02:16:03 +0800 Subject: [PATCH 03/50] fix: correct project name from 'Antigravity Kit' to 'UI UX Pro Max' in CLAUDE.md (#365) Co-authored-by: Xavier Virrey --- CLAUDE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index 4c121a1ea..f7609b897 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,7 +4,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Project Overview -Antigravity Kit is an AI-powered design intelligence toolkit providing searchable databases of UI styles, color palettes, font pairings, chart types, and UX guidelines. It works as a skill/workflow for AI coding assistants (Claude Code, Windsurf, Cursor, etc.). +UI UX Pro Max is an AI-powered design intelligence toolkit providing searchable databases of UI styles, color palettes, font pairings, chart types, and UX guidelines. It works as a skill/workflow for AI coding assistants (Claude Code, Windsurf, Cursor, etc.). ## Search Command From 5e2c0a2b5ec81bf5733ddcee2d7db4c34dc71aa3 Mon Sep 17 00:00:00 2001 From: Spinulosa1111 Date: Sun, 21 Jun 2026 05:00:03 +1000 Subject: [PATCH 04/50] docs: add Troubleshooting section to README (closes #304 #318 #338) (#350) --- README.md | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/README.md b/README.md index e2b4129e7..71bb41ec6 100755 --- a/README.md +++ b/README.md @@ -504,6 +504,78 @@ gh pr create See [CLAUDE.md](CLAUDE.md) for detailed development guidelines. +## Troubleshooting + +### `uipro: unknown command 'uninstall'` or `unknown command 'update'` + +Your installed version of `uipro-cli` is outdated. Update it and retry: + +```bash +npm install -g uipro-cli@latest +uipro uninstall +``` + +### `uipro uninstall` says "No installed AI skill directories detected" + +The skill was installed in a different directory than where you're running the command. Either: + +```bash +# Option A — run from the project root where you originally installed it +cd /path/to/your/project +uipro uninstall + +# Option B — remove the global install +uipro uninstall --global + +# Option C — remove manually +rm -rf .claude/skills/ui-ux-pro-max # Claude Code +rm -rf .cursor/skills/ui-ux-pro-max # Cursor +rm -rf .windsurf/skills/ui-ux-pro-max # Windsurf +rm -rf .agents/skills/ui-ux-pro-max # Antigravity +``` + +### Claude Marketplace install fails with "Zip file contains a symbolic link" + +This is a known issue with versions prior to v2.5.1. The repository used symlinks internally which some installation tools can't handle. **Fix:** use the CLI installer instead: + +```bash +npm install -g uipro-cli +uipro init --ai claude +``` + +Or wait for the next release where this is resolved. + +### `npm install -g uipro-cli` fails with permission error + +```bash +# macOS/Linux — use a Node version manager (recommended) or sudo +sudo npm install -g uipro-cli + +# Or use npx without installing globally +npx uipro-cli init --ai claude +``` + +### Python not found when running design system commands + +The search scripts require Python 3.x. Install it for your OS: + +```bash +brew install python3 # macOS +sudo apt install python3 # Ubuntu/Debian +winget install Python.Python.3.12 # Windows +``` + +### Design system output is cut off / fields truncated + +Use the `--max-length` flag to increase (or remove) the truncation limit: + +```bash +python3 .claude/skills/ui-ux-pro-max/scripts/search.py "SaaS" --domain style --max-length 0 +# ^ 0 = unlimited +``` + +--- + ## Star History [![Star History Chart](https://api.star-history.com/svg?repos=nextlevelbuilder/ui-ux-pro-max-skill&type=Date)](https://star-history.com/#nextlevelbuilder/ui-ux-pro-max-skill&Date) From 03e6afc908ba341c0dc11fc15b1a88d68ed23d5b Mon Sep 17 00:00:00 2001 From: Roy Naquin <87366539+roynaquin@users.noreply.github.com> Date: Sun, 21 Jun 2026 15:14:55 +0900 Subject: [PATCH 05/50] ci: add paths-ignore to python-package-conda workflow (#312) Skip docs-only changes (*.md, docs/**, .claude/**) from triggering the Conda build/lint/test pipeline. Co-authored-by: Claude Sonnet 4.6 --- .github/workflows/python-package-conda.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/python-package-conda.yml b/.github/workflows/python-package-conda.yml index f3586044a..41c11cbba 100644 --- a/.github/workflows/python-package-conda.yml +++ b/.github/workflows/python-package-conda.yml @@ -1,6 +1,11 @@ name: Python Package using Conda -on: [push] +on: + push: + paths-ignore: + - '**/*.md' + - 'docs/**' + - '.claude/**' jobs: build-linux: From 71d02eccde7391a6d2332104968b76e7cdb97ed0 Mon Sep 17 00:00:00 2001 From: Alfredo Augusto Petri Date: Sun, 21 Jun 2026 04:28:44 -0300 Subject: [PATCH 06/50] fix(meta): align marketplace.json and package-lock.json to v2.5.0 (#327) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both files were stuck at v2.2.1 while plugin.json, skill.json and cli/package.json had moved to v2.5.0. Claude marketplace reads marketplace.json for version and palette count — the stale entry showed outdated data (96 palettes vs actual 161, 13 stacks vs 15). Co-authored-by: Claude Sonnet 4.6 --- .claude-plugin/marketplace.json | 6 +++--- cli/package-lock.json | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 2cc8a4e1d..332198b33 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -5,15 +5,15 @@ "name": "nextlevelbuilder" }, "metadata": { - "description": "UI/UX design intelligence skill with 67 styles, 96 palettes, 57 font pairings, 25 charts, and 13 stack guidelines", - "version": "2.2.1" + "description": "UI/UX design intelligence skill with 67 styles, 161 palettes, 57 font pairings, 25 charts, and 15 stack guidelines", + "version": "2.5.0" }, "plugins": [ { "name": "ui-ux-pro-max", "source": "./", "description": "Professional UI/UX design intelligence for AI coding assistants. Includes searchable databases of styles, colors, typography, charts, and UX guidelines for React, Next.js, Astro, Vue, Nuxt.js, Nuxt UI, Svelte, SwiftUI, React Native, Flutter, Tailwind, shadcn/ui, and Jetpack Compose.", - "version": "2.2.1", + "version": "2.5.0", "author": { "name": "nextlevelbuilder" }, diff --git a/cli/package-lock.json b/cli/package-lock.json index de4644b3e..87bb37f15 100644 --- a/cli/package-lock.json +++ b/cli/package-lock.json @@ -1,12 +1,12 @@ { "name": "uipro-cli", - "version": "2.2.1", + "version": "2.5.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "uipro-cli", - "version": "2.2.1", + "version": "2.5.0", "license": "MIT", "dependencies": { "chalk": "^5.3.0", From c522197c727ceb15dd855746c9403e651db11a40 Mon Sep 17 00:00:00 2001 From: Alfredo Augusto Petri Date: Sun, 21 Jun 2026 05:46:42 -0300 Subject: [PATCH 07/50] fix(cli): implement --force flag to protect existing skill files (#324) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The --force option was accepted by Commander but ignored: writeFile() always overwrote existing files silently. Users expecting protection against accidental overwrites had no way to preserve existing configs. - generatePlatformFiles: check file existence before writing; skip with a clear message when file exists and force=false - generateAllPlatformFiles / templateInstall: propagate force parameter - initCommand: pass options.force through to templateInstall Behavior change: uipro init --ai claude → skips if SKILL.md already exists uipro init --ai claude --force → overwrites regardless Co-authored-by: Claude Sonnet 4.6 --- cli/src/commands/init.ts | 9 +++++---- cli/src/utils/template.ts | 14 +++++++++++--- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/cli/src/commands/init.ts b/cli/src/commands/init.ts index e3bae33c3..3f9be0cd5 100755 --- a/cli/src/commands/init.ts +++ b/cli/src/commands/init.ts @@ -101,17 +101,18 @@ async function templateInstall( targetDir: string, aiType: AIType, spinner: ReturnType, - isGlobal = false + isGlobal = false, + force = false ): Promise { spinner.text = isGlobal ? 'Generating skill files globally...' : 'Generating skill files from templates...'; if (aiType === 'all') { - return generateAllPlatformFiles(targetDir, isGlobal); + return generateAllPlatformFiles(targetDir, isGlobal, force); } - return generatePlatformFiles(targetDir, aiType, isGlobal); + return generatePlatformFiles(targetDir, aiType, isGlobal, force); } export async function initCommand(options: InitOptions): Promise { @@ -178,7 +179,7 @@ export async function initCommand(options: InitOptions): Promise { } } else { // Use new template-based generation (default) - copiedFolders = await templateInstall(cwd, aiType, spinner, isGlobal); + copiedFolders = await templateInstall(cwd, aiType, spinner, isGlobal, options.force); installMethod = 'template'; } diff --git a/cli/src/utils/template.ts b/cli/src/utils/template.ts index 3223a6ead..d671a4d10 100755 --- a/cli/src/utils/template.ts +++ b/cli/src/utils/template.ts @@ -187,7 +187,8 @@ async function copyDataAndScripts(targetSkillDir: string): Promise { export async function generatePlatformFiles( targetDir: string, aiType: string, - isGlobal = false + isGlobal = false, + force = false ): Promise { const config = await loadPlatformConfig(aiType); const createdFolders: string[] = []; @@ -208,6 +209,13 @@ export async function generatePlatformFiles( // Render and write skill file (pass isGlobal to adjust paths) const skillContent = await renderSkillFile(config, isGlobal); const skillFilePath = join(skillDir, config.folderStructure.filename); + + const fileAlreadyExists = await exists(skillFilePath); + if (fileAlreadyExists && !force) { + console.log(` Skipped (already exists): ${skillFilePath} — use --force to overwrite`); + return []; + } + await writeFile(skillFilePath, skillContent, 'utf-8'); createdFolders.push(config.folderStructure.root); @@ -220,12 +228,12 @@ export async function generatePlatformFiles( /** * Generate files for all AI types */ -export async function generateAllPlatformFiles(targetDir: string, isGlobal = false): Promise { +export async function generateAllPlatformFiles(targetDir: string, isGlobal = false, force = false): Promise { const allFolders = new Set(); for (const aiType of Object.keys(AI_TO_PLATFORM)) { try { - const folders = await generatePlatformFiles(targetDir, aiType, isGlobal); + const folders = await generatePlatformFiles(targetDir, aiType, isGlobal, force); folders.forEach(f => allFolders.add(f)); } catch { // Skip if generation fails for a platform From f32d6a61cdf0bfd57404c45854583fd19ff95088 Mon Sep 17 00:00:00 2001 From: Wynn Date: Sun, 21 Jun 2026 04:58:45 -0400 Subject: [PATCH 08/50] Add openclaw to platforms list (#308) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OpenClaw (https://openclaw.ai) is an open-source agent gateway that runs Claude as its primary backend. This skill works out-of-the-box inside OpenClaw agents — same SKILL.md + python3 search.py invocation pattern as the other supported platforms. Adding it to the list so the install flow can target it. Co-authored-by: yinhaoti --- skill.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/skill.json b/skill.json index 4c6748bf4..9cdb76c76 100644 --- a/skill.json +++ b/skill.json @@ -35,7 +35,8 @@ "droid", "warp", "augment", - "antigravity" + "antigravity", + "openclaw" ], "install": "npx uipro-cli init --ai {{platform}}" } From 9dea1bc76f4eceb825abd0b399982bcbb473b920 Mon Sep 17 00:00:00 2001 From: xiaolai Date: Sun, 21 Jun 2026 20:05:21 +0800 Subject: [PATCH 09/50] fix: remove unsubstituted template variable from slides/SKILL.md (#287) Line 14 contained a raw `$ARGUMENTS` tag that was never replaced during skill generation. This literal XML-like string renders as part of the skill body and can confuse LLM consumers. Co-authored-by: claude[bot] Co-authored-by: Claude Code --- .claude/skills/slides/SKILL.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/.claude/skills/slides/SKILL.md b/.claude/skills/slides/SKILL.md index ef4500a08..619bb9095 100644 --- a/.claude/skills/slides/SKILL.md +++ b/.claude/skills/slides/SKILL.md @@ -11,8 +11,6 @@ metadata: Strategic HTML presentation design with data visualization. -$ARGUMENTS - ## When to Use - Marketing presentations and pitch decks From 7538cfb3604c83b0eb5ab570a6375ba9acd6507a Mon Sep 17 00:00:00 2001 From: Runxin Yan <2564788741@qq.com> Date: Sun, 21 Jun 2026 21:02:56 +0800 Subject: [PATCH 10/50] docs: add Windows Python compatibility note (#280) Add cross-platform Python command note to skills and docs: - CLAUDE.md: Add Windows note in Prerequisites - ui-ux-pro-max/SKILL.md: Add Windows note in Prerequisites - design/SKILL.md: Add Prerequisites section with Windows note - banner-design/SKILL.md: Add Prerequisites section with Windows note - templates/base/skill-content.md: Add Windows note (source template) Windows uses 'python' instead of 'python3' to run scripts. Co-authored-by: Claude Opus 4.7 --- .claude/skills/banner-design/SKILL.md | 4 ++++ .claude/skills/design/SKILL.md | 11 +++++++++++ .claude/skills/ui-ux-pro-max/SKILL.md | 2 ++ CLAUDE.md | 2 ++ src/ui-ux-pro-max/templates/base/skill-content.md | 2 ++ 5 files changed, 21 insertions(+) diff --git a/.claude/skills/banner-design/SKILL.md b/.claude/skills/banner-design/SKILL.md index 18fdac634..002c2daed 100644 --- a/.claude/skills/banner-design/SKILL.md +++ b/.claude/skills/banner-design/SKILL.md @@ -21,6 +21,10 @@ Design banners across social, ads, web, and print formats. Generates multiple ar - Event/print banner design - Creative asset generation for campaigns +## Prerequisites + +**Python:** This skill uses Python scripts. On Windows, use `python` instead of `python3` (e.g., `python scripts/search.py` instead of `python3 scripts/search.py`). + ## Workflow ### Step 1: Gather Requirements (AskUserQuestion) diff --git a/.claude/skills/design/SKILL.md b/.claude/skills/design/SKILL.md index 1c4a37fb2..e3ce436b7 100644 --- a/.claude/skills/design/SKILL.md +++ b/.claude/skills/design/SKILL.md @@ -289,6 +289,15 @@ Load `references/social-photos-design.md` for sizes, templates, best practices. | `scripts/cip/core.py` | BM25 search engine for CIP data | | `scripts/icon/generate.py` | Generate SVG icons with Gemini 3.1 Pro | +## Prerequisites + +**Python:** This skill uses Python scripts. On Windows, use `python` instead of `python3` (e.g., `python scripts/logo/search.py` instead of `python3 scripts/logo/search.py`). + +Check if Python is installed: +```bash +python3 --version || python --version +``` + ## Setup ```bash @@ -296,6 +305,8 @@ export GEMINI_API_KEY="your-key" # https://aistudio.google.com/apikey pip install google-genai pillow ``` +> **Note for Windows:** Use `python` instead of `pip` where needed (e.g., `python -m pip install ...`). + ## Integration **External sub-skills:** brand, design-system, ui-styling diff --git a/.claude/skills/ui-ux-pro-max/SKILL.md b/.claude/skills/ui-ux-pro-max/SKILL.md index a64d6c233..75d2e1b22 100644 --- a/.claude/skills/ui-ux-pro-max/SKILL.md +++ b/.claude/skills/ui-ux-pro-max/SKILL.md @@ -330,6 +330,8 @@ sudo apt update && sudo apt install python3 winget install Python.Python.3.12 ``` +> **Note:** On Windows, use `python` instead of `python3` to run scripts (e.g., `python scripts/search.py` instead of `python3 scripts/search.py`). + --- ## How to Use This Skill diff --git a/CLAUDE.md b/CLAUDE.md index f7609b897..ab6379c92 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -88,6 +88,8 @@ When modifying files: Python 3.x (no external dependencies required) +**Note:** On Windows, use `python` instead of `python3` to run the scripts. + ## Git Workflow Never push directly to `main`. Always: diff --git a/src/ui-ux-pro-max/templates/base/skill-content.md b/src/ui-ux-pro-max/templates/base/skill-content.md index c86923534..2b82877c6 100644 --- a/src/ui-ux-pro-max/templates/base/skill-content.md +++ b/src/ui-ux-pro-max/templates/base/skill-content.md @@ -27,6 +27,8 @@ sudo apt update && sudo apt install python3 winget install Python.Python.3.12 ``` +> **Note:** On Windows, use `python` instead of `python3` to run scripts (e.g., `python scripts/search.py` instead of `python3 scripts/search.py`). + --- ## How to Use This Skill From 10d6ca310541d3ffeee6dceda0a29e373796f321 Mon Sep 17 00:00:00 2001 From: Antony Omeri Date: Sun, 21 Jun 2026 18:40:01 +0300 Subject: [PATCH 11/50] Fix 3 latent bugs in ui-ux-pro-max (css2 font URLs, 2-char search, persist path) (#321) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All three are in the canonical src/ tree, reproduced on Python 3.14.5: 1. data/typography.csv — all 73 'Google Fonts URL' values were unusable fonts.google.com/share *UI* links, not stylesheet hrefs. Replaced with the proper fonts.googleapis.com/css2 URLs (extracted verbatim from each row's correct 'CSS Import' column), so the URL column is actually loadable. 2. scripts/core.py — BM25 tokenizer kept only words >2 chars, so common design terms 'ux', 'ui', 'ai', '3d' tokenized to nothing and returned 0 results (e.g. `--domain style "3d"`). Changed >2 to >=2; '3d'/'ai' now match. 3. scripts/search.py — `--persist` without `-p` printed 'design-system/default/' but actually wrote to the query slug (e.g. design-system/fintech-crypto/). Use the same default the writer uses so the printed path matches reality. Co-authored-by: Claude Opus 4.8 (1M context) --- src/ui-ux-pro-max/data/typography.csv | 146 +++++++++++++------------- src/ui-ux-pro-max/scripts/core.py | 2 +- src/ui-ux-pro-max/scripts/search.py | 2 +- 3 files changed, 75 insertions(+), 75 deletions(-) diff --git a/src/ui-ux-pro-max/data/typography.csv b/src/ui-ux-pro-max/data/typography.csv index 51a63f01a..7a1893794 100644 --- a/src/ui-ux-pro-max/data/typography.csv +++ b/src/ui-ux-pro-max/data/typography.csv @@ -1,74 +1,74 @@ No,Font Pairing Name,Category,Heading Font,Body Font,Mood/Style Keywords,Best For,Google Fonts URL,CSS Import,Tailwind Config,Notes -1,Classic Elegant,"Serif + Sans",Playfair Display,Inter,"elegant, luxury, sophisticated, timeless, premium, editorial","Luxury brands, fashion, spa, beauty, editorial, magazines, high-end e-commerce","https://fonts.google.com/share?selection.family=Inter:wght@300;400;500;600;700|Playfair+Display:wght@400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Playfair+Display:wght@400;500;600;700&display=swap');","fontFamily: { serif: ['Playfair Display', 'serif'], sans: ['Inter', 'sans-serif'] }","High contrast between elegant heading and clean body. Perfect for luxury/premium." -2,Modern Professional,"Sans + Sans",Poppins,Open Sans,"modern, professional, clean, corporate, friendly, approachable","SaaS, corporate sites, business apps, startups, professional services","https://fonts.google.com/share?selection.family=Open+Sans:wght@300;400;500;600;700|Poppins:wght@400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;500;600;700&family=Poppins:wght@400;500;600;700&display=swap');","fontFamily: { heading: ['Poppins', 'sans-serif'], body: ['Open Sans', 'sans-serif'] }","Geometric Poppins for headings, humanist Open Sans for readability." -3,Tech Startup,"Sans + Sans",Space Grotesk,DM Sans,"tech, startup, modern, innovative, bold, futuristic","Tech companies, startups, SaaS, developer tools, AI products","https://fonts.google.com/share?selection.family=DM+Sans:wght@400;500;700|Space+Grotesk:wght@400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;700&family=Space+Grotesk:wght@400;500;600;700&display=swap');","fontFamily: { heading: ['Space Grotesk', 'sans-serif'], body: ['DM Sans', 'sans-serif'] }","Space Grotesk has unique character, DM Sans is highly readable." -4,Editorial Classic,"Serif + Serif",Cormorant Garamond,Libre Baskerville,"editorial, classic, literary, traditional, refined, bookish","Publishing, blogs, news sites, literary magazines, book covers","https://fonts.google.com/share?selection.family=Cormorant+Garamond:wght@400;500;600;700|Libre+Baskerville:wght@400;700","@import url('https://fonts.googleapis.com/css2?family=Cormorant+Garamond:wght@400;500;600;700&family=Libre+Baskerville:wght@400;700&display=swap');","fontFamily: { heading: ['Cormorant Garamond', 'serif'], body: ['Libre Baskerville', 'serif'] }","All-serif pairing for traditional editorial feel." -5,Minimal Swiss,"Sans + Sans",Inter,Inter,"minimal, clean, swiss, functional, neutral, professional","Dashboards, admin panels, documentation, enterprise apps, design systems","https://fonts.google.com/share?selection.family=Inter:wght@300;400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');","fontFamily: { sans: ['Inter', 'sans-serif'] }","Single font family with weight variations. Ultimate simplicity." -6,Playful Creative,"Display + Sans",Fredoka,Nunito,"playful, friendly, fun, creative, warm, approachable","Children's apps, educational, gaming, creative tools, entertainment","https://fonts.google.com/share?selection.family=Fredoka:wght@400;500;600;700|Nunito:wght@300;400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Fredoka:wght@400;500;600;700&family=Nunito:wght@300;400;500;600;700&display=swap');","fontFamily: { heading: ['Fredoka', 'sans-serif'], body: ['Nunito', 'sans-serif'] }","Rounded, friendly fonts perfect for playful UIs." -7,Bold Statement,"Display + Sans",Bebas Neue,Source Sans 3,"bold, impactful, strong, dramatic, modern, headlines","Marketing sites, portfolios, agencies, event pages, sports","https://fonts.google.com/share?selection.family=Bebas+Neue|Source+Sans+3:wght@300;400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Source+Sans+3:wght@300;400;500;600;700&display=swap');","fontFamily: { display: ['Bebas Neue', 'sans-serif'], body: ['Source Sans 3', 'sans-serif'] }","Bebas Neue for large headlines only. All-caps display font." -8,Wellness Calm,"Serif + Sans",Lora,Raleway,"calm, wellness, health, relaxing, natural, organic","Health apps, wellness, spa, meditation, yoga, organic brands","https://fonts.google.com/share?selection.family=Lora:wght@400;500;600;700|Raleway:wght@300;400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Lora:wght@400;500;600;700&family=Raleway:wght@300;400;500;600;700&display=swap');","fontFamily: { serif: ['Lora', 'serif'], sans: ['Raleway', 'sans-serif'] }","Lora's organic curves with Raleway's elegant simplicity." -9,Developer Mono,"Mono + Sans",JetBrains Mono,IBM Plex Sans,"code, developer, technical, precise, functional, hacker","Developer tools, documentation, code editors, tech blogs, CLI apps","https://fonts.google.com/share?selection.family=IBM+Plex+Sans:wght@300;400;500;600;700|JetBrains+Mono:wght@400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap');","fontFamily: { mono: ['JetBrains Mono', 'monospace'], sans: ['IBM Plex Sans', 'sans-serif'] }","JetBrains for code, IBM Plex for UI. Developer-focused." -10,Retro Vintage,"Display + Serif",Abril Fatface,Merriweather,"retro, vintage, nostalgic, dramatic, decorative, bold","Vintage brands, breweries, restaurants, creative portfolios, posters","https://fonts.google.com/share?selection.family=Abril+Fatface|Merriweather:wght@300;400;700","@import url('https://fonts.googleapis.com/css2?family=Abril+Fatface&family=Merriweather:wght@300;400;700&display=swap');","fontFamily: { display: ['Abril Fatface', 'serif'], body: ['Merriweather', 'serif'] }","Abril Fatface for hero headlines only. High-impact vintage feel." -11,Geometric Modern,"Sans + Sans",Outfit,Work Sans,"geometric, modern, clean, balanced, contemporary, versatile","General purpose, portfolios, agencies, modern brands, landing pages","https://fonts.google.com/share?selection.family=Outfit:wght@300;400;500;600;700|Work+Sans:wght@300;400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&family=Work+Sans:wght@300;400;500;600;700&display=swap');","fontFamily: { heading: ['Outfit', 'sans-serif'], body: ['Work Sans', 'sans-serif'] }","Both geometric but Outfit more distinctive for headings." -12,Luxury Serif,"Serif + Sans",Cormorant,Montserrat,"luxury, high-end, fashion, elegant, refined, premium","Fashion brands, luxury e-commerce, jewelry, high-end services","https://fonts.google.com/share?selection.family=Cormorant:wght@400;500;600;700|Montserrat:wght@300;400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Cormorant:wght@400;500;600;700&family=Montserrat:wght@300;400;500;600;700&display=swap');","fontFamily: { serif: ['Cormorant', 'serif'], sans: ['Montserrat', 'sans-serif'] }","Cormorant's elegance with Montserrat's geometric precision." -13,Friendly SaaS,"Sans + Sans",Plus Jakarta Sans,Plus Jakarta Sans,"friendly, modern, saas, clean, approachable, professional","SaaS products, web apps, dashboards, B2B, productivity tools","https://fonts.google.com/share?selection.family=Plus+Jakarta+Sans:wght@300;400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700&display=swap');","fontFamily: { sans: ['Plus Jakarta Sans', 'sans-serif'] }","Single versatile font. Modern alternative to Inter." -14,News Editorial,"Serif + Sans",Newsreader,Roboto,"news, editorial, journalism, trustworthy, readable, informative","News sites, blogs, magazines, journalism, content-heavy sites","https://fonts.google.com/share?selection.family=Newsreader:wght@400;500;600;700|Roboto:wght@300;400;500;700","@import url('https://fonts.googleapis.com/css2?family=Newsreader:wght@400;500;600;700&family=Roboto:wght@300;400;500;700&display=swap');","fontFamily: { serif: ['Newsreader', 'serif'], sans: ['Roboto', 'sans-serif'] }","Newsreader designed for long-form reading. Roboto for UI." -15,Handwritten Charm,"Script + Sans",Caveat,Quicksand,"handwritten, personal, friendly, casual, warm, charming","Personal blogs, invitations, creative portfolios, lifestyle brands","https://fonts.google.com/share?selection.family=Caveat:wght@400;500;600;700|Quicksand:wght@300;400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Caveat:wght@400;500;600;700&family=Quicksand:wght@300;400;500;600;700&display=swap');","fontFamily: { script: ['Caveat', 'cursive'], sans: ['Quicksand', 'sans-serif'] }","Use Caveat sparingly for accents. Quicksand for body." -16,Corporate Trust,"Sans + Sans",Lexend,Source Sans 3,"corporate, trustworthy, accessible, readable, professional, clean","Enterprise, government, healthcare, finance, accessibility-focused","https://fonts.google.com/share?selection.family=Lexend:wght@300;400;500;600;700|Source+Sans+3:wght@300;400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Lexend:wght@300;400;500;600;700&family=Source+Sans+3:wght@300;400;500;600;700&display=swap');","fontFamily: { heading: ['Lexend', 'sans-serif'], body: ['Source Sans 3', 'sans-serif'] }","Lexend designed for readability. Excellent accessibility." -17,Brutalist Raw,"Mono + Mono",Space Mono,Space Mono,"brutalist, raw, technical, monospace, minimal, stark","Brutalist designs, developer portfolios, experimental, tech art","https://fonts.google.com/share?selection.family=Space+Mono:wght@400;700","@import url('https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&display=swap');","fontFamily: { mono: ['Space Mono', 'monospace'] }","All-mono for raw brutalist aesthetic. Limited weights." -18,Fashion Forward,"Sans + Sans",Syne,Manrope,"fashion, avant-garde, creative, bold, artistic, edgy","Fashion brands, creative agencies, art galleries, design studios","https://fonts.google.com/share?selection.family=Manrope:wght@300;400;500;600;700|Syne:wght@400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Manrope:wght@300;400;500;600;700&family=Syne:wght@400;500;600;700&display=swap');","fontFamily: { heading: ['Syne', 'sans-serif'], body: ['Manrope', 'sans-serif'] }","Syne's unique character for headlines. Manrope for readability." -19,Soft Rounded,"Sans + Sans",Varela Round,Nunito Sans,"soft, rounded, friendly, approachable, warm, gentle","Children's products, pet apps, friendly brands, wellness, soft UI","https://fonts.google.com/share?selection.family=Nunito+Sans:wght@300;400;500;600;700|Varela+Round","@import url('https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@300;400;500;600;700&family=Varela+Round&display=swap');","fontFamily: { heading: ['Varela Round', 'sans-serif'], body: ['Nunito Sans', 'sans-serif'] }","Both rounded and friendly. Perfect for soft UI designs." -20,Premium Sans,"Sans + Sans",Satoshi,General Sans,"premium, modern, clean, sophisticated, versatile, balanced","Premium brands, modern agencies, SaaS, portfolios, startups","https://fonts.google.com/share?selection.family=DM+Sans:wght@400;500;700","@import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;700&display=swap');","fontFamily: { sans: ['DM Sans', 'sans-serif'] }","Note: Satoshi/General Sans on Fontshare. DM Sans as Google alternative." -21,Vietnamese Friendly,"Sans + Sans",Be Vietnam Pro,Noto Sans,"vietnamese, international, readable, clean, multilingual, accessible","Vietnamese sites, multilingual apps, international products","https://fonts.google.com/share?selection.family=Be+Vietnam+Pro:wght@300;400;500;600;700|Noto+Sans:wght@300;400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Be+Vietnam+Pro:wght@300;400;500;600;700&family=Noto+Sans:wght@300;400;500;600;700&display=swap');","fontFamily: { sans: ['Be Vietnam Pro', 'Noto Sans', 'sans-serif'] }","Be Vietnam Pro excellent Vietnamese support. Noto as fallback." -22,Japanese Elegant,"Serif + Sans",Noto Serif JP,Noto Sans JP,"japanese, elegant, traditional, modern, multilingual, readable","Japanese sites, Japanese restaurants, cultural sites, anime/manga","https://fonts.google.com/share?selection.family=Noto+Sans+JP:wght@300;400;500;700|Noto+Serif+JP:wght@400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@300;400;500;700&family=Noto+Serif+JP:wght@400;500;600;700&display=swap');","fontFamily: { serif: ['Noto Serif JP', 'serif'], sans: ['Noto Sans JP', 'sans-serif'] }","Noto fonts excellent Japanese support. Traditional + modern feel." -23,Korean Modern,"Sans + Sans",Noto Sans KR,Noto Sans KR,"korean, modern, clean, professional, multilingual, readable","Korean sites, K-beauty, K-pop, Korean businesses, multilingual","https://fonts.google.com/share?selection.family=Noto+Sans+KR:wght@300;400;500;700","@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700&display=swap');","fontFamily: { sans: ['Noto Sans KR', 'sans-serif'] }","Clean Korean typography. Single font with weight variations." -24,Chinese Traditional,"Serif + Sans",Noto Serif TC,Noto Sans TC,"chinese, traditional, elegant, cultural, multilingual, readable","Traditional Chinese sites, cultural content, Taiwan/Hong Kong markets","https://fonts.google.com/share?selection.family=Noto+Sans+TC:wght@300;400;500;700|Noto+Serif+TC:wght@400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@300;400;500;700&family=Noto+Serif+TC:wght@400;500;600;700&display=swap');","fontFamily: { serif: ['Noto Serif TC', 'serif'], sans: ['Noto Sans TC', 'sans-serif'] }","Traditional Chinese character support. Elegant pairing." -25,Chinese Simplified,"Sans + Sans",Noto Sans SC,Noto Sans SC,"chinese, simplified, modern, professional, multilingual, readable","Simplified Chinese sites, mainland China market, business apps","https://fonts.google.com/share?selection.family=Noto+Sans+SC:wght@300;400;500;700","@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300;400;500;700&display=swap');","fontFamily: { sans: ['Noto Sans SC', 'sans-serif'] }","Simplified Chinese support. Clean modern look." -26,Arabic Elegant,"Serif + Sans",Noto Naskh Arabic,Noto Sans Arabic,"arabic, elegant, traditional, cultural, RTL, readable","Arabic sites, Middle East market, Islamic content, bilingual sites","https://fonts.google.com/share?selection.family=Noto+Naskh+Arabic:wght@400;500;600;700|Noto+Sans+Arabic:wght@300;400;500;700","@import url('https://fonts.googleapis.com/css2?family=Noto+Naskh+Arabic:wght@400;500;600;700&family=Noto+Sans+Arabic:wght@300;400;500;700&display=swap');","fontFamily: { serif: ['Noto Naskh Arabic', 'serif'], sans: ['Noto Sans Arabic', 'sans-serif'] }","RTL support. Naskh for traditional, Sans for modern Arabic." -27,Thai Modern,"Sans + Sans",Noto Sans Thai,Noto Sans Thai,"thai, modern, readable, clean, multilingual, accessible","Thai sites, Southeast Asia, tourism, Thai restaurants","https://fonts.google.com/share?selection.family=Noto+Sans+Thai:wght@300;400;500;700","@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+Thai:wght@300;400;500;700&display=swap');","fontFamily: { sans: ['Noto Sans Thai', 'sans-serif'] }","Clean Thai typography. Excellent readability." -28,Hebrew Modern,"Sans + Sans",Noto Sans Hebrew,Noto Sans Hebrew,"hebrew, modern, RTL, clean, professional, readable","Hebrew sites, Israeli market, Jewish content, bilingual sites","https://fonts.google.com/share?selection.family=Noto+Sans+Hebrew:wght@300;400;500;700","@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+Hebrew:wght@300;400;500;700&display=swap');","fontFamily: { sans: ['Noto Sans Hebrew', 'sans-serif'] }","RTL support. Clean modern Hebrew typography." -29,Legal Professional,"Serif + Sans",EB Garamond,Lato,"legal, professional, traditional, trustworthy, formal, authoritative","Law firms, legal services, contracts, formal documents, government","https://fonts.google.com/share?selection.family=EB+Garamond:wght@400;500;600;700|Lato:wght@300;400;700","@import url('https://fonts.googleapis.com/css2?family=EB+Garamond:wght@400;500;600;700&family=Lato:wght@300;400;700&display=swap');","fontFamily: { serif: ['EB Garamond', 'serif'], sans: ['Lato', 'sans-serif'] }","EB Garamond for authority. Lato for clean body text." -30,Medical Clean,"Sans + Sans",Figtree,Noto Sans,"medical, clean, accessible, professional, healthcare, trustworthy","Healthcare, medical clinics, pharma, health apps, accessibility","https://fonts.google.com/share?selection.family=Figtree:wght@300;400;500;600;700|Noto+Sans:wght@300;400;500;700","@import url('https://fonts.googleapis.com/css2?family=Figtree:wght@300;400;500;600;700&family=Noto+Sans:wght@300;400;500;700&display=swap');","fontFamily: { heading: ['Figtree', 'sans-serif'], body: ['Noto Sans', 'sans-serif'] }","Clean, accessible fonts for medical contexts." -31,Financial Trust,"Sans + Sans",IBM Plex Sans,IBM Plex Sans,"financial, trustworthy, professional, corporate, banking, serious","Banks, finance, insurance, investment, fintech, enterprise","https://fonts.google.com/share?selection.family=IBM+Plex+Sans:wght@300;400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@300;400;500;600;700&display=swap');","fontFamily: { sans: ['IBM Plex Sans', 'sans-serif'] }","IBM Plex conveys trust and professionalism. Excellent for data." -32,Real Estate Luxury,"Serif + Sans",Cinzel,Josefin Sans,"real estate, luxury, elegant, sophisticated, property, premium","Real estate, luxury properties, architecture, interior design","https://fonts.google.com/share?selection.family=Cinzel:wght@400;500;600;700|Josefin+Sans:wght@300;400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Cinzel:wght@400;500;600;700&family=Josefin+Sans:wght@300;400;500;600;700&display=swap');","fontFamily: { serif: ['Cinzel', 'serif'], sans: ['Josefin Sans', 'sans-serif'] }","Cinzel's elegance for headlines. Josefin for modern body." -33,Restaurant Menu,"Serif + Sans",Playfair Display SC,Karla,"restaurant, menu, culinary, elegant, foodie, hospitality","Restaurants, cafes, food blogs, culinary, hospitality","https://fonts.google.com/share?selection.family=Karla:wght@300;400;500;600;700|Playfair+Display+SC:wght@400;700","@import url('https://fonts.googleapis.com/css2?family=Karla:wght@300;400;500;600;700&family=Playfair+Display+SC:wght@400;700&display=swap');","fontFamily: { display: ['Playfair Display SC', 'serif'], sans: ['Karla', 'sans-serif'] }","Small caps Playfair for menu headers. Karla for descriptions." -34,Art Deco,"Display + Sans",Poiret One,Didact Gothic,"art deco, vintage, 1920s, elegant, decorative, gatsby","Vintage events, art deco themes, luxury hotels, classic cocktails","https://fonts.google.com/share?selection.family=Didact+Gothic|Poiret+One","@import url('https://fonts.googleapis.com/css2?family=Didact+Gothic&family=Poiret+One&display=swap');","fontFamily: { display: ['Poiret One', 'sans-serif'], sans: ['Didact Gothic', 'sans-serif'] }","Poiret One for art deco headlines only. Didact for body." -35,Magazine Style,"Serif + Sans",Libre Bodoni,Public Sans,"magazine, editorial, publishing, refined, journalism, print","Magazines, online publications, editorial content, journalism","https://fonts.google.com/share?selection.family=Libre+Bodoni:wght@400;500;600;700|Public+Sans:wght@300;400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Libre+Bodoni:wght@400;500;600;700&family=Public+Sans:wght@300;400;500;600;700&display=swap');","fontFamily: { serif: ['Libre Bodoni', 'serif'], sans: ['Public Sans', 'sans-serif'] }","Bodoni's editorial elegance. Public Sans for clean UI." -36,Crypto/Web3,"Sans + Sans",Orbitron,Exo 2,"crypto, web3, futuristic, tech, blockchain, digital","Crypto platforms, NFT, blockchain, web3, futuristic tech","https://fonts.google.com/share?selection.family=Exo+2:wght@300;400;500;600;700|Orbitron:wght@400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Exo+2:wght@300;400;500;600;700&family=Orbitron:wght@400;500;600;700&display=swap');","fontFamily: { display: ['Orbitron', 'sans-serif'], body: ['Exo 2', 'sans-serif'] }","Orbitron for futuristic headers. Exo 2 for readable body." -37,Gaming Bold,"Display + Sans",Russo One,Chakra Petch,"gaming, bold, action, esports, competitive, energetic","Gaming, esports, action games, competitive sports, entertainment","https://fonts.google.com/share?selection.family=Chakra+Petch:wght@300;400;500;600;700|Russo+One","@import url('https://fonts.googleapis.com/css2?family=Chakra+Petch:wght@300;400;500;600;700&family=Russo+One&display=swap');","fontFamily: { display: ['Russo One', 'sans-serif'], body: ['Chakra Petch', 'sans-serif'] }","Russo One for impact. Chakra Petch for techy body text." -38,Indie/Craft,"Display + Sans",Amatic SC,Cabin,"indie, craft, handmade, artisan, organic, creative","Craft brands, indie products, artisan, handmade, organic products","https://fonts.google.com/share?selection.family=Amatic+SC:wght@400;700|Cabin:wght@400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Amatic+SC:wght@400;700&family=Cabin:wght@400;500;600;700&display=swap');","fontFamily: { display: ['Amatic SC', 'sans-serif'], sans: ['Cabin', 'sans-serif'] }","Amatic for handwritten feel. Cabin for readable body." -39,Startup Bold,"Sans + Sans",Clash Display,Satoshi,"startup, bold, modern, innovative, confident, dynamic","Startups, pitch decks, product launches, bold brands","https://fonts.google.com/share?selection.family=Outfit:wght@400;500;600;700|Rubik:wght@300;400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700&family=Rubik:wght@300;400;500;600;700&display=swap');","fontFamily: { heading: ['Outfit', 'sans-serif'], body: ['Rubik', 'sans-serif'] }","Note: Clash Display on Fontshare. Outfit as Google alternative." -40,E-commerce Clean,"Sans + Sans",Rubik,Nunito Sans,"ecommerce, clean, shopping, product, retail, conversion","E-commerce, online stores, product pages, retail, shopping","https://fonts.google.com/share?selection.family=Nunito+Sans:wght@300;400;500;600;700|Rubik:wght@300;400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@300;400;500;600;700&family=Rubik:wght@300;400;500;600;700&display=swap');","fontFamily: { heading: ['Rubik', 'sans-serif'], body: ['Nunito Sans', 'sans-serif'] }","Clean readable fonts perfect for product descriptions." -41,Academic/Research,"Serif + Sans",Crimson Pro,Atkinson Hyperlegible,"academic, research, scholarly, accessible, readable, educational","Universities, research papers, academic journals, educational","https://fonts.google.com/share?selection.family=Atkinson+Hyperlegible:wght@400;700|Crimson+Pro:wght@400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible:wght@400;700&family=Crimson+Pro:wght@400;500;600;700&display=swap');","fontFamily: { serif: ['Crimson Pro', 'serif'], sans: ['Atkinson Hyperlegible', 'sans-serif'] }","Crimson for scholarly headlines. Atkinson for accessibility." -42,Dashboard Data,"Mono + Sans",Fira Code,Fira Sans,"dashboard, data, analytics, code, technical, precise","Dashboards, analytics, data visualization, admin panels","https://fonts.google.com/share?selection.family=Fira+Code:wght@400;500;600;700|Fira+Sans:wght@300;400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&family=Fira+Sans:wght@300;400;500;600;700&display=swap');","fontFamily: { mono: ['Fira Code', 'monospace'], sans: ['Fira Sans', 'sans-serif'] }","Fira family cohesion. Code for data, Sans for labels." -43,Music/Entertainment,"Display + Sans",Righteous,Poppins,"music, entertainment, fun, energetic, bold, performance","Music platforms, entertainment, events, festivals, performers","https://fonts.google.com/share?selection.family=Poppins:wght@300;400;500;600;700|Righteous","@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&family=Righteous&display=swap');","fontFamily: { display: ['Righteous', 'sans-serif'], sans: ['Poppins', 'sans-serif'] }","Righteous for bold entertainment headers. Poppins for body." -44,Minimalist Portfolio,"Sans + Sans",Archivo,Space Grotesk,"minimal, portfolio, designer, creative, clean, artistic","Design portfolios, creative professionals, minimalist brands","https://fonts.google.com/share?selection.family=Archivo:wght@300;400;500;600;700|Space+Grotesk:wght@300;400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Archivo:wght@300;400;500;600;700&family=Space+Grotesk:wght@300;400;500;600;700&display=swap');","fontFamily: { heading: ['Space Grotesk', 'sans-serif'], body: ['Archivo', 'sans-serif'] }","Space Grotesk for distinctive headers. Archivo for clean body." -45,Kids/Education,"Display + Sans",Baloo 2,Comic Neue,"kids, education, playful, friendly, colorful, learning","Children's apps, educational games, kid-friendly content","https://fonts.google.com/share?selection.family=Baloo+2:wght@400;500;600;700|Comic+Neue:wght@300;400;700","@import url('https://fonts.googleapis.com/css2?family=Baloo+2:wght@400;500;600;700&family=Comic+Neue:wght@300;400;700&display=swap');","fontFamily: { display: ['Baloo 2', 'sans-serif'], sans: ['Comic Neue', 'sans-serif'] }","Fun, playful fonts for children. Comic Neue is readable comic style." -46,Wedding/Romance,"Script + Serif",Great Vibes,Cormorant Infant,"wedding, romance, elegant, script, invitation, feminine","Wedding sites, invitations, romantic brands, bridal","https://fonts.google.com/share?selection.family=Cormorant+Infant:wght@300;400;500;600;700|Great+Vibes","@import url('https://fonts.googleapis.com/css2?family=Cormorant+Infant:wght@300;400;500;600;700&family=Great+Vibes&display=swap');","fontFamily: { script: ['Great Vibes', 'cursive'], serif: ['Cormorant Infant', 'serif'] }","Great Vibes for elegant accents. Cormorant for readable text." -47,Science/Tech,"Sans + Sans",Exo,Roboto Mono,"science, technology, research, data, futuristic, precise","Science, research, tech documentation, data-heavy sites","https://fonts.google.com/share?selection.family=Exo:wght@300;400;500;600;700|Roboto+Mono:wght@300;400;500;700","@import url('https://fonts.googleapis.com/css2?family=Exo:wght@300;400;500;600;700&family=Roboto+Mono:wght@300;400;500;700&display=swap');","fontFamily: { sans: ['Exo', 'sans-serif'], mono: ['Roboto Mono', 'monospace'] }","Exo for modern tech feel. Roboto Mono for code/data." -48,Accessibility First,"Sans + Sans",Atkinson Hyperlegible,Atkinson Hyperlegible,"accessible, readable, inclusive, WCAG, dyslexia-friendly, clear","Accessibility-critical sites, government, healthcare, inclusive design","https://fonts.google.com/share?selection.family=Atkinson+Hyperlegible:wght@400;700","@import url('https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible:wght@400;700&display=swap');","fontFamily: { sans: ['Atkinson Hyperlegible', 'sans-serif'] }","Designed for maximum legibility. Excellent for accessibility." -49,Sports/Fitness,"Sans + Sans",Barlow Condensed,Barlow,"sports, fitness, athletic, energetic, condensed, action","Sports, fitness, gyms, athletic brands, competition","https://fonts.google.com/share?selection.family=Barlow+Condensed:wght@400;500;600;700|Barlow:wght@300;400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@400;500;600;700&family=Barlow:wght@300;400;500;600;700&display=swap');","fontFamily: { display: ['Barlow Condensed', 'sans-serif'], body: ['Barlow', 'sans-serif'] }","Condensed for impact headlines. Regular Barlow for body." -50,Luxury Minimalist,"Serif + Sans",Bodoni Moda,Jost,"luxury, minimalist, high-end, sophisticated, refined, premium","Luxury minimalist brands, high-end fashion, premium products","https://fonts.google.com/share?selection.family=Bodoni+Moda:wght@400;500;600;700|Jost:wght@300;400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Bodoni+Moda:wght@400;500;600;700&family=Jost:wght@300;400;500;600;700&display=swap');","fontFamily: { serif: ['Bodoni Moda', 'serif'], sans: ['Jost', 'sans-serif'] }","Bodoni's high contrast elegance. Jost for geometric body." -51,Tech/HUD Mono,"Mono + Mono",Share Tech Mono,Fira Code,"tech, futuristic, hud, sci-fi, data, monospaced, precise","Sci-fi interfaces, developer tools, cybersecurity, dashboards","https://fonts.google.com/share?selection.family=Fira+Code:wght@300;400;500;600;700|Share+Tech+Mono","@import url('https://fonts.googleapis.com/css2?family=Fira+Code:wght@300;400;500;600;700&family=Share+Tech+Mono&display=swap');","fontFamily: { hud: ['Share Tech Mono', 'monospace'], code: ['Fira Code', 'monospace'] }","Share Tech Mono has that classic sci-fi look." -52,Pixel Retro,"Display + Sans",Press Start 2P,VT323,"pixel, retro, gaming, 8-bit, nostalgic, arcade","Pixel art games, retro websites, creative portfolios","https://fonts.google.com/share?selection.family=Press+Start+2P|VT323","@import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&family=VT323&display=swap');","fontFamily: { pixel: ['Press Start 2P', 'cursive'], terminal: ['VT323', 'monospace'] }","Press Start 2P is very wide/large. VT323 is better for body text." -53,Neubrutalist Bold,"Display + Sans",Lexend Mega,Public Sans,"bold, neubrutalist, loud, strong, geometric, quirky","Neubrutalist designs, Gen Z brands, bold marketing","https://fonts.google.com/share?selection.family=Lexend+Mega:wght@100..900|Public+Sans:wght@100..900","@import url('https://fonts.googleapis.com/css2?family=Lexend+Mega:wght@100..900&family=Public+Sans:wght@100..900&display=swap');","fontFamily: { mega: ['Lexend Mega', 'sans-serif'], body: ['Public Sans', 'sans-serif'] }","Lexend Mega has distinct character and variable weight." -54,Academic/Archival,"Serif + Serif",EB Garamond,Crimson Text,"academic, old-school, university, research, serious, traditional","University sites, archives, research papers, history","https://fonts.google.com/share?selection.family=Crimson+Text:wght@400;600;700|EB+Garamond:wght@400;500;600;700;800","@import url('https://fonts.googleapis.com/css2?family=Crimson+Text:wght@400;600;700&family=EB+Garamond:wght@400;500;600;700;800&display=swap');","fontFamily: { classic: ['EB Garamond', 'serif'], text: ['Crimson Text', 'serif'] }","Classic academic aesthetic. Very legible." -55,Spatial Clear,"Sans + Sans",Inter,Inter,"spatial, legible, glass, system, clean, neutral","Spatial computing, AR/VR, glassmorphism interfaces","https://fonts.google.com/share?selection.family=Inter:wght@300;400;500;600","@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&display=swap');","fontFamily: { sans: ['Inter', 'sans-serif'] }","Optimized for readability on dynamic backgrounds." -56,Kinetic Motion,"Display + Mono",Syncopate,Space Mono,"kinetic, motion, futuristic, speed, wide, tech","Music festivals, automotive, high-energy brands","https://fonts.google.com/share?selection.family=Space+Mono:wght@400;700|Syncopate:wght@400;700","@import url('https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&family=Syncopate:wght@400;700&display=swap');","fontFamily: { display: ['Syncopate', 'sans-serif'], mono: ['Space Mono', 'monospace'] }","Syncopate's wide stance works well with motion effects." -57,Gen Z Brutal,"Display + Sans",Anton,Epilogue,"brutal, loud, shouty, meme, internet, bold","Gen Z marketing, streetwear, viral campaigns","https://fonts.google.com/share?selection.family=Anton|Epilogue:wght@400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Anton&family=Epilogue:wght@400;500;600;700&display=swap');","fontFamily: { display: ['Anton', 'sans-serif'], body: ['Epilogue', 'sans-serif'] }","Anton is impactful and condensed. Good for stickers/badges."57,Bauhaus Geometric,"Geometric Sans + Single Weight","Outfit","Outfit","bauhaus, geometric, constructivist, bold, uppercase, architectural, mechanical, poster, tactile","Bauhaus mobile apps, bold editorial mobile, design-forward branding apps, art/culture platforms","https://fonts.google.com/share?selection.family=Outfit:wght@400;500;700;900","@import url('https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;700;900&display=swap');","fontFamily: { display: ['Outfit', 'sans-serif'], body: ['Outfit', 'sans-serif'] }","Single-family system: Outfit 900 uppercase tracking-tighter for heroes; Outfit 700 uppercase for buttons/nav; Outfit 500 for body. Scale aggressively: text-4xl–text-5xl headlines on mobile." -58,Minimalist Monochrome Editorial,"Serif + Serif + Mono (Triple Stack)",Playfair Display,Source Serif 4,"monochrome, editorial, austere, typographic, pocket manifesto, luxury, high contrast, brutalist mobile","Luxury fashion mobile apps, editorial publications, digital exhibitions, portfolio apps, high-contrast e-reader aesthetics","https://fonts.google.com/share?selection.family=JetBrains+Mono:wght@400;500|Playfair+Display:ital,wght@0,400;0,700;0,900;1,400|Source+Serif+4:ital,wght@0,300;0,400;0,600;1,300","@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&family=Playfair+Display:ital,wght@0,400;0,700;0,900;1,400&family=Source+Serif+4:ital,wght@0,300;0,400;0,600;1,300&display=swap');","fontFamily: { display: ['Playfair Display', 'serif'], body: ['Source Serif 4', 'serif'], mono: ['JetBrains Mono', 'monospace'] }","Triple stack: Playfair Display 900 tracking-tighter leading-[0.9] for heroes (text-5xl–text-6xl breaks words graphically). Source Serif 4 300–600 for body legibility. JetBrains Mono 400–500 uppercase tracking-widest for tags/dates/labels. NO UI sans-serif — 100% serif/mono." -59,Modern Dark Cinema (Inter System),"Sans + Mono",Inter,Inter,"dark, cinematic, technical, precision, clean, premium, developer, professional, high-end utility","Developer tools, fintech/trading, AI dashboards, streaming platforms, high-end productivity apps","https://fonts.google.com/share?selection.family=Inter:wght@300;400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');","fontFamily: { sans: ['Inter', 'sans-serif'] }","Single-family precision system: Inter 700 (-1.5 tracking) for Display 48pt; Inter 600 (-0.5 tracking) for H1 32pt / H2 24pt; Inter 400 for body 16pt; Inter 500 uppercase +1.2 tracking for labels/mono. Gradient text via mask-view + react-native-linear-gradient (#FFFFFF → rgba(255,255,255,0.7)) on major headers." -60,SaaS Mobile Boutique (Calistoga + Inter),"Display Serif + Sans + Mono",Calistoga,Inter,"saas, boutique, electric, warm, editorial, bold, premium, fintech, business, dual font, human warmth","B2B SaaS mobile, fintech apps, analytics dashboards, marketing tools, operations platforms","https://fonts.google.com/share?selection.family=Calistoga:ital@0;1|Inter:wght@300;400;500;600;700|JetBrains+Mono:wght@400;500","@import url('https://fonts.googleapis.com/css2?family=Calistoga:ital@0;1&family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap');","fontFamily: { display: ['Calistoga', 'serif'], body: ['Inter', 'sans-serif'], mono: ['JetBrains Mono', 'monospace'] }","Tri-stack: Calistoga (adds human warmth) for heroes 36–42pt leading-1.1; Inter 400–600 for body/UI 16–18pt; JetBrains Mono 12pt uppercase tracking-[1.5] for data labels and section badges. Scale: Hero 36–42pt, Section H2 28–32pt, Body 16–18pt, Label 12pt. Avoid italic Calistoga except editorial callouts." -61,Terminal CLI Monospace,"Mono + Mono (Single Family)",JetBrains Mono,JetBrains Mono,"terminal, cli, hacker, monospace, matrix, developer, retro-future, command line, precision, OLED","Developer tools, Web3/blockchain apps, hacker aesthetic, sci-fi games, ARG, security tools, geek-culture portfolios","https://fonts.google.com/share?selection.family=JetBrains+Mono:ital,wght@0,400;0,500;1,400","@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,400;0,500;1,400&display=swap');","fontFamily: { mono: ['JetBrains Mono', 'monospace'] }","Single monospace system: use ONLY JetBrains Mono (or SpaceMono-Regular as system fallback). Strict sizes: 12pt / 14pt / 16pt only — no in-between. Weight: 400 normal (bold ruins mono character). Line height: 1.2x font size for information density. Letter spacing: normal (monospaced auto-spacing). All UI labels uppercase. ASCII borders and text-based progress bars." -62,Kinetic Brutalism (Space Grotesk),"Geometric Sans (Single Dominant)",Space Grotesk,Space Grotesk,"kinetic, brutalist, aggressive, uppercase, oversized, display, motion, street, bold, high-energy, zine","Music/culture apps, sports platforms, brand flagship mobile, performance dashboards, underground product drops","https://fonts.google.com/share?selection.family=Space+Grotesk:wght@400;500;600;700","@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&display=swap');","fontFamily: { display: ['Space Grotesk', 'sans-serif'], body: ['Space Grotesk', 'sans-serif'] }","Dominant single-family system: Space Grotesk 700–900 for ALL display. Scale: Hero 60–120pt (windowWidth/375*size), Section 40–50pt, Card titles 28–32pt, Body 18–20pt, Labels 12pt. ALL display/buttons/nav: UPPERCASE, letterSpacing -1 (large) / +2 (labels), lineHeight 0.9–1.1x. Use Inter as fallback. Font scale must use PixelRatio helper for responsive sizing." -63,Flat Design Mobile (System Bold),"Sans + Sans",Inter,Inter,"flat, clean, system, bold, geometric, cross-platform, icon, poster, minimal, functional, responsive","Cross-platform apps, dashboards, system UI, onboarding, marketing pages, informational apps, icon-heavy interfaces","https://fonts.google.com/share?selection.family=Inter:wght@400;600;700;800","@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;800&display=swap');","fontFamily: { sans: ['Inter', 'sans-serif'] }","System-first strategy: Inter as primary, falls back to system SF/Roboto on iOS/Android. Scale: Headlines fontWeight 800 letterSpacing -0.5; Subheadings fontWeight 600 fontSize 18; Body fontWeight 400 lineHeight 24; Labels fontWeight 700 uppercase letterSpacing 1. Thick weights carry all hierarchy since there are no shadows. Use aggressive size contrast (poster rule: body 16pt vs headline 40pt+). Avoid italic." -64,Material You MD3 (Roboto System),"Sans (System Default)",Roboto,Roboto,"material design 3, md3, android, google, tonal, friendly, rounded, accessible, adaptive","Android apps, cross-platform tools, productivity software, data-heavy B2B dashboards, enterprise mobile","https://fonts.google.com/share?selection.family=Roboto:ital,wght@0,300;0,400;0,500;0,700;1,400","@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,300;0,400;0,500;0,700;1,400&display=swap');","fontFamily: { sans: ['Roboto', 'sans-serif'] }","MD3 type scale: Display Large 56px/400/64px. Headline Large 32px/500/40px. Title Large 22px/500/28px. Body Large 16px/400/24px. Label Medium 12px/500/16px. Buttons and Labels: letterSpacing 0.1px. Use system Roboto on Android; load from Google Fonts for iOS parity. Never use custom weights beyond 300–700." -65,Neo Brutalism Mobile (Space Grotesk Heavy),"Geometric Sans (Bold-Only)",Space Grotesk,Space Grotesk,"neo brutalism, pop art, loud, bold, heavy, stickers, mechanical, high contrast, cream, gen-z","Creative tools, Gen-Z marketing, e-commerce for youth culture, content portfolios, collage-style apps","https://fonts.google.com/share?selection.family=Space+Grotesk:wght@700","@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@700&display=swap');","fontFamily: { display: ['Space Grotesk', 'sans-serif'], body: ['Space Grotesk', 'sans-serif'] }","Strictly 700 (Bold) and 900 (Black/Heavy) ONLY — never Regular or Light. Display: 48–64px. Heading: 24–32px. Body: 18–20px (stays heavy for brutalist density). Labels: 14px ALL CAPS letterSpacing 2. All buttons and navigation: uppercase. System bold as fallback. No italic, no thin weights." -66,Bold Typography Mobile (Inter-Tight Poster),"Sans + Serif (Display) + Mono","Inter","Playfair Display","bold typography, editorial, poster, near-black, vermillion, luxury, type-as-hero, manifesto, high-contrast","Creative brand flagships, reading platforms, event apps, flash pages, luxury mobile experiences","https://fonts.google.com/share?selection.family=Inter:ital,wght@0,400;0,500;0,600;0,700;0,800;1,400|JetBrains+Mono:wght@400|Playfair+Display:ital@1","@import url('https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400;0,500;0,600;0,700;0,800;1,400&family=JetBrains+Mono:wght@400&family=Playfair+Display:ital@1&display=swap');","fontFamily: { display: ['Inter', 'sans-serif'], quote: ['Playfair Display', 'serif'], mono: ['JetBrains Mono', 'monospace'] }","Tri-stack: Inter 600–800 for all UI (letterSpacing -1.5px heroes, -0.5px subheads). Playfair Display Italic ONLY for pull quotes. JetBrains Mono for labels and stats. Scale: 12px labels, 16px body, 22px sub, 32px section, 40px H2, 56px H1, 72px Hero Statement. 5:1 ratio H1:Body is mandatory. lineHeight 1.1 headlines, 1.6 body. Underlines (2–3pt accent) replace buttons for interactions." -67,Academia Mobile (Cormorant + Crimson + Cinzel),"Serif + Book Serif + Engraved (Triple Stack)","Cormorant Garamond","Crimson Pro","academia, library, mahogany, parchment, brass, scholarly, prestige, antique, victorian, leather","Knowledge management apps, scholarly reading tools, personal brand portfolios, RPG games, cultural community platforms","https://fonts.google.com/share?selection.family=Cinzel:wght@400;500;600|Cormorant+Garamond:ital,wght@0,300;0,500;0,700;1,300;1,500|Crimson+Pro:ital,wght@0,300;0,400;0,600;1,300;1,400","@import url('https://fonts.googleapis.com/css2?family=Cinzel:wght@400;500;600&family=Cormorant+Garamond:ital,wght@0,300;0,500;0,700;1,300;1,500&family=Crimson+Pro:ital,wght@0,300;0,400;0,600;1,300;1,400&display=swap');","fontFamily: { heading: ['Cormorant Garamond', 'serif'], body: ['Crimson Pro', 'serif'], display: ['Cinzel', 'serif'] }","Triple-stack: Cormorant Garamond Medium for all headings (32–40px tight leading). Crimson Pro Regular for body reading text (16–18px, lineHeight 24–26px). Cinzel SemiBold for ALL-CAPS labels, overlines, section prefixes (10–12px, letterSpacing 2–3px). Drop caps: first letter 60px Cinzel in Brass #C9A962. Section prefix: VOLUME I/II/III in Cinzel 10px. NO sans-serif anywhere." -68,Cyberpunk Mobile (Orbitron + JetBrains Mono),"Tech Display + Mono","Orbitron","JetBrains Mono","cyberpunk, neon, glitch, hud, sci-fi, dark, matrix green, magenta, chamfered, tactical","Gaming companion apps, fintech/crypto, data visualization, dark brand apps, cyberpunk narrative games","https://fonts.google.com/share?selection.family=JetBrains+Mono:wght@400;500|Orbitron:wght@700;900","@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&family=Orbitron:wght@700;900&display=swap');","fontFamily: { heading: ['Orbitron', 'sans-serif'], body: ['JetBrains Mono', 'monospace'] }","Dual-stack: Orbitron 700–900 for H1 (42px uppercase letterSpacing 4, fontWeight 900). JetBrains Mono 400–500 for all body/data text (14px letterSpacing 1). Labels: 10px uppercase opacity 0.7. Heading scale aggressive: H1 42px, H2 28px, Section 20px. Body 14px monospace only. NO mixed sans-serif. Fallback: monospace system font. Orbitron requires loading — use NativeWind or useFonts hook." -69,Web3 Bitcoin DeFi (Space Grotesk + Inter + Mono),"Geometric Sans + Sans + Mono (Triple)","Space Grotesk","Inter","web3, bitcoin, defi, digital gold, fintech, crypto, trustless, luminescent, precision, dark","DeFi protocols and wallets, NFT platforms, metaverse social apps, high-tech brand landing pages","https://fonts.google.com/share?selection.family=Inter:wght@400;500;600;700|JetBrains+Mono:wght@400;500|Space+Grotesk:wght@500;600;700","@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&family=Space+Grotesk:wght@500;600;700&display=swap');","fontFamily: { heading: ['Space Grotesk', 'sans-serif'], body: ['Inter', 'sans-serif'], mono: ['JetBrains Mono', 'monospace'] }","Tri-stack: Space Grotesk 600–700 for headings (geometric, technical character). Inter 400–600 for all body and UI text (high legibility). JetBrains Mono Medium for all data/stats/prices/hashes (technical accuracy). Buttons: Inter Bold uppercase letterSpacing 1.5. Balance figures use MaskedView gradient text (orange→gold). Heading scale: H1 36–42px, H2 24–28px, body 16–18px, mono labels 12–14px." -70,Claymorphism Mobile (Nunito + DM Sans),"Display Rounded + Geometric Sans","Nunito","DM Sans","claymorphism, clay, rounded, playful, candy, bubbly, soft, 3d, children, education, tactile, spring, nunito, dm sans","Children education apps, teen social, brand mascot apps, creative tools, fintech gamification","https://fonts.google.com/share?selection.family=DM+Sans:ital,wght@0,400;0,500;0,700;1,400|Nunito:ital,wght@0,700;0,800;0,900;1,700","@import url('https://fonts.googleapis.com/css2?family=DM+Sans:ital,wght@0,400;0,500;0,700;1,400&family=Nunito:ital,wght@0,700;0,800;0,900;1,700&display=swap');","fontFamily: { display: ['Nunito', 'sans-serif'], body: ['DM Sans', 'sans-serif'] }","Dual-stack: Nunito Black (900) or ExtraBold (800) for ALL headings — rounded terminals are mandatory. DM Sans Medium (500) for body text — clean and geometric. Scale: Hero 48px lineHeight 52 letterSpacing -1. Section Title 32px lineHeight 38. Card Title 22px lineHeight 28. Body 16px lineHeight 24. Never use Nunito for body text (too decorative at small sizes). Never use weights below 700 for any heading. includeFontPadding: false on all Nunito Text components for vertical centering in rounded buttons." -71,Enterprise SaaS Mobile (Plus Jakarta Sans),"Geometric Sans (Single Family)","Plus Jakarta Sans","Plus Jakarta Sans","enterprise, saas, b2b, professional, indigo, modern, approachable, legible, ios dynamic type, android scaling","B2B SaaS apps, productivity tools, government and finance mobile apps, admin dashboards, enterprise onboarding","https://fonts.google.com/share?selection.family=Plus+Jakarta+Sans:ital,wght@0,400;0,600;0,700;0,800;1,400","@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,400;0,600;0,700;0,800;1,400&display=swap');","fontFamily: { sans: ['Plus Jakarta Sans', 'sans-serif'] }","Single-family system: Plus Jakarta Sans balances professional authority with mobile approachability. Weight scale: ExtraBold 800 for screen titles/hero (line height 1.1–1.2). Bold 700 for section headers. SemiBold 600 for card titles and buttons. Regular 400 for body text (line height 1.4–1.5). Must support iOS Dynamic Type and Android font scaling — never hardcode pixel sizes without respecting system font scale. Button text: uppercase, letterSpacing 0.5. Caption: 12px Regular. Muted: Slate 500 #64748B." -72,Sketch Hand-Drawn Mobile (Kalam + Patrick Hand),"Handwritten + Handwritten (Dual)","Kalam","Patrick Hand","sketch, hand-drawn, handwriting, human, imperfect, organic, paper, kalam, patrick hand, education, journal, creative","Journaling apps, prototype tools, children's picturebook apps, creative platforms, gamified puzzle apps","https://fonts.google.com/share?selection.family=Kalam:wght@400;700|Patrick+Hand","@import url('https://fonts.googleapis.com/css2?family=Kalam:wght@400;700&family=Patrick+Hand&display=swap');","fontFamily: { heading: ['Kalam', 'cursive'], body: ['Patrick Hand', 'cursive'] }","Dual handwritten stack: Kalam Bold (700) for all headings — high visual weight, felt-tip marker aesthetic, conveys intentional messiness. Patrick Hand Regular for all body text — highly legible at mobile sizes while remaining distinctly human. Scale: Heading 28–36px with lineHeight adjusted for descenders. Body 16–18px lineHeight 1.5. Labels 14px. Vary font sizes slightly between adjacent elements for spontaneous feel. Avoid alignment: 'center' for long body text — left-aligned reads more naturally. Both fonts require useFonts loading in Expo. Never use these fonts for financial figures or legal text." -73,Neumorphism Mobile (Plus Jakarta Sans + System),"Geometric Sans (System Fallback)","Plus Jakarta Sans","Plus Jakarta Sans","neumorphism, soft ui, monochromatic, cool grey, minimal, physical, depth, ceramic, system font, utility","Smart home controls, minimal tools, aesthetic dashboards, health monitors, brand showcase pages","https://fonts.google.com/share?selection.family=Plus+Jakarta+Sans:ital,wght@0,400;0,500;0,700;1,400","@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,400;0,500;0,700;1,400&display=swap');","fontFamily: { sans: ['Plus Jakarta Sans', 'sans-serif'] }","Single-family or System fallback: Plus Jakarta Sans Bold/Medium pairs beautifully with the monochromatic #E0E5EC surface — subtle geometry without competing with the depth effect. Heading: 24–32px Bold (700), letterSpacing -0.5 for modern premium feel. Body: 16px Medium (500), lineHeight 1.4. Caption: 12px Regular (400). Use Text Primary #3D4852 (7.5:1 contrast against #E0E5EC) for all primary text. Use Text Muted #6B7280 (4.6:1 contrast) for secondary text. Accent color #6C63FF only on active labels or focus indicators. Never use italic or thin weights — they lose legibility against the embossed background. System (SF Pro / Roboto) is an acceptable fallback for performance-sensitive implementations." +1,Classic Elegant,"Serif + Sans",Playfair Display,Inter,"elegant, luxury, sophisticated, timeless, premium, editorial","Luxury brands, fashion, spa, beauty, editorial, magazines, high-end e-commerce","https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Playfair+Display:wght@400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Playfair+Display:wght@400;500;600;700&display=swap');","fontFamily: { serif: ['Playfair Display', 'serif'], sans: ['Inter', 'sans-serif'] }","High contrast between elegant heading and clean body. Perfect for luxury/premium." +2,Modern Professional,"Sans + Sans",Poppins,Open Sans,"modern, professional, clean, corporate, friendly, approachable","SaaS, corporate sites, business apps, startups, professional services","https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;500;600;700&family=Poppins:wght@400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Open+Sans:wght@300;400;500;600;700&family=Poppins:wght@400;500;600;700&display=swap');","fontFamily: { heading: ['Poppins', 'sans-serif'], body: ['Open Sans', 'sans-serif'] }","Geometric Poppins for headings, humanist Open Sans for readability." +3,Tech Startup,"Sans + Sans",Space Grotesk,DM Sans,"tech, startup, modern, innovative, bold, futuristic","Tech companies, startups, SaaS, developer tools, AI products","https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;700&family=Space+Grotesk:wght@400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;700&family=Space+Grotesk:wght@400;500;600;700&display=swap');","fontFamily: { heading: ['Space Grotesk', 'sans-serif'], body: ['DM Sans', 'sans-serif'] }","Space Grotesk has unique character, DM Sans is highly readable." +4,Editorial Classic,"Serif + Serif",Cormorant Garamond,Libre Baskerville,"editorial, classic, literary, traditional, refined, bookish","Publishing, blogs, news sites, literary magazines, book covers","https://fonts.googleapis.com/css2?family=Cormorant+Garamond:wght@400;500;600;700&family=Libre+Baskerville:wght@400;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Cormorant+Garamond:wght@400;500;600;700&family=Libre+Baskerville:wght@400;700&display=swap');","fontFamily: { heading: ['Cormorant Garamond', 'serif'], body: ['Libre Baskerville', 'serif'] }","All-serif pairing for traditional editorial feel." +5,Minimal Swiss,"Sans + Sans",Inter,Inter,"minimal, clean, swiss, functional, neutral, professional","Dashboards, admin panels, documentation, enterprise apps, design systems","https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');","fontFamily: { sans: ['Inter', 'sans-serif'] }","Single font family with weight variations. Ultimate simplicity." +6,Playful Creative,"Display + Sans",Fredoka,Nunito,"playful, friendly, fun, creative, warm, approachable","Children's apps, educational, gaming, creative tools, entertainment","https://fonts.googleapis.com/css2?family=Fredoka:wght@400;500;600;700&family=Nunito:wght@300;400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Fredoka:wght@400;500;600;700&family=Nunito:wght@300;400;500;600;700&display=swap');","fontFamily: { heading: ['Fredoka', 'sans-serif'], body: ['Nunito', 'sans-serif'] }","Rounded, friendly fonts perfect for playful UIs." +7,Bold Statement,"Display + Sans",Bebas Neue,Source Sans 3,"bold, impactful, strong, dramatic, modern, headlines","Marketing sites, portfolios, agencies, event pages, sports","https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Source+Sans+3:wght@300;400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Bebas+Neue&family=Source+Sans+3:wght@300;400;500;600;700&display=swap');","fontFamily: { display: ['Bebas Neue', 'sans-serif'], body: ['Source Sans 3', 'sans-serif'] }","Bebas Neue for large headlines only. All-caps display font." +8,Wellness Calm,"Serif + Sans",Lora,Raleway,"calm, wellness, health, relaxing, natural, organic","Health apps, wellness, spa, meditation, yoga, organic brands","https://fonts.googleapis.com/css2?family=Lora:wght@400;500;600;700&family=Raleway:wght@300;400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Lora:wght@400;500;600;700&family=Raleway:wght@300;400;500;600;700&display=swap');","fontFamily: { serif: ['Lora', 'serif'], sans: ['Raleway', 'sans-serif'] }","Lora's organic curves with Raleway's elegant simplicity." +9,Developer Mono,"Mono + Sans",JetBrains Mono,IBM Plex Sans,"code, developer, technical, precise, functional, hacker","Developer tools, documentation, code editors, tech blogs, CLI apps","https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500;600;700&display=swap');","fontFamily: { mono: ['JetBrains Mono', 'monospace'], sans: ['IBM Plex Sans', 'sans-serif'] }","JetBrains for code, IBM Plex for UI. Developer-focused." +10,Retro Vintage,"Display + Serif",Abril Fatface,Merriweather,"retro, vintage, nostalgic, dramatic, decorative, bold","Vintage brands, breweries, restaurants, creative portfolios, posters","https://fonts.googleapis.com/css2?family=Abril+Fatface&family=Merriweather:wght@300;400;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Abril+Fatface&family=Merriweather:wght@300;400;700&display=swap');","fontFamily: { display: ['Abril Fatface', 'serif'], body: ['Merriweather', 'serif'] }","Abril Fatface for hero headlines only. High-impact vintage feel." +11,Geometric Modern,"Sans + Sans",Outfit,Work Sans,"geometric, modern, clean, balanced, contemporary, versatile","General purpose, portfolios, agencies, modern brands, landing pages","https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&family=Work+Sans:wght@300;400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&family=Work+Sans:wght@300;400;500;600;700&display=swap');","fontFamily: { heading: ['Outfit', 'sans-serif'], body: ['Work Sans', 'sans-serif'] }","Both geometric but Outfit more distinctive for headings." +12,Luxury Serif,"Serif + Sans",Cormorant,Montserrat,"luxury, high-end, fashion, elegant, refined, premium","Fashion brands, luxury e-commerce, jewelry, high-end services","https://fonts.googleapis.com/css2?family=Cormorant:wght@400;500;600;700&family=Montserrat:wght@300;400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Cormorant:wght@400;500;600;700&family=Montserrat:wght@300;400;500;600;700&display=swap');","fontFamily: { serif: ['Cormorant', 'serif'], sans: ['Montserrat', 'sans-serif'] }","Cormorant's elegance with Montserrat's geometric precision." +13,Friendly SaaS,"Sans + Sans",Plus Jakarta Sans,Plus Jakarta Sans,"friendly, modern, saas, clean, approachable, professional","SaaS products, web apps, dashboards, B2B, productivity tools","https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@300;400;500;600;700&display=swap');","fontFamily: { sans: ['Plus Jakarta Sans', 'sans-serif'] }","Single versatile font. Modern alternative to Inter." +14,News Editorial,"Serif + Sans",Newsreader,Roboto,"news, editorial, journalism, trustworthy, readable, informative","News sites, blogs, magazines, journalism, content-heavy sites","https://fonts.googleapis.com/css2?family=Newsreader:wght@400;500;600;700&family=Roboto:wght@300;400;500;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Newsreader:wght@400;500;600;700&family=Roboto:wght@300;400;500;700&display=swap');","fontFamily: { serif: ['Newsreader', 'serif'], sans: ['Roboto', 'sans-serif'] }","Newsreader designed for long-form reading. Roboto for UI." +15,Handwritten Charm,"Script + Sans",Caveat,Quicksand,"handwritten, personal, friendly, casual, warm, charming","Personal blogs, invitations, creative portfolios, lifestyle brands","https://fonts.googleapis.com/css2?family=Caveat:wght@400;500;600;700&family=Quicksand:wght@300;400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Caveat:wght@400;500;600;700&family=Quicksand:wght@300;400;500;600;700&display=swap');","fontFamily: { script: ['Caveat', 'cursive'], sans: ['Quicksand', 'sans-serif'] }","Use Caveat sparingly for accents. Quicksand for body." +16,Corporate Trust,"Sans + Sans",Lexend,Source Sans 3,"corporate, trustworthy, accessible, readable, professional, clean","Enterprise, government, healthcare, finance, accessibility-focused","https://fonts.googleapis.com/css2?family=Lexend:wght@300;400;500;600;700&family=Source+Sans+3:wght@300;400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Lexend:wght@300;400;500;600;700&family=Source+Sans+3:wght@300;400;500;600;700&display=swap');","fontFamily: { heading: ['Lexend', 'sans-serif'], body: ['Source Sans 3', 'sans-serif'] }","Lexend designed for readability. Excellent accessibility." +17,Brutalist Raw,"Mono + Mono",Space Mono,Space Mono,"brutalist, raw, technical, monospace, minimal, stark","Brutalist designs, developer portfolios, experimental, tech art","https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&display=swap');","fontFamily: { mono: ['Space Mono', 'monospace'] }","All-mono for raw brutalist aesthetic. Limited weights." +18,Fashion Forward,"Sans + Sans",Syne,Manrope,"fashion, avant-garde, creative, bold, artistic, edgy","Fashion brands, creative agencies, art galleries, design studios","https://fonts.googleapis.com/css2?family=Manrope:wght@300;400;500;600;700&family=Syne:wght@400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Manrope:wght@300;400;500;600;700&family=Syne:wght@400;500;600;700&display=swap');","fontFamily: { heading: ['Syne', 'sans-serif'], body: ['Manrope', 'sans-serif'] }","Syne's unique character for headlines. Manrope for readability." +19,Soft Rounded,"Sans + Sans",Varela Round,Nunito Sans,"soft, rounded, friendly, approachable, warm, gentle","Children's products, pet apps, friendly brands, wellness, soft UI","https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@300;400;500;600;700&family=Varela+Round&display=swap","@import url('https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@300;400;500;600;700&family=Varela+Round&display=swap');","fontFamily: { heading: ['Varela Round', 'sans-serif'], body: ['Nunito Sans', 'sans-serif'] }","Both rounded and friendly. Perfect for soft UI designs." +20,Premium Sans,"Sans + Sans",Satoshi,General Sans,"premium, modern, clean, sophisticated, versatile, balanced","Premium brands, modern agencies, SaaS, portfolios, startups","https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;700&display=swap');","fontFamily: { sans: ['DM Sans', 'sans-serif'] }","Note: Satoshi/General Sans on Fontshare. DM Sans as Google alternative." +21,Vietnamese Friendly,"Sans + Sans",Be Vietnam Pro,Noto Sans,"vietnamese, international, readable, clean, multilingual, accessible","Vietnamese sites, multilingual apps, international products","https://fonts.googleapis.com/css2?family=Be+Vietnam+Pro:wght@300;400;500;600;700&family=Noto+Sans:wght@300;400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Be+Vietnam+Pro:wght@300;400;500;600;700&family=Noto+Sans:wght@300;400;500;600;700&display=swap');","fontFamily: { sans: ['Be Vietnam Pro', 'Noto Sans', 'sans-serif'] }","Be Vietnam Pro excellent Vietnamese support. Noto as fallback." +22,Japanese Elegant,"Serif + Sans",Noto Serif JP,Noto Sans JP,"japanese, elegant, traditional, modern, multilingual, readable","Japanese sites, Japanese restaurants, cultural sites, anime/manga","https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@300;400;500;700&family=Noto+Serif+JP:wght@400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+JP:wght@300;400;500;700&family=Noto+Serif+JP:wght@400;500;600;700&display=swap');","fontFamily: { serif: ['Noto Serif JP', 'serif'], sans: ['Noto Sans JP', 'sans-serif'] }","Noto fonts excellent Japanese support. Traditional + modern feel." +23,Korean Modern,"Sans + Sans",Noto Sans KR,Noto Sans KR,"korean, modern, clean, professional, multilingual, readable","Korean sites, K-beauty, K-pop, Korean businesses, multilingual","https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;500;700&display=swap');","fontFamily: { sans: ['Noto Sans KR', 'sans-serif'] }","Clean Korean typography. Single font with weight variations." +24,Chinese Traditional,"Serif + Sans",Noto Serif TC,Noto Sans TC,"chinese, traditional, elegant, cultural, multilingual, readable","Traditional Chinese sites, cultural content, Taiwan/Hong Kong markets","https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@300;400;500;700&family=Noto+Serif+TC:wght@400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+TC:wght@300;400;500;700&family=Noto+Serif+TC:wght@400;500;600;700&display=swap');","fontFamily: { serif: ['Noto Serif TC', 'serif'], sans: ['Noto Sans TC', 'sans-serif'] }","Traditional Chinese character support. Elegant pairing." +25,Chinese Simplified,"Sans + Sans",Noto Sans SC,Noto Sans SC,"chinese, simplified, modern, professional, multilingual, readable","Simplified Chinese sites, mainland China market, business apps","https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300;400;500;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300;400;500;700&display=swap');","fontFamily: { sans: ['Noto Sans SC', 'sans-serif'] }","Simplified Chinese support. Clean modern look." +26,Arabic Elegant,"Serif + Sans",Noto Naskh Arabic,Noto Sans Arabic,"arabic, elegant, traditional, cultural, RTL, readable","Arabic sites, Middle East market, Islamic content, bilingual sites","https://fonts.googleapis.com/css2?family=Noto+Naskh+Arabic:wght@400;500;600;700&family=Noto+Sans+Arabic:wght@300;400;500;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Noto+Naskh+Arabic:wght@400;500;600;700&family=Noto+Sans+Arabic:wght@300;400;500;700&display=swap');","fontFamily: { serif: ['Noto Naskh Arabic', 'serif'], sans: ['Noto Sans Arabic', 'sans-serif'] }","RTL support. Naskh for traditional, Sans for modern Arabic." +27,Thai Modern,"Sans + Sans",Noto Sans Thai,Noto Sans Thai,"thai, modern, readable, clean, multilingual, accessible","Thai sites, Southeast Asia, tourism, Thai restaurants","https://fonts.googleapis.com/css2?family=Noto+Sans+Thai:wght@300;400;500;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+Thai:wght@300;400;500;700&display=swap');","fontFamily: { sans: ['Noto Sans Thai', 'sans-serif'] }","Clean Thai typography. Excellent readability." +28,Hebrew Modern,"Sans + Sans",Noto Sans Hebrew,Noto Sans Hebrew,"hebrew, modern, RTL, clean, professional, readable","Hebrew sites, Israeli market, Jewish content, bilingual sites","https://fonts.googleapis.com/css2?family=Noto+Sans+Hebrew:wght@300;400;500;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+Hebrew:wght@300;400;500;700&display=swap');","fontFamily: { sans: ['Noto Sans Hebrew', 'sans-serif'] }","RTL support. Clean modern Hebrew typography." +29,Legal Professional,"Serif + Sans",EB Garamond,Lato,"legal, professional, traditional, trustworthy, formal, authoritative","Law firms, legal services, contracts, formal documents, government","https://fonts.googleapis.com/css2?family=EB+Garamond:wght@400;500;600;700&family=Lato:wght@300;400;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=EB+Garamond:wght@400;500;600;700&family=Lato:wght@300;400;700&display=swap');","fontFamily: { serif: ['EB Garamond', 'serif'], sans: ['Lato', 'sans-serif'] }","EB Garamond for authority. Lato for clean body text." +30,Medical Clean,"Sans + Sans",Figtree,Noto Sans,"medical, clean, accessible, professional, healthcare, trustworthy","Healthcare, medical clinics, pharma, health apps, accessibility","https://fonts.googleapis.com/css2?family=Figtree:wght@300;400;500;600;700&family=Noto+Sans:wght@300;400;500;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Figtree:wght@300;400;500;600;700&family=Noto+Sans:wght@300;400;500;700&display=swap');","fontFamily: { heading: ['Figtree', 'sans-serif'], body: ['Noto Sans', 'sans-serif'] }","Clean, accessible fonts for medical contexts." +31,Financial Trust,"Sans + Sans",IBM Plex Sans,IBM Plex Sans,"financial, trustworthy, professional, corporate, banking, serious","Banks, finance, insurance, investment, fintech, enterprise","https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@300;400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@300;400;500;600;700&display=swap');","fontFamily: { sans: ['IBM Plex Sans', 'sans-serif'] }","IBM Plex conveys trust and professionalism. Excellent for data." +32,Real Estate Luxury,"Serif + Sans",Cinzel,Josefin Sans,"real estate, luxury, elegant, sophisticated, property, premium","Real estate, luxury properties, architecture, interior design","https://fonts.googleapis.com/css2?family=Cinzel:wght@400;500;600;700&family=Josefin+Sans:wght@300;400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Cinzel:wght@400;500;600;700&family=Josefin+Sans:wght@300;400;500;600;700&display=swap');","fontFamily: { serif: ['Cinzel', 'serif'], sans: ['Josefin Sans', 'sans-serif'] }","Cinzel's elegance for headlines. Josefin for modern body." +33,Restaurant Menu,"Serif + Sans",Playfair Display SC,Karla,"restaurant, menu, culinary, elegant, foodie, hospitality","Restaurants, cafes, food blogs, culinary, hospitality","https://fonts.googleapis.com/css2?family=Karla:wght@300;400;500;600;700&family=Playfair+Display+SC:wght@400;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Karla:wght@300;400;500;600;700&family=Playfair+Display+SC:wght@400;700&display=swap');","fontFamily: { display: ['Playfair Display SC', 'serif'], sans: ['Karla', 'sans-serif'] }","Small caps Playfair for menu headers. Karla for descriptions." +34,Art Deco,"Display + Sans",Poiret One,Didact Gothic,"art deco, vintage, 1920s, elegant, decorative, gatsby","Vintage events, art deco themes, luxury hotels, classic cocktails","https://fonts.googleapis.com/css2?family=Didact+Gothic&family=Poiret+One&display=swap","@import url('https://fonts.googleapis.com/css2?family=Didact+Gothic&family=Poiret+One&display=swap');","fontFamily: { display: ['Poiret One', 'sans-serif'], sans: ['Didact Gothic', 'sans-serif'] }","Poiret One for art deco headlines only. Didact for body." +35,Magazine Style,"Serif + Sans",Libre Bodoni,Public Sans,"magazine, editorial, publishing, refined, journalism, print","Magazines, online publications, editorial content, journalism","https://fonts.googleapis.com/css2?family=Libre+Bodoni:wght@400;500;600;700&family=Public+Sans:wght@300;400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Libre+Bodoni:wght@400;500;600;700&family=Public+Sans:wght@300;400;500;600;700&display=swap');","fontFamily: { serif: ['Libre Bodoni', 'serif'], sans: ['Public Sans', 'sans-serif'] }","Bodoni's editorial elegance. Public Sans for clean UI." +36,Crypto/Web3,"Sans + Sans",Orbitron,Exo 2,"crypto, web3, futuristic, tech, blockchain, digital","Crypto platforms, NFT, blockchain, web3, futuristic tech","https://fonts.googleapis.com/css2?family=Exo+2:wght@300;400;500;600;700&family=Orbitron:wght@400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Exo+2:wght@300;400;500;600;700&family=Orbitron:wght@400;500;600;700&display=swap');","fontFamily: { display: ['Orbitron', 'sans-serif'], body: ['Exo 2', 'sans-serif'] }","Orbitron for futuristic headers. Exo 2 for readable body." +37,Gaming Bold,"Display + Sans",Russo One,Chakra Petch,"gaming, bold, action, esports, competitive, energetic","Gaming, esports, action games, competitive sports, entertainment","https://fonts.googleapis.com/css2?family=Chakra+Petch:wght@300;400;500;600;700&family=Russo+One&display=swap","@import url('https://fonts.googleapis.com/css2?family=Chakra+Petch:wght@300;400;500;600;700&family=Russo+One&display=swap');","fontFamily: { display: ['Russo One', 'sans-serif'], body: ['Chakra Petch', 'sans-serif'] }","Russo One for impact. Chakra Petch for techy body text." +38,Indie/Craft,"Display + Sans",Amatic SC,Cabin,"indie, craft, handmade, artisan, organic, creative","Craft brands, indie products, artisan, handmade, organic products","https://fonts.googleapis.com/css2?family=Amatic+SC:wght@400;700&family=Cabin:wght@400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Amatic+SC:wght@400;700&family=Cabin:wght@400;500;600;700&display=swap');","fontFamily: { display: ['Amatic SC', 'sans-serif'], sans: ['Cabin', 'sans-serif'] }","Amatic for handwritten feel. Cabin for readable body." +39,Startup Bold,"Sans + Sans",Clash Display,Satoshi,"startup, bold, modern, innovative, confident, dynamic","Startups, pitch decks, product launches, bold brands","https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700&family=Rubik:wght@300;400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700&family=Rubik:wght@300;400;500;600;700&display=swap');","fontFamily: { heading: ['Outfit', 'sans-serif'], body: ['Rubik', 'sans-serif'] }","Note: Clash Display on Fontshare. Outfit as Google alternative." +40,E-commerce Clean,"Sans + Sans",Rubik,Nunito Sans,"ecommerce, clean, shopping, product, retail, conversion","E-commerce, online stores, product pages, retail, shopping","https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@300;400;500;600;700&family=Rubik:wght@300;400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Nunito+Sans:wght@300;400;500;600;700&family=Rubik:wght@300;400;500;600;700&display=swap');","fontFamily: { heading: ['Rubik', 'sans-serif'], body: ['Nunito Sans', 'sans-serif'] }","Clean readable fonts perfect for product descriptions." +41,Academic/Research,"Serif + Sans",Crimson Pro,Atkinson Hyperlegible,"academic, research, scholarly, accessible, readable, educational","Universities, research papers, academic journals, educational","https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible:wght@400;700&family=Crimson+Pro:wght@400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible:wght@400;700&family=Crimson+Pro:wght@400;500;600;700&display=swap');","fontFamily: { serif: ['Crimson Pro', 'serif'], sans: ['Atkinson Hyperlegible', 'sans-serif'] }","Crimson for scholarly headlines. Atkinson for accessibility." +42,Dashboard Data,"Mono + Sans",Fira Code,Fira Sans,"dashboard, data, analytics, code, technical, precise","Dashboards, analytics, data visualization, admin panels","https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&family=Fira+Sans:wght@300;400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&family=Fira+Sans:wght@300;400;500;600;700&display=swap');","fontFamily: { mono: ['Fira Code', 'monospace'], sans: ['Fira Sans', 'sans-serif'] }","Fira family cohesion. Code for data, Sans for labels." +43,Music/Entertainment,"Display + Sans",Righteous,Poppins,"music, entertainment, fun, energetic, bold, performance","Music platforms, entertainment, events, festivals, performers","https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&family=Righteous&display=swap","@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&family=Righteous&display=swap');","fontFamily: { display: ['Righteous', 'sans-serif'], sans: ['Poppins', 'sans-serif'] }","Righteous for bold entertainment headers. Poppins for body." +44,Minimalist Portfolio,"Sans + Sans",Archivo,Space Grotesk,"minimal, portfolio, designer, creative, clean, artistic","Design portfolios, creative professionals, minimalist brands","https://fonts.googleapis.com/css2?family=Archivo:wght@300;400;500;600;700&family=Space+Grotesk:wght@300;400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Archivo:wght@300;400;500;600;700&family=Space+Grotesk:wght@300;400;500;600;700&display=swap');","fontFamily: { heading: ['Space Grotesk', 'sans-serif'], body: ['Archivo', 'sans-serif'] }","Space Grotesk for distinctive headers. Archivo for clean body." +45,Kids/Education,"Display + Sans",Baloo 2,Comic Neue,"kids, education, playful, friendly, colorful, learning","Children's apps, educational games, kid-friendly content","https://fonts.googleapis.com/css2?family=Baloo+2:wght@400;500;600;700&family=Comic+Neue:wght@300;400;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Baloo+2:wght@400;500;600;700&family=Comic+Neue:wght@300;400;700&display=swap');","fontFamily: { display: ['Baloo 2', 'sans-serif'], sans: ['Comic Neue', 'sans-serif'] }","Fun, playful fonts for children. Comic Neue is readable comic style." +46,Wedding/Romance,"Script + Serif",Great Vibes,Cormorant Infant,"wedding, romance, elegant, script, invitation, feminine","Wedding sites, invitations, romantic brands, bridal","https://fonts.googleapis.com/css2?family=Cormorant+Infant:wght@300;400;500;600;700&family=Great+Vibes&display=swap","@import url('https://fonts.googleapis.com/css2?family=Cormorant+Infant:wght@300;400;500;600;700&family=Great+Vibes&display=swap');","fontFamily: { script: ['Great Vibes', 'cursive'], serif: ['Cormorant Infant', 'serif'] }","Great Vibes for elegant accents. Cormorant for readable text." +47,Science/Tech,"Sans + Sans",Exo,Roboto Mono,"science, technology, research, data, futuristic, precise","Science, research, tech documentation, data-heavy sites","https://fonts.googleapis.com/css2?family=Exo:wght@300;400;500;600;700&family=Roboto+Mono:wght@300;400;500;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Exo:wght@300;400;500;600;700&family=Roboto+Mono:wght@300;400;500;700&display=swap');","fontFamily: { sans: ['Exo', 'sans-serif'], mono: ['Roboto Mono', 'monospace'] }","Exo for modern tech feel. Roboto Mono for code/data." +48,Accessibility First,"Sans + Sans",Atkinson Hyperlegible,Atkinson Hyperlegible,"accessible, readable, inclusive, WCAG, dyslexia-friendly, clear","Accessibility-critical sites, government, healthcare, inclusive design","https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible:wght@400;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible:wght@400;700&display=swap');","fontFamily: { sans: ['Atkinson Hyperlegible', 'sans-serif'] }","Designed for maximum legibility. Excellent for accessibility." +49,Sports/Fitness,"Sans + Sans",Barlow Condensed,Barlow,"sports, fitness, athletic, energetic, condensed, action","Sports, fitness, gyms, athletic brands, competition","https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@400;500;600;700&family=Barlow:wght@300;400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Barlow+Condensed:wght@400;500;600;700&family=Barlow:wght@300;400;500;600;700&display=swap');","fontFamily: { display: ['Barlow Condensed', 'sans-serif'], body: ['Barlow', 'sans-serif'] }","Condensed for impact headlines. Regular Barlow for body." +50,Luxury Minimalist,"Serif + Sans",Bodoni Moda,Jost,"luxury, minimalist, high-end, sophisticated, refined, premium","Luxury minimalist brands, high-end fashion, premium products","https://fonts.googleapis.com/css2?family=Bodoni+Moda:wght@400;500;600;700&family=Jost:wght@300;400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Bodoni+Moda:wght@400;500;600;700&family=Jost:wght@300;400;500;600;700&display=swap');","fontFamily: { serif: ['Bodoni Moda', 'serif'], sans: ['Jost', 'sans-serif'] }","Bodoni's high contrast elegance. Jost for geometric body." +51,Tech/HUD Mono,"Mono + Mono",Share Tech Mono,Fira Code,"tech, futuristic, hud, sci-fi, data, monospaced, precise","Sci-fi interfaces, developer tools, cybersecurity, dashboards","https://fonts.googleapis.com/css2?family=Fira+Code:wght@300;400;500;600;700&family=Share+Tech+Mono&display=swap","@import url('https://fonts.googleapis.com/css2?family=Fira+Code:wght@300;400;500;600;700&family=Share+Tech+Mono&display=swap');","fontFamily: { hud: ['Share Tech Mono', 'monospace'], code: ['Fira Code', 'monospace'] }","Share Tech Mono has that classic sci-fi look." +52,Pixel Retro,"Display + Sans",Press Start 2P,VT323,"pixel, retro, gaming, 8-bit, nostalgic, arcade","Pixel art games, retro websites, creative portfolios","https://fonts.googleapis.com/css2?family=Press+Start+2P&family=VT323&display=swap","@import url('https://fonts.googleapis.com/css2?family=Press+Start+2P&family=VT323&display=swap');","fontFamily: { pixel: ['Press Start 2P', 'cursive'], terminal: ['VT323', 'monospace'] }","Press Start 2P is very wide/large. VT323 is better for body text." +53,Neubrutalist Bold,"Display + Sans",Lexend Mega,Public Sans,"bold, neubrutalist, loud, strong, geometric, quirky","Neubrutalist designs, Gen Z brands, bold marketing","https://fonts.googleapis.com/css2?family=Lexend+Mega:wght@100..900&family=Public+Sans:wght@100..900&display=swap","@import url('https://fonts.googleapis.com/css2?family=Lexend+Mega:wght@100..900&family=Public+Sans:wght@100..900&display=swap');","fontFamily: { mega: ['Lexend Mega', 'sans-serif'], body: ['Public Sans', 'sans-serif'] }","Lexend Mega has distinct character and variable weight." +54,Academic/Archival,"Serif + Serif",EB Garamond,Crimson Text,"academic, old-school, university, research, serious, traditional","University sites, archives, research papers, history","https://fonts.googleapis.com/css2?family=Crimson+Text:wght@400;600;700&family=EB+Garamond:wght@400;500;600;700;800&display=swap","@import url('https://fonts.googleapis.com/css2?family=Crimson+Text:wght@400;600;700&family=EB+Garamond:wght@400;500;600;700;800&display=swap');","fontFamily: { classic: ['EB Garamond', 'serif'], text: ['Crimson Text', 'serif'] }","Classic academic aesthetic. Very legible." +55,Spatial Clear,"Sans + Sans",Inter,Inter,"spatial, legible, glass, system, clean, neutral","Spatial computing, AR/VR, glassmorphism interfaces","https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&display=swap","@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600&display=swap');","fontFamily: { sans: ['Inter', 'sans-serif'] }","Optimized for readability on dynamic backgrounds." +56,Kinetic Motion,"Display + Mono",Syncopate,Space Mono,"kinetic, motion, futuristic, speed, wide, tech","Music festivals, automotive, high-energy brands","https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&family=Syncopate:wght@400;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Space+Mono:wght@400;700&family=Syncopate:wght@400;700&display=swap');","fontFamily: { display: ['Syncopate', 'sans-serif'], mono: ['Space Mono', 'monospace'] }","Syncopate's wide stance works well with motion effects." +57,Gen Z Brutal,"Display + Sans",Anton,Epilogue,"brutal, loud, shouty, meme, internet, bold","Gen Z marketing, streetwear, viral campaigns","https://fonts.googleapis.com/css2?family=Anton&family=Epilogue:wght@400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Anton&family=Epilogue:wght@400;500;600;700&display=swap');","fontFamily: { display: ['Anton', 'sans-serif'], body: ['Epilogue', 'sans-serif'] }","Anton is impactful and condensed. Good for stickers/badges."57,Bauhaus Geometric,"Geometric Sans + Single Weight","Outfit","Outfit","bauhaus, geometric, constructivist, bold, uppercase, architectural, mechanical, poster, tactile","Bauhaus mobile apps, bold editorial mobile, design-forward branding apps, art/culture platforms","https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;700;900&display=swap","@import url('https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;700;900&display=swap');","fontFamily: { display: ['Outfit', 'sans-serif'], body: ['Outfit', 'sans-serif'] }","Single-family system: Outfit 900 uppercase tracking-tighter for heroes; Outfit 700 uppercase for buttons/nav; Outfit 500 for body. Scale aggressively: text-4xl–text-5xl headlines on mobile." +58,Minimalist Monochrome Editorial,"Serif + Serif + Mono (Triple Stack)",Playfair Display,Source Serif 4,"monochrome, editorial, austere, typographic, pocket manifesto, luxury, high contrast, brutalist mobile","Luxury fashion mobile apps, editorial publications, digital exhibitions, portfolio apps, high-contrast e-reader aesthetics","https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&family=Playfair+Display:ital,wght@0,400;0,700;0,900;1,400|Source+Serif+4:ital,wght@0,300;0,400;0,600;1,300","@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&family=Playfair+Display:ital,wght@0,400;0,700;0,900;1,400&family=Source+Serif+4:ital,wght@0,300;0,400;0,600;1,300&display=swap');","fontFamily: { display: ['Playfair Display', 'serif'], body: ['Source Serif 4', 'serif'], mono: ['JetBrains Mono', 'monospace'] }","Triple stack: Playfair Display 900 tracking-tighter leading-[0.9] for heroes (text-5xl–text-6xl breaks words graphically). Source Serif 4 300–600 for body legibility. JetBrains Mono 400–500 uppercase tracking-widest for tags/dates/labels. NO UI sans-serif — 100% serif/mono." +59,Modern Dark Cinema (Inter System),"Sans + Mono",Inter,Inter,"dark, cinematic, technical, precision, clean, premium, developer, professional, high-end utility","Developer tools, fintech/trading, AI dashboards, streaming platforms, high-end productivity apps","https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');","fontFamily: { sans: ['Inter', 'sans-serif'] }","Single-family precision system: Inter 700 (-1.5 tracking) for Display 48pt; Inter 600 (-0.5 tracking) for H1 32pt / H2 24pt; Inter 400 for body 16pt; Inter 500 uppercase +1.2 tracking for labels/mono. Gradient text via mask-view + react-native-linear-gradient (#FFFFFF → rgba(255,255,255,0.7)) on major headers." +60,SaaS Mobile Boutique (Calistoga + Inter),"Display Serif + Sans + Mono",Calistoga,Inter,"saas, boutique, electric, warm, editorial, bold, premium, fintech, business, dual font, human warmth","B2B SaaS mobile, fintech apps, analytics dashboards, marketing tools, operations platforms","https://fonts.googleapis.com/css2?family=Calistoga:ital@0;1&family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap","@import url('https://fonts.googleapis.com/css2?family=Calistoga:ital@0;1&family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap');","fontFamily: { display: ['Calistoga', 'serif'], body: ['Inter', 'sans-serif'], mono: ['JetBrains Mono', 'monospace'] }","Tri-stack: Calistoga (adds human warmth) for heroes 36–42pt leading-1.1; Inter 400–600 for body/UI 16–18pt; JetBrains Mono 12pt uppercase tracking-[1.5] for data labels and section badges. Scale: Hero 36–42pt, Section H2 28–32pt, Body 16–18pt, Label 12pt. Avoid italic Calistoga except editorial callouts." +61,Terminal CLI Monospace,"Mono + Mono (Single Family)",JetBrains Mono,JetBrains Mono,"terminal, cli, hacker, monospace, matrix, developer, retro-future, command line, precision, OLED","Developer tools, Web3/blockchain apps, hacker aesthetic, sci-fi games, ARG, security tools, geek-culture portfolios","https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,400;0,500;1,400","@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,400;0,500;1,400&display=swap');","fontFamily: { mono: ['JetBrains Mono', 'monospace'] }","Single monospace system: use ONLY JetBrains Mono (or SpaceMono-Regular as system fallback). Strict sizes: 12pt / 14pt / 16pt only — no in-between. Weight: 400 normal (bold ruins mono character). Line height: 1.2x font size for information density. Letter spacing: normal (monospaced auto-spacing). All UI labels uppercase. ASCII borders and text-based progress bars." +62,Kinetic Brutalism (Space Grotesk),"Geometric Sans (Single Dominant)",Space Grotesk,Space Grotesk,"kinetic, brutalist, aggressive, uppercase, oversized, display, motion, street, bold, high-energy, zine","Music/culture apps, sports platforms, brand flagship mobile, performance dashboards, underground product drops","https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&display=swap');","fontFamily: { display: ['Space Grotesk', 'sans-serif'], body: ['Space Grotesk', 'sans-serif'] }","Dominant single-family system: Space Grotesk 700–900 for ALL display. Scale: Hero 60–120pt (windowWidth/375*size), Section 40–50pt, Card titles 28–32pt, Body 18–20pt, Labels 12pt. ALL display/buttons/nav: UPPERCASE, letterSpacing -1 (large) / +2 (labels), lineHeight 0.9–1.1x. Use Inter as fallback. Font scale must use PixelRatio helper for responsive sizing." +63,Flat Design Mobile (System Bold),"Sans + Sans",Inter,Inter,"flat, clean, system, bold, geometric, cross-platform, icon, poster, minimal, functional, responsive","Cross-platform apps, dashboards, system UI, onboarding, marketing pages, informational apps, icon-heavy interfaces","https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;800&display=swap","@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700;800&display=swap');","fontFamily: { sans: ['Inter', 'sans-serif'] }","System-first strategy: Inter as primary, falls back to system SF/Roboto on iOS/Android. Scale: Headlines fontWeight 800 letterSpacing -0.5; Subheadings fontWeight 600 fontSize 18; Body fontWeight 400 lineHeight 24; Labels fontWeight 700 uppercase letterSpacing 1. Thick weights carry all hierarchy since there are no shadows. Use aggressive size contrast (poster rule: body 16pt vs headline 40pt+). Avoid italic." +64,Material You MD3 (Roboto System),"Sans (System Default)",Roboto,Roboto,"material design 3, md3, android, google, tonal, friendly, rounded, accessible, adaptive","Android apps, cross-platform tools, productivity software, data-heavy B2B dashboards, enterprise mobile","https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,300;0,400;0,500;0,700;1,400","@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,300;0,400;0,500;0,700;1,400&display=swap');","fontFamily: { sans: ['Roboto', 'sans-serif'] }","MD3 type scale: Display Large 56px/400/64px. Headline Large 32px/500/40px. Title Large 22px/500/28px. Body Large 16px/400/24px. Label Medium 12px/500/16px. Buttons and Labels: letterSpacing 0.1px. Use system Roboto on Android; load from Google Fonts for iOS parity. Never use custom weights beyond 300–700." +65,Neo Brutalism Mobile (Space Grotesk Heavy),"Geometric Sans (Bold-Only)",Space Grotesk,Space Grotesk,"neo brutalism, pop art, loud, bold, heavy, stickers, mechanical, high contrast, cream, gen-z","Creative tools, Gen-Z marketing, e-commerce for youth culture, content portfolios, collage-style apps","https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@700&display=swap');","fontFamily: { display: ['Space Grotesk', 'sans-serif'], body: ['Space Grotesk', 'sans-serif'] }","Strictly 700 (Bold) and 900 (Black/Heavy) ONLY — never Regular or Light. Display: 48–64px. Heading: 24–32px. Body: 18–20px (stays heavy for brutalist density). Labels: 14px ALL CAPS letterSpacing 2. All buttons and navigation: uppercase. System bold as fallback. No italic, no thin weights." +66,Bold Typography Mobile (Inter-Tight Poster),"Sans + Serif (Display) + Mono","Inter","Playfair Display","bold typography, editorial, poster, near-black, vermillion, luxury, type-as-hero, manifesto, high-contrast","Creative brand flagships, reading platforms, event apps, flash pages, luxury mobile experiences","https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400;0,500;0,600;0,700;0,800;1,400|JetBrains+Mono:wght@400|Playfair+Display:ital@1","@import url('https://fonts.googleapis.com/css2?family=Inter:ital,wght@0,400;0,500;0,600;0,700;0,800;1,400&family=JetBrains+Mono:wght@400&family=Playfair+Display:ital@1&display=swap');","fontFamily: { display: ['Inter', 'sans-serif'], quote: ['Playfair Display', 'serif'], mono: ['JetBrains Mono', 'monospace'] }","Tri-stack: Inter 600–800 for all UI (letterSpacing -1.5px heroes, -0.5px subheads). Playfair Display Italic ONLY for pull quotes. JetBrains Mono for labels and stats. Scale: 12px labels, 16px body, 22px sub, 32px section, 40px H2, 56px H1, 72px Hero Statement. 5:1 ratio H1:Body is mandatory. lineHeight 1.1 headlines, 1.6 body. Underlines (2–3pt accent) replace buttons for interactions." +67,Academia Mobile (Cormorant + Crimson + Cinzel),"Serif + Book Serif + Engraved (Triple Stack)","Cormorant Garamond","Crimson Pro","academia, library, mahogany, parchment, brass, scholarly, prestige, antique, victorian, leather","Knowledge management apps, scholarly reading tools, personal brand portfolios, RPG games, cultural community platforms","https://fonts.googleapis.com/css2?family=Cinzel:wght@400;500;600&family=Cormorant+Garamond:ital,wght@0,300;0,500;0,700;1,300;1,500|Crimson+Pro:ital,wght@0,300;0,400;0,600;1,300;1,400","@import url('https://fonts.googleapis.com/css2?family=Cinzel:wght@400;500;600&family=Cormorant+Garamond:ital,wght@0,300;0,500;0,700;1,300;1,500&family=Crimson+Pro:ital,wght@0,300;0,400;0,600;1,300;1,400&display=swap');","fontFamily: { heading: ['Cormorant Garamond', 'serif'], body: ['Crimson Pro', 'serif'], display: ['Cinzel', 'serif'] }","Triple-stack: Cormorant Garamond Medium for all headings (32–40px tight leading). Crimson Pro Regular for body reading text (16–18px, lineHeight 24–26px). Cinzel SemiBold for ALL-CAPS labels, overlines, section prefixes (10–12px, letterSpacing 2–3px). Drop caps: first letter 60px Cinzel in Brass #C9A962. Section prefix: VOLUME I/II/III in Cinzel 10px. NO sans-serif anywhere." +68,Cyberpunk Mobile (Orbitron + JetBrains Mono),"Tech Display + Mono","Orbitron","JetBrains Mono","cyberpunk, neon, glitch, hud, sci-fi, dark, matrix green, magenta, chamfered, tactical","Gaming companion apps, fintech/crypto, data visualization, dark brand apps, cyberpunk narrative games","https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&family=Orbitron:wght@700;900&display=swap","@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&family=Orbitron:wght@700;900&display=swap');","fontFamily: { heading: ['Orbitron', 'sans-serif'], body: ['JetBrains Mono', 'monospace'] }","Dual-stack: Orbitron 700–900 for H1 (42px uppercase letterSpacing 4, fontWeight 900). JetBrains Mono 400–500 for all body/data text (14px letterSpacing 1). Labels: 10px uppercase opacity 0.7. Heading scale aggressive: H1 42px, H2 28px, Section 20px. Body 14px monospace only. NO mixed sans-serif. Fallback: monospace system font. Orbitron requires loading — use NativeWind or useFonts hook." +69,Web3 Bitcoin DeFi (Space Grotesk + Inter + Mono),"Geometric Sans + Sans + Mono (Triple)","Space Grotesk","Inter","web3, bitcoin, defi, digital gold, fintech, crypto, trustless, luminescent, precision, dark","DeFi protocols and wallets, NFT platforms, metaverse social apps, high-tech brand landing pages","https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&family=Space+Grotesk:wght@500;600;700&display=swap","@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&family=Space+Grotesk:wght@500;600;700&display=swap');","fontFamily: { heading: ['Space Grotesk', 'sans-serif'], body: ['Inter', 'sans-serif'], mono: ['JetBrains Mono', 'monospace'] }","Tri-stack: Space Grotesk 600–700 for headings (geometric, technical character). Inter 400–600 for all body and UI text (high legibility). JetBrains Mono Medium for all data/stats/prices/hashes (technical accuracy). Buttons: Inter Bold uppercase letterSpacing 1.5. Balance figures use MaskedView gradient text (orange→gold). Heading scale: H1 36–42px, H2 24–28px, body 16–18px, mono labels 12–14px." +70,Claymorphism Mobile (Nunito + DM Sans),"Display Rounded + Geometric Sans","Nunito","DM Sans","claymorphism, clay, rounded, playful, candy, bubbly, soft, 3d, children, education, tactile, spring, nunito, dm sans","Children education apps, teen social, brand mascot apps, creative tools, fintech gamification","https://fonts.googleapis.com/css2?family=DM+Sans:ital,wght@0,400;0,500;0,700;1,400|Nunito:ital,wght@0,700;0,800;0,900;1,700","@import url('https://fonts.googleapis.com/css2?family=DM+Sans:ital,wght@0,400;0,500;0,700;1,400&family=Nunito:ital,wght@0,700;0,800;0,900;1,700&display=swap');","fontFamily: { display: ['Nunito', 'sans-serif'], body: ['DM Sans', 'sans-serif'] }","Dual-stack: Nunito Black (900) or ExtraBold (800) for ALL headings — rounded terminals are mandatory. DM Sans Medium (500) for body text — clean and geometric. Scale: Hero 48px lineHeight 52 letterSpacing -1. Section Title 32px lineHeight 38. Card Title 22px lineHeight 28. Body 16px lineHeight 24. Never use Nunito for body text (too decorative at small sizes). Never use weights below 700 for any heading. includeFontPadding: false on all Nunito Text components for vertical centering in rounded buttons." +71,Enterprise SaaS Mobile (Plus Jakarta Sans),"Geometric Sans (Single Family)","Plus Jakarta Sans","Plus Jakarta Sans","enterprise, saas, b2b, professional, indigo, modern, approachable, legible, ios dynamic type, android scaling","B2B SaaS apps, productivity tools, government and finance mobile apps, admin dashboards, enterprise onboarding","https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,400;0,600;0,700;0,800;1,400","@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,400;0,600;0,700;0,800;1,400&display=swap');","fontFamily: { sans: ['Plus Jakarta Sans', 'sans-serif'] }","Single-family system: Plus Jakarta Sans balances professional authority with mobile approachability. Weight scale: ExtraBold 800 for screen titles/hero (line height 1.1–1.2). Bold 700 for section headers. SemiBold 600 for card titles and buttons. Regular 400 for body text (line height 1.4–1.5). Must support iOS Dynamic Type and Android font scaling — never hardcode pixel sizes without respecting system font scale. Button text: uppercase, letterSpacing 0.5. Caption: 12px Regular. Muted: Slate 500 #64748B." +72,Sketch Hand-Drawn Mobile (Kalam + Patrick Hand),"Handwritten + Handwritten (Dual)","Kalam","Patrick Hand","sketch, hand-drawn, handwriting, human, imperfect, organic, paper, kalam, patrick hand, education, journal, creative","Journaling apps, prototype tools, children's picturebook apps, creative platforms, gamified puzzle apps","https://fonts.googleapis.com/css2?family=Kalam:wght@400;700&family=Patrick+Hand&display=swap","@import url('https://fonts.googleapis.com/css2?family=Kalam:wght@400;700&family=Patrick+Hand&display=swap');","fontFamily: { heading: ['Kalam', 'cursive'], body: ['Patrick Hand', 'cursive'] }","Dual handwritten stack: Kalam Bold (700) for all headings — high visual weight, felt-tip marker aesthetic, conveys intentional messiness. Patrick Hand Regular for all body text — highly legible at mobile sizes while remaining distinctly human. Scale: Heading 28–36px with lineHeight adjusted for descenders. Body 16–18px lineHeight 1.5. Labels 14px. Vary font sizes slightly between adjacent elements for spontaneous feel. Avoid alignment: 'center' for long body text — left-aligned reads more naturally. Both fonts require useFonts loading in Expo. Never use these fonts for financial figures or legal text." +73,Neumorphism Mobile (Plus Jakarta Sans + System),"Geometric Sans (System Fallback)","Plus Jakarta Sans","Plus Jakarta Sans","neumorphism, soft ui, monochromatic, cool grey, minimal, physical, depth, ceramic, system font, utility","Smart home controls, minimal tools, aesthetic dashboards, health monitors, brand showcase pages","https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,400;0,500;0,700;1,400","@import url('https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:ital,wght@0,400;0,500;0,700;1,400&display=swap');","fontFamily: { sans: ['Plus Jakarta Sans', 'sans-serif'] }","Single-family or System fallback: Plus Jakarta Sans Bold/Medium pairs beautifully with the monochromatic #E0E5EC surface — subtle geometry without competing with the depth effect. Heading: 24–32px Bold (700), letterSpacing -0.5 for modern premium feel. Body: 16px Medium (500), lineHeight 1.4. Caption: 12px Regular (400). Use Text Primary #3D4852 (7.5:1 contrast against #E0E5EC) for all primary text. Use Text Muted #6B7280 (4.6:1 contrast) for secondary text. Accent color #6C63FF only on active labels or focus indicators. Never use italic or thin weights — they lose legibility against the embossed background. System (SF Pro / Roboto) is an acceptable fallback for performance-sensitive implementations." diff --git a/src/ui-ux-pro-max/scripts/core.py b/src/ui-ux-pro-max/scripts/core.py index 8d0206548..2480a8bc8 100755 --- a/src/ui-ux-pro-max/scripts/core.py +++ b/src/ui-ux-pro-max/scripts/core.py @@ -117,7 +117,7 @@ def __init__(self, k1=1.5, b=0.75): def tokenize(self, text): """Lowercase, split, remove punctuation, filter short words""" text = re.sub(r'[^\w\s]', ' ', str(text).lower()) - return [w for w in text.split() if len(w) > 2] + return [w for w in text.split() if len(w) >= 2] def fit(self, documents): """Build BM25 index from documents""" diff --git a/src/ui-ux-pro-max/scripts/search.py b/src/ui-ux-pro-max/scripts/search.py index d782d315f..13da28bf5 100644 --- a/src/ui-ux-pro-max/scripts/search.py +++ b/src/ui-ux-pro-max/scripts/search.py @@ -85,7 +85,7 @@ def format_output(result): # Print persistence confirmation if args.persist: - project_slug = args.project_name.lower().replace(' ', '-') if args.project_name else "default" + project_slug = (args.project_name or args.query).lower().replace(' ', '-') print("\n" + "=" * 60) print(f"✅ Design system persisted to design-system/{project_slug}/") print(f" 📄 design-system/{project_slug}/MASTER.md (Global Source of Truth)") From a3dea0d72fd44396a116459d88872f15418e4d91 Mon Sep 17 00:00:00 2001 From: xiaolai Date: Mon, 22 Jun 2026 01:54:21 +0800 Subject: [PATCH 12/50] fix: replace execSync template string with execFileSync array form (#283) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit execSync with a backtick template string creates a shell-expansion surface. Although all three variables (generateScript, DESIGN_TOKENS_JSON, DESIGN_TOKENS_CSS) are currently hardcoded constants, the pattern is fragile — any future substitution of user-controlled data would create shell injection. Replace with execFileSync('node', [...args]) to eliminate the shell entirely and make the boundary explicit. Co-authored-by: claude[bot] Co-authored-by: Claude Code --- .claude/skills/brand/scripts/sync-brand-to-tokens.cjs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.claude/skills/brand/scripts/sync-brand-to-tokens.cjs b/.claude/skills/brand/scripts/sync-brand-to-tokens.cjs index 86c19e880..e7bc17117 100644 --- a/.claude/skills/brand/scripts/sync-brand-to-tokens.cjs +++ b/.claude/skills/brand/scripts/sync-brand-to-tokens.cjs @@ -11,7 +11,7 @@ const fs = require('fs'); const path = require('path'); -const { execSync } = require('child_process'); +const { execFileSync } = require('child_process'); // Paths const BRAND_GUIDELINES = 'docs/brand-guidelines.md'; @@ -250,7 +250,7 @@ function main() { const generateScript = path.resolve(process.cwd(), GENERATE_TOKENS_SCRIPT); if (fs.existsSync(generateScript)) { try { - execSync(`node ${generateScript} --config ${DESIGN_TOKENS_JSON} -o ${DESIGN_TOKENS_CSS}`, { + execFileSync('node', [generateScript, '--config', DESIGN_TOKENS_JSON, '-o', DESIGN_TOKENS_CSS], { cwd: process.cwd(), stdio: 'inherit' }); From fb1fc58bf9d67d44b89b45761a81f7420cd7aab4 Mon Sep 17 00:00:00 2001 From: Ray Tien Date: Mon, 22 Jun 2026 04:58:29 +0800 Subject: [PATCH 13/50] feat(nuxt-ui): update stack data to v4 (#345) Breaking changes fixed: - Row 8/9: icon format corrected from 'lucide:home' (v3) to 'i-lucide-home' (v4 Iconify i-prefix) - Row 18: useOverlay API updated from .open(Component, {props}) to .create(Component).open({props}) New v4 guidelines added (rows 51-70): - Auto-registered modules: do not re-add @nuxt/icon @nuxt/fonts @nuxtjs/color-mode - Official nuxi init templates for project bootstrapping - Local Iconify JSON install for SSR reliability - Global icon overrides via appConfig.ui.icons - New form components: UFileUpload, UInputDate, UInputTags, UColorPicker - New data components: UTree, UMarquee - UContextMenu for right-click menus - Awaiting overlay result Promise for confirmation dialogs - UCommandPalette grouped items and extractShortcuts - UHeader/UFooter/UPageAside layout components - ClientOnly pattern for color mode hydration safety - Generated theme file (.nuxt/ui/) for slot discovery - defineShortcuts whenever condition guard - UApp locale prop for i18n (50+ built-in locales) Sync cli/assets to match src. --- cli/assets/data/stacks/nuxt-ui.csv | 26 ++++++++++++++++++++--- src/ui-ux-pro-max/data/stacks/nuxt-ui.csv | 26 ++++++++++++++++++++--- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/cli/assets/data/stacks/nuxt-ui.csv b/cli/assets/data/stacks/nuxt-ui.csv index 7146e8483..caf4ff6a5 100644 --- a/cli/assets/data/stacks/nuxt-ui.csv +++ b/cli/assets/data/stacks/nuxt-ui.csv @@ -6,8 +6,8 @@ No,Category,Guideline,Description,Do,Don't,Code Good,Code Bad,Severity,Docs URL 5,Components,Use semantic color props,Use semantic colors like primary secondary error,color="primary" color="error",Hardcoded colors,"","",Medium,https://ui.nuxt.com/docs/getting-started/theme/design-system 6,Components,Use variant prop for styling,Nuxt UI provides solid outline soft subtle ghost link variants,variant="soft" variant="outline",Custom button classes,"","",Medium,https://ui.nuxt.com/docs/components/button 7,Components,Use size prop consistently,Components support xs sm md lg xl sizes,size="sm" size="lg",Arbitrary sizing classes,"","",Low,https://ui.nuxt.com/docs/components/button -8,Icons,Use icon prop with Iconify format,Nuxt UI supports Iconify icons via icon prop,icon="lucide:home" icon="heroicons:user",i-lucide-home format,"","",Medium,https://ui.nuxt.com/docs/getting-started/integrations/icons/nuxt -9,Icons,Use leadingIcon and trailingIcon,Position icons with dedicated props for clarity,leadingIcon="lucide:plus" trailingIcon="lucide:arrow-right",Manual icon positioning,"","Add",Low,https://ui.nuxt.com/docs/components/button +8,Icons,Use i-{collection}-{name} format for icons,Nuxt UI v4 uses Iconify i-prefix format — lucide:home is v3 legacy,i-lucide-home i-heroicons-user format,lucide:home format (v3 syntax),"","",High,https://ui.nuxt.com/docs/getting-started/installation/nuxt +9,Icons,Use leadingIcon and trailingIcon props,Position icons with dedicated props for clarity,leadingIcon="i-lucide-plus" trailingIcon="i-lucide-arrow-right",Manual icon positioning or slots,"","Add",Low,https://ui.nuxt.com/docs/components/button 10,Theming,Configure colors in app.config.ts,Runtime color configuration without restart,ui.colors.primary in app.config.ts,Hardcoded colors in components,"defineAppConfig({ ui: { colors: { primary: 'blue' } } })","",High,https://ui.nuxt.com/docs/getting-started/theme/design-system 11,Theming,Use @theme directive for custom colors,Define design tokens in CSS with Tailwind @theme,@theme { --color-brand-500: #xxx },Inline color definitions,@theme { --color-brand-500: #ef4444; },:style="{ color: '#ef4444' }",Medium,https://ui.nuxt.com/docs/getting-started/theme/design-system 12,Theming,Extend semantic colors in nuxt.config,Register new colors like tertiary in theme.colors,theme.colors array in ui config,Use undefined colors,"ui: { theme: { colors: ['primary', 'tertiary'] } }"," without config",Medium,https://ui.nuxt.com/docs/getting-started/theme/design-system @@ -16,7 +16,7 @@ No,Category,Guideline,Description,Do,Don't,Code Good,Code Bad,Severity,Docs URL 15,Forms,Handle form submit with @submit,UForm emits submit event with validated data,@submit handler on UForm,@click on submit button,"","",Medium,https://ui.nuxt.com/docs/components/form 16,Forms,Use validateOn prop for validation timing,Control when validation triggers (blur change input),validateOn="['blur']" for performance,Always validate on input,""," (validates on every keystroke)",Low,https://ui.nuxt.com/docs/components/form 17,Overlays,Use v-model:open for overlay control,Modal Slideover Drawer use v-model:open,v-model:open for controlled state,Manual show/hide logic,"",,Medium,https://ui.nuxt.com/docs/components/modal -18,Overlays,Use useOverlay composable for programmatic overlays,Open overlays programmatically without template refs,useOverlay().open(MyModal),Template ref and manual control,"const overlay = useOverlay(); overlay.open(MyModal, { props })","const modal = ref(); modal.value.open()",Medium,https://ui.nuxt.com/docs/components/modal +18,Overlays,Use useOverlay composable for programmatic overlays,Open overlays programmatically — v4 API is create().open() not open(Component),overlay.create(Component).open({ props }) pattern,v3 overlay.open(Component) pattern (removed in v4),"const modal = overlay.create(MyModal); const { result } = modal.open({ title: 'Confirm' })","overlay.open(MyModal, { props: { title: 'Confirm' } })",High,https://ui.nuxt.com/docs/components/modal 19,Overlays,Use title and description props,Built-in header support for overlays,title="Confirm" description="Are you sure?",Manual header content,"","",Low,https://ui.nuxt.com/docs/components/modal 20,Dashboard,Use UDashboardSidebar for navigation,Provides collapsible resizable sidebar with mobile support,UDashboardSidebar with header default footer slots,Custom sidebar implementation,,