Agent skill
policyengine-design
PolicyEngine design system — tokens, typography, colors, charts, and branding for all project types. Triggers: "brand colors", "design tokens", "PolicyEngine colors", "typography", "font", "color palette", "CSS variables", "design system", "branding guidelines"
Install this agent skill to your Project
npx add-skill https://github.com/PolicyEngine/policyengine-claude/tree/main/skills/documentation/policyengine-design-skill
SKILL.md
PolicyEngine design system
Single source of truth for PolicyEngine's visual identity. Design tokens are defined as CSS custom properties in @policyengine/ui-kit/theme.css. Every frontend project imports this single CSS file.
When to use which format:
| Context | Approach | Example |
|---|---|---|
| React components | Tailwind semantic classes | className="bg-primary text-foreground" |
| Brand palette | Tailwind direct classes | className="bg-teal-500 text-gray-600" |
| Recharts (SVG) | CSS vars directly in fill/stroke | fill="var(--chart-1)" |
| Inline styles | CSS vars | style={{ color: "var(--primary)" }} |
| Python (Plotly) | Hex with CSS var comment | TEAL = "#319795" # --chart-1 |
<meta> tags, static HTML |
Hex values with CSS var name in comment | content="#319795" |
Python has no CSS runtime, so hex values are acceptable — but always comment with the CSS var name so values stay traceable to the design system.
The ui-kit theme
Install:
bun install @policyengine/ui-kit
Import the theme CSS in your globals.css:
@import "tailwindcss";
@import "@policyengine/ui-kit/theme.css";
The first line enables Tailwind v4 utilities. The second provides all PE design tokens, @theme configuration, and base styles. Both are required — see policyengine-ui-kit-consumer-skill for details.
Source: PolicyEngine/policyengine-ui-kit/src/theme/tokens.css
The theme CSS has three layers:
:root— shadcn/ui semantic variables (--primary,--background,--chart-1, etc.)@theme inline— Bridges:rootvars to Tailwind utilities (bg-primary,text-foreground)@theme— Brand palette (bg-teal-500,text-gray-600), font sizes, spacing, breakpoints
Colors
Primary — teal
| Token | Hex | Tailwind class | Usage |
|---|---|---|---|
teal-500 |
#319795 |
bg-teal-500 |
Main brand color — charts, highlights |
teal-400 |
#38B2AC |
bg-teal-400 |
Lighter interactive elements |
teal-600 |
#2C7A7B |
bg-teal-600 / bg-primary |
Hover state, buttons |
teal-700 |
#285E61 |
bg-teal-700 |
Active/pressed state |
teal-50 |
#E6FFFA |
bg-teal-50 |
Tinted backgrounds |
teal-800 |
#234E52 |
bg-teal-800 |
Dark text on light teal |
Semantic (shadcn/ui)
| Role | CSS variable | Tailwind class | Hex |
|---|---|---|---|
| Primary | --primary |
bg-primary |
#2C7A7B |
| Background | --background |
bg-background |
#FFFFFF |
| Foreground | --foreground |
text-foreground |
#000000 |
| Muted | --muted |
bg-muted |
#F2F4F7 |
| Muted foreground | --muted-foreground |
text-muted-foreground |
#6B7280 |
| Border | --border |
border-border |
#E2E8F0 |
| Destructive | --destructive |
bg-destructive |
#EF4444 |
| Card | --card |
bg-card |
#FFFFFF |
| Ring | --ring |
ring-ring |
#319795 |
Charts
| CSS variable | Tailwind class | Hex | Usage |
|---|---|---|---|
--chart-1 |
fill-chart-1 |
#319795 |
Primary series (teal) |
--chart-2 |
fill-chart-2 |
#0EA5E9 |
Secondary series (blue) |
--chart-3 |
fill-chart-3 |
#285E61 |
Tertiary series (dark teal) |
--chart-4 |
fill-chart-4 |
#026AA2 |
Quaternary series (dark blue) |
--chart-5 |
fill-chart-5 |
#6B7280 |
Quinary series (gray) |
Additional semantic colors
| Color | Hex | Tailwind class |
|---|---|---|
| Success | #22C55E |
text-success / bg-success |
| Error | #EF4444 |
text-destructive / bg-destructive |
| Warning | #FEC601 |
text-warning / bg-warning |
| Info | #1890FF |
text-info / bg-info |
Gray scale
| Token | Hex | Tailwind class |
|---|---|---|
gray-50 |
#F9FAFB |
bg-gray-50 |
gray-100 |
#F2F4F7 |
bg-gray-100 |
gray-200 |
#E2E8F0 |
bg-gray-200 |
gray-500 |
#6B7280 |
text-gray-500 |
gray-600 |
#4B5563 |
text-gray-600 |
gray-700 |
#344054 |
text-gray-700 |
Typography
Font families
Two font families only: Inter + JetBrains Mono. No serif fonts, no Roboto, no Public Sans.
| Context | Font | CSS variable | Tailwind |
|---|---|---|---|
| Everything (UI, charts, blog, tools) | Inter | --font-sans |
font-sans |
| Code | JetBrains Mono | --font-mono |
font-mono |
Loading Inter:
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
Font sizes
| Tailwind class | Size | Usage |
|---|---|---|
text-xs |
12px | Small labels, captions |
text-sm |
14px | Body text, form labels |
text-base |
16px | Large body text |
text-lg |
18px | Subheadings |
text-xl |
20px | Section titles |
text-2xl |
24px | Page titles |
text-3xl |
28px | Large headings |
Sentence case
All UI text uses sentence case — capitalize only the first word and proper nouns.
- "Your saved policies" not "Your Saved Policies"
- "Tax liability by income" not "Tax Liability by Income"
- Proper nouns stay capitalized: "Child Tax Credit", "PolicyEngine", "California"
Spacing
Standard Tailwind spacing classes (p-4, gap-2, m-6) use the default Tailwind scale. Named spacing tokens:
| Token | Value | Tailwind class |
|---|---|---|
| Header | 58px | h-header |
| Sidebar | 280px | w-sidebar |
| Content | 976px | max-w-content |
Border radius
| Tailwind class | Value |
|---|---|
rounded-sm |
4px |
rounded-md |
6px |
rounded-lg |
8px |
Chart branding
Recharts (React tools)
import { BarChart, Bar, XAxis, YAxis, Tooltip } from "recharts";
<BarChart data={data}>
<XAxis dataKey="name" niceTicks="snap125" domain={["auto", "auto"]} style={{ fontFamily: "var(--font-sans)" }} />
<YAxis niceTicks="snap125" domain={["auto", "auto"]} style={{ fontFamily: "var(--font-sans)" }} />
<Tooltip separator=": " />
<Bar dataKey="value" fill="var(--chart-1)" />
</BarChart>
SVG fill and stroke attributes accept var() directly — no helper function needed.
Plotly (Python)
import plotly.graph_objects as go
TEAL = "#319795" # --chart-1
CHART_FONT = "Inter"
LOGO_URL = "https://raw.githubusercontent.com/PolicyEngine/policyengine-app-v2/main/app/public/assets/logos/policyengine/teal.png"
def format_fig(fig):
fig.update_layout(
font=dict(family=CHART_FONT, color="black", size=14),
plot_bgcolor="white",
paper_bgcolor="white",
template="plotly_white",
height=600,
width=800,
margin=dict(l=60, r=40, t=40, b=60),
modebar=dict(bgcolor="rgba(0,0,0,0)", color="rgba(0,0,0,0)"),
)
fig.add_layout_image(dict(
source=LOGO_URL,
xref="paper", yref="paper",
x=1.0, y=-0.10,
sizex=0.10, sizey=0.10,
xanchor="right", yanchor="bottom",
))
return fig
Chart color conventions
| Meaning | CSS variable | Hex |
|---|---|---|
| Positive / bonus / gains | --chart-1 |
#319795 |
| Negative / penalty / losses | --chart-5 or --destructive |
#6B7280 or #EF4444 |
| Neutral / baseline | --border |
#E2E8F0 |
| Multi-series | --chart-1 through --chart-5 |
See chart table above |
Inverted metrics (taxes): When a positive delta means bad (higher taxes), use invertDelta logic to show "Penalty" label and swap colors.
Chart typography
- Axis labels and titles:
var(--font-sans), 14px - Tick labels:
var(--font-sans), 12px - Legend:
var(--font-sans), horizontal, above chart
Favicon
Every PolicyEngine dashboard must include a favicon. The ui-kit exports the logo as a favicon-ready SVG:
- Copy:
cp node_modules/@policyengine/ui-kit/src/assets/logos/policyengine/teal-square.svg public/favicon.svg - Add to
layout.tsxmetadata:tsxexport const metadata: Metadata = { // ... icons: { icon: '/favicon.svg' }, };
The ui-kit also exports logos.favicon (SVG) and logos.faviconPng (PNG fallback) for programmatic use.
Logos
All logo files in policyengine-app-v2/app/public/assets/logos/policyengine/:
| File | Background | Format |
|---|---|---|
teal.png / teal.svg |
Light | Wide |
teal-square.png / teal-square.svg |
Light | Square (for chart watermarks) |
white.png / white.svg |
Dark | Wide |
white-square.svg |
Dark | Square |
Raw URL for charts:
https://raw.githubusercontent.com/PolicyEngine/policyengine-app-v2/main/app/public/assets/logos/policyengine/teal.png
Using tokens by project type
| Project type | Token source | Font setup |
|---|---|---|
| Standalone tool | @import "@policyengine/ui-kit/theme.css" |
Google Fonts: Inter |
| app-v2 | import { colors } from '@/designTokens' |
Built-in (Mantine + Inter) |
| Python chart | Hardcode or load tokens.json from @policyengine/design-system |
Inter for Plotly |
| Blog HTML | Hardcode from token values | Google Fonts: Inter |
Accessibility
- Teal
#319795on white passes WCAG AA for large text (3.8:1) text-foreground(#000000) on white passes AAA (21:1)text-muted-foreground(#6B7280) on white passes AA (4.6:1)- Never rely on color alone — use labels, patterns, or position to convey meaning
- Ensure chart data series are distinguishable in grayscale
Related skills
policyengine-interactive-tools-skill— Building standalone tools that use these tokenspolicyengine-vercel-deployment-skill— Deploying standalone toolspolicyengine-app-skill— app-v2 developmentpolicyengine-writing-skill— Content style (complements visual style)
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
policyengine-healthcare
Healthcare program modeling in PolicyEngine-US — Medicaid, ACA marketplace, CHIP, and Medicare. Covers encoding rules, running analyses, and navigating the unique complexity of US healthcare programs. Triggers: "healthcare", "health insurance", "Medicaid", "ACA", "CHIP", "Medicare", "marketplace", "premium tax credit", "APTC", "PTC", "SLCSP", "benchmark plan", "rating area", "age curve", "family tier", "coverage gap", "Medicaid expansion", "MAGI", "medicaid_magi", "aca_magi", "medicaid_income_level", "medicaid_category", "enrollment", "takeup", "take-up", "per capita", "CSR", "cost sharing", "insurance premium", "second lowest silver", "required contribution percentage", "42 CFR", "IRC 36B", "categorical eligibility", "expansion adult", "healthcare reform", "healthcare analysis", "health policy".
policyengine-us
ALWAYS LOAD THIS SKILL FIRST before writing any PolicyEngine-US code. Contains the correct API patterns for household calculations and population simulations using the new policyengine package. Covers US federal and state taxes/benefits. Triggers: "what would", "how much would a", "benefit be", "eligible for", "qualify for", "single parent", "married couple", "family of", "household of", "if they earn", "earning $", "making $", "calculate benefits", "calculate taxes", "benefit for a", "what would I get", "what is the maximum", "what is the rate", "poverty line", "income limit", "benefit amount", "maximum benefit", "compare states", "TANF", "SNAP", "EITC", "CTC", "SSI", "WIC", "Section 8", "Medicaid", "ACA", "child tax credit", "earned income", "supplemental security", "housing voucher", "microsimulation", "population", "reform", "policy impact", "budgetary", "decile".
policyengine-uk
ALWAYS LOAD THIS SKILL FIRST before writing any PolicyEngine-UK code. Contains the correct API patterns for household calculations and population simulations using the new policyengine package (not policyengine_uk directly). Triggers: "what would", "how much would a", "benefit be", "eligible for", "qualify for", "single parent", "married couple", "family of", "household of", "if they earn", "with income of", "earning £", "making £", "calculate benefits", "calculate taxes", "benefit for a", "tax for a", "what would I get", "what would they get", "what is the rate", "what is the threshold", "personal allowance", "maximum benefit", "income limit", "benefit amount", "how much is", "Universal Credit", "child benefit", "pension credit", "housing benefit", "council tax", "income tax", "national insurance", "JSA", "ESA", "PIP", "disability living allowance", "working tax credit", "child tax credit", "Scotland", "Wales", "UK", "microsimulation", "population", "reform", "policy impact", "budgetary", "decile".
policyengine-canada
ALWAYS LOAD THIS SKILL FIRST before writing any PolicyEngine-Canada code. Contains Canadian federal and provincial tax/benefit rules for household calculations. IMPORTANT: PolicyEngine-Canada does NOT have representative population microdata. Do NOT attempt microsimulation or population-level estimates for Canada. Only provide household-level analysis (single-family impacts, eligibility, benefit amounts). Triggers: "what would", "how much would a", "benefit be", "eligible for", "qualify for", "single parent", "married couple", "family of", "household of", "if they earn", "earning $", "making $", "calculate benefits", "calculate taxes", "benefit for a", "what would I get", "what is the maximum", "what is the rate", "income limit", "benefit amount", "maximum benefit", "compare provinces", "CCB", "Canada Child Benefit", "GST credit", "HST credit", "GST/HST", "OAS", "Old Age Security", "GIS", "Guaranteed Income Supplement", "CWB", "Canada Workers Benefit", "EI", "Employment Insurance", "CPP", "Canada Pension Plan", "RRSP", "TFSA", "Ontario Child Benefit", "OCB", "Ontario Trillium Benefit", "OTB", "BC Climate Action", "Alberta Child Benefit", "Quebec", "CRA", "Canada Revenue Agency", "Canadian", "Canada", "Ontario", "British Columbia", "Alberta", "Saskatchewan", "Manitoba", "Nova Scotia", "New Brunswick", "PEI", "Newfoundland", "Yukon", "NWT", "Nunavut", "provincial tax", "federal tax Canada".
policyengine-ui-kit-consumer
This skill should be used when setting up a new project that uses @policyengine/ui-kit, debugging CSS or styling issues in a consumer app, or when Tailwind utility classes are not being generated. Also use when creating globals.css, configuring PostCSS, or troubleshooting "no styles", "no spacing", or "no layout" problems. Triggers: "ui-kit import", "globals.css setup", "Tailwind not working", "styles not applying", "utility classes missing", "setup ui-kit", "PostCSS config", "no styling", "CSS broken", "import ui-kit", "theme.css", "no layout", "no spacing", "@tailwindcss/postcss"
policyengine-tailwind-shadcn
Tailwind CSS v4 + shadcn/ui integration patterns for PolicyEngine frontend projects. Covers @theme namespaces, CSS variable conventions, SVG var() usage, and common mistakes. Triggers: "Tailwind v4", "@theme", "shadcn", "CSS variables", "design tokens CSS", "theme.css", "@theme inline"
Didn't find tool you were looking for?