Workflow

When triggered, always:

  1. Read THIS skill’s DESIGN.md for the sidebar-specific overrides.

  2. Read ~/.claude/skills/openclaw-dcc/DESIGN.md for inherited base tokens (colors, semantic palette, component types). The sidebar inherits but constrains.

  3. CRITICAL CONSTRAINTS — failing any of these breaks production:

    • NO <link> to external CDN — HubSpot UI Extensions iframe sandbox blocks it. Verify by grepping output for cdn.jsdelivr or fonts.googleapis — if found, FAIL.
    • NO Google Fonts CDN — use system stack: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif. Mono fallback: ui-monospace, "SF Mono", Consolas, monospace.
    • NO Chart.js CDN — use inline SVG sparklines (path elements with stroke). Skip activity bar charts entirely or render them as inline SVG.
    • NO fetch() to external URLs — only relative same-origin paths via hubspot.fetch() (the wrapper).
    • All CSS inline — either inside a single <style> block in the head, OR via style="" attributes on elements. NO <link rel="stylesheet"> to external paths.
    • All JS inline — single <script> block, no <script src=> to externals.
    • max-width 350px — every container, panel, table, button must respect this. Test by setting body max-width: 350px during dev.
  4. Component shrink rules (from openclaw-dcc full → sidebar compact):

    • Score ring: 148px → 100px (still SVG stroke-dashoffset, just smaller)
    • KPI tiles: 14px padding → 10px padding, font-size 22px value → 16px value
    • Tabs: horizontal scroll with snap points (overflow-x: auto), abbreviate labels (“End Buyers” → “EBuy”)
    • Action panel: moves below content (not right rail) — sidebar is too narrow for 3-col
    • Tables: 2-3 columns max, mono shrunk to 11px, hide secondary columns
    • Channel cards: stack vertically (1-col instead of 2-col)
    • Calendar: simplified — list view of upcoming dates instead of full month grid
    • Timeline (Responses): denser, smaller font, condensed timestamps (“14m ago” → “14m”)
  5. Inline SVG sparklines (replacing Chart.js):

    <svg viewBox="0 0 100 24" width="100%" height="24" preserveAspectRatio="none">
      <path d="M0,18 L20,15 L40,12 L60,8 L80,5 L100,3" stroke="#5b21b6" stroke-width="1.5" fill="none"/>
      <path d="M0,18 L20,15 L40,12 L60,8 L80,5 L100,3 L100,24 L0,24 Z" fill="rgba(91,33,182,.08)"/>
    </svg>
  6. Quality gates before delivering:

    • max-width 350px enforced
    • Zero external CDN links
    • System font stack only (no Google Fonts)
    • No Chart.js — inline SVG sparklines used
    • All 7 tabs collapsed to horizontal-scroll nav
    • SVG ring still uses stroke-dashoffset
    • Counter animations still rAF
    • Color tokens match openclaw-dcc parent

CSP Compliance Checklist

Run this checklist on every output:

✓ grep -c 'fonts.googleapis' output.html  → must be 0
✓ grep -c 'cdn.jsdelivr' output.html      → must be 0
✓ grep -c '<link rel="stylesheet"' output → must be 0 (or only relative)
✓ grep -c '<script src=' output.html      → must be 0 (or only relative)
✓ grep -E 'fetch\([\"`](https?:|//)' out  → must be 0

Trigger Examples

  • “Generate the HubSpot sidebar version of the DCC for the deal card extension” → 350px file
  • “Compact DCC for HubSpot, just the readiness tab” → 350px single-tab variant
  • “DispoControlCenter.tsx React component for HubSpot UI Extension” → React + sidebar constraints + 21st.dev compound workflow

Reference Materials

  • DESIGN.md (this directory) — sidebar-specific overrides
  • ~/.claude/skills/openclaw-dcc/DESIGN.md — inherited base
  • ~/.openclaw/hubspot-projects/openclaw-betterfiles/OpenClawBetterFiles/src/app/cards/DispoControlCenter.tsx — current production sidebar (for context)
  • HubSpot UI Extensions docs: CSP rules

Anti-Slop for Sidebar Specifically

  • ❌ Don’t use system-ui as ONLY font with no fallbacks — chain: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif
  • ❌ Don’t try to fit 4 KPI tiles in one row at 350px — stack to 2-col max
  • ❌ Don’t render Chart.js with empty data state — use inline SVG sparkline placeholder
  • ❌ Don’t use absolute positioning for the action panel — use relative + flow
  • ✅ Embed any required graphics as inline SVG (no to external)