---
name: policyengine-design
description: PolicyEngine visual identity - colors, fonts, logos, and branding for web apps, calculators, charts, and research
---
# PolicyEngine Design System
PolicyEngine's visual identity and branding guidelines for creating consistent user experiences across web apps, calculators, charts, and research outputs.
## For Users 👥
### PolicyEngine Visual Identity
**Brand colors:**
- **Teal** (#39C6C0) - Primary accent color (buttons, highlights, interactive elements)
- **Blue** (#2C6496) - Secondary color (links, charts, headers)
**Typography:**
- **Charts:** Roboto Serif
- **Web app:** System fonts (sans-serif)
- **Streamlit apps:** Default sans-serif
**Logo:**
- Used in charts (bottom right)
- Blue version for light backgrounds
- White version for dark backgrounds
### Recognizing PolicyEngine Content
**You can identify PolicyEngine content by:**
- Teal accent color (#39C6C0) on buttons and interactive elements
- Blue (#2C6496) in charts and links
- Roboto Serif font in charts
- PolicyEngine logo in chart footer
- Clean, minimal white backgrounds
- Data-focused, quantitative presentation
## For Analysts 📊
### Chart Branding
When creating charts for PolicyEngine analysis, follow these guidelines:
#### Color Palette
**Primary colors:**
```python
TEAL_ACCENT = "#39C6C0" # Primary color (teal)
BLUE_PRIMARY = "#2C6496" # Secondary color (blue)
DARK_GRAY = "#616161" # Text color
```
**Extended palette:**
```python
# Blues
BLUE = "#2C6496"
BLUE_LIGHT = "#D8E6F3"
BLUE_PRESSED = "#17354F"
BLUE_98 = "#F7FAFD"
DARK_BLUE_HOVER = "#1d3e5e"
DARKEST_BLUE = "#0C1A27"
# Teals
TEAL_ACCENT = "#39C6C0"
TEAL_LIGHT = "#F7FDFC"
TEAL_PRESSED = "#227773"
# Grays
DARK_GRAY = "#616161"
GRAY = "#808080"
MEDIUM_LIGHT_GRAY = "#BDBDBD"
MEDIUM_DARK_GRAY = "#D2D2D2"
LIGHT_GRAY = "#F2F2F2"
# Accents
WHITE = "#FFFFFF"
BLACK = "#000000"
DARK_RED = "#b50d0d" # For negative values
```
**See current colors:**
```bash
cat policyengine-app/src/style/colors.js
```
#### Plotly Chart Formatting
**Standard PolicyEngine chart:**
```python
import plotly.graph_objects as go
def format_fig(fig):
"""Format chart with PolicyEngine branding."""
fig.update_layout(
# Typography
font=dict(
family="Roboto Serif",
color="black"
),
# Background
plot_bgcolor="white",
template="plotly_white",
# Margins (leave room for logo)
margin=dict(
l=50,
r=100,
t=50,
b=120,
pad=4
),
# Chart size
height=600,
width=800,
)
# Add PolicyEngine logo (bottom right)
fig.add_layout_image(
dict(
source="https://raw.githubusercontent.com/PolicyEngine/policyengine-app/master/src/images/logos/policyengine/blue.png",
xref="paper",
yref="paper",
x=1.0,
y=-0.10,
sizex=0.10,
sizey=0.10,
xanchor="right",
yanchor="bottom"
)
)
# Clean modebar
fig.update_layout(
modebar=dict(
bgcolor="rgba(0,0,0,0)",
color="rgba(0,0,0,0)"
)
)
return fig
# Usage
fig = go.Figure()
fig.add_trace(go.Scatter(x=x_data, y=y_data, line=dict(color=TEAL_ACCENT)))
fig = format_fig(fig)
```
**Current implementation:**
```bash
# See format_fig in action
cat givecalc/ui/visualization.py
cat policyengine-app/src/pages/policy/output/...
```
#### Chart Colors
**For line charts:**
- Primary line: Teal (#39C6C0) or Blue (#2C6496)
- Background lines: Light gray (rgb(180, 180, 180))
- Markers: Teal with 70% opacity
**For bar charts:**
- Positive values: Teal (#39C6C0)
- Negative values: Dark red (#b50d0d)
- Neutral: Gray
**For multiple series:**
Use variations of blue and teal, or discrete color scale:
```python
colors = ["#2C6496", "#39C6C0", "#17354F", "#227773"]
```
#### Typography
**Charts:**
```python
font=dict(family="Roboto Serif", size=14, color="black")
```
**Axis labels:**
```python
xaxis=dict(
title=dict(text="Label", font=dict(size=14)),
tickfont=dict(size=12)
)
```
**Load Roboto font:**
```python
# In Streamlit apps
st.markdown("""
""", unsafe_allow_html=True)
```
### Streamlit App Branding
**Streamlit configuration (.streamlit/config.toml):**
```toml
[theme]
base = "light"
primaryColor = "#39C6C0" # Teal accent
backgroundColor = "#FFFFFF" # White background
secondaryBackgroundColor = "#F7FDFC" # Teal light
textColor = "#616161" # Dark gray
[client]
toolbarMode = "minimal"
```
**Current implementation:**
```bash
cat givecalc/.streamlit/config.toml
cat salt-amt-calculator/.streamlit/config.toml # Other calculators
```
### Logo Usage
**Logo URLs:**
```python
# Blue logo (for light backgrounds)
LOGO_BLUE = "https://raw.githubusercontent.com/PolicyEngine/policyengine-app/master/src/images/logos/policyengine/blue.png"
# White logo (for dark backgrounds)
LOGO_WHITE = "https://raw.githubusercontent.com/PolicyEngine/policyengine-app/master/src/images/logos/policyengine/white.png"
# SVG versions (scalable)
LOGO_BLUE_SVG = "https://raw.githubusercontent.com/PolicyEngine/policyengine-app/master/src/images/logos/policyengine/blue.svg"
LOGO_WHITE_SVG = "https://raw.githubusercontent.com/PolicyEngine/policyengine-app/master/src/images/logos/policyengine/white.svg"
```
**Logo placement in charts:**
- Bottom right corner
- 10% of chart width
- Slightly below bottom edge (y=-0.10)
**Current logos:**
```bash
ls policyengine-app/src/images/logos/policyengine/
```
### Complete Example: Branded Chart
```python
import plotly.graph_objects as go
# PolicyEngine colors
TEAL_ACCENT = "#39C6C0"
BLUE_PRIMARY = "#2C6496"
# Create chart
fig = go.Figure()
# Add data
fig.add_trace(go.Scatter(
x=incomes,
y=taxes,
mode='lines',
name='Tax liability',
line=dict(color=TEAL_ACCENT, width=3)
))
# Apply PolicyEngine branding
fig.update_layout(
# Typography
font=dict(family="Roboto Serif", size=14, color="black"),
# Title and labels
title="Tax liability by income",
xaxis_title="Income",
yaxis_title="Tax ($)",
# Formatting
xaxis_tickformat="$,.0f",
yaxis_tickformat="$,.0f",
# Appearance
plot_bgcolor="white",
template="plotly_white",
# Size and margins
height=600,
width=800,
margin=dict(l=50, r=100, t=50, b=120, pad=4)
)
# Add logo
fig.add_layout_image(
dict(
source="https://raw.githubusercontent.com/PolicyEngine/policyengine-app/master/src/images/logos/policyengine/blue.png",
xref="paper",
yref="paper",
x=1.0,
y=-0.10,
sizex=0.10,
sizey=0.10,
xanchor="right",
yanchor="bottom"
)
)
# Show
fig.show()
```
## For Contributors 💻
### Brand Assets
**Repository:** PolicyEngine/policyengine-app-v2 (current), PolicyEngine/policyengine-app (legacy)
**Logo files:**
```bash
# Logos in app (both v1 and v2 use same logos)
ls policyengine-app/src/images/logos/policyengine/
# - blue.png - For light backgrounds
# - white.png - For dark backgrounds
# - blue.svg - Scalable blue logo
# - white.svg - Scalable white logo
# - banners/ - Banner variations
# - profile/ - Profile/avatar versions
```
**Access logos:**
```bash
# View logo files (v1 repo has the assets)
cd policyengine-app/src/images/logos/policyengine/
ls -la
```
### Color Definitions
**⚠️ IMPORTANT: App V2 Transition**
PolicyEngine is transitioning to policyengine-app-v2 with updated design tokens. Use app-v2 colors for new projects.
**Current colors (policyengine-app-v2):**
```typescript
// policyengine-app-v2/app/src/designTokens/colors.ts
// Primary (teal) - 50 to 900 scale
primary[500]: "#319795" // Main teal
primary[400]: "#38B2AC" // Lighter teal
primary[600]: "#2C7A7B" // Darker teal
// Blue scale
blue[700]: "#026AA2" // Primary blue
blue[500]: "#0EA5E9" // Lighter blue
// Gray scale
gray[700]: "#344054" // Dark text
gray[100]: "#F2F4F7" // Light backgrounds
// Semantic
success: "#22C55E"
warning: "#FEC601"
error: "#EF4444"
// Background
background.primary: "#FFFFFF"
background.secondary: "#F5F9FF"
// Text
text.primary: "#000000"
text.secondary: "#5A5A5A"
```
**To see current design tokens:**
```bash
cat policyengine-app-v2/app/src/designTokens/colors.ts
cat policyengine-app-v2/app/src/styles/colors.ts # Mantine integration
```
**Legacy colors (policyengine-app - still used in some projects):**
```javascript
// policyengine-app/src/style/colors.js
TEAL_ACCENT = "#39C6C0" // Old teal (slightly different from v2)
BLUE = "#2C6496" // Old blue
DARK_GRAY = "#616161" // Old dark gray
```
**To see legacy colors:**
```bash
cat policyengine-app/src/style/colors.js
```
**Usage in React (app-v2):**
```typescript
import { colors } from 'designTokens';
Description
``` **Current colors:** ```bash cat policyengine-app/src/style/colors.js ``` ## Visual Guidelines ### Chart Design Principles 1. **Minimal decoration** - Let data speak 2. **White backgrounds** - Clean, print-friendly 3. **Clear axis labels** - Always include units 4. **Formatted numbers** - Currency ($), percentages (%), etc. 5. **Logo inclusion** - Bottom right, never intrusive 6. **Consistent sizing** - 800x600 standard 7. **Roboto Serif** - Professional, readable font ### Color Usage Rules **Primary actions:** - Use TEAL_ACCENT (#39C6C0) - Buttons, highlights, current selection **Chart lines:** - Primary data: TEAL_ACCENT or BLUE_PRIMARY - Secondary data: BLUE_LIGHT or GRAY - Negative values: DARK_RED (#b50d0d) **Backgrounds:** - Main: WHITE (#FFFFFF) - Secondary: TEAL_LIGHT (#F7FDFC) or BLUE_98 (#F7FAFD) - Plot area: WHITE **Text:** - Primary: BLACK (#000000) - Secondary: DARK_GRAY (#616161) - Muted: GRAY (#808080) ### Accessibility **Color contrast requirements:** - Text on background: 4.5:1 minimum (WCAG AA) - DARK_GRAY on WHITE: ✅ Passes - TEAL_ACCENT on WHITE: ✅ Passes for large text - Use sufficient line weights for visibility **Don't rely on color alone:** - Use patterns or labels for different data series - Ensure charts work in grayscale ## Common Branding Tasks ### Task 1: Create Branded Plotly Chart 1. **Define colors:** ```python TEAL_ACCENT = "#39C6C0" BLUE_PRIMARY = "#2C6496" ``` 2. **Create chart:** ```python fig = go.Figure() fig.add_trace(go.Scatter(x=x, y=y, line=dict(color=TEAL_ACCENT))) ``` 3. **Apply branding:** ```python fig = format_fig(fig) # See implementation above ``` ### Task 2: Setup Streamlit Branding 1. **Create config directory:** ```bash mkdir .streamlit ``` 2. **Copy theme config:** ```bash cat givecalc/.streamlit/config.toml > .streamlit/config.toml ``` 3. **Verify in app:** ```python import streamlit as st st.button("Test", type="primary") # Should be teal ``` ### Task 3: Brand Consistency Check **Checklist:** - [ ] Charts use Roboto Serif font - [ ] Primary color is TEAL_ACCENT (#39C6C0) - [ ] Secondary color is BLUE_PRIMARY (#2C6496) - [ ] White backgrounds - [ ] Logo in charts (bottom right) - [ ] Currency formatted with $ and commas - [ ] Percentages formatted with % - [ ] Streamlit config.toml uses PolicyEngine theme ## Reference Implementations ### Excellent Examples **Streamlit calculators:** ```bash # GiveCalc - Complete example cat givecalc/ui/visualization.py cat givecalc/.streamlit/config.toml # Other calculators ls salt-amt-calculator/ ls ctc-calculator/ ``` **Blog post charts:** ```bash # Analysis with branded charts cat policyengine-app/src/posts/articles/harris-eitc.md cat policyengine-app/src/posts/articles/montana-tax-cuts-2026.md ``` **React app components:** ```bash # Charts in app cat policyengine-app/src/pages/policy/output/DistributionalImpact.jsx ``` ### Don't Use These **❌ Wrong colors:** ```python # Don't use random colors color = "#FF5733" color = "red" color = "green" ``` **❌ Wrong fonts:** ```python # Don't use other fonts for charts font = dict(family="Arial") font = dict(family="Times New Roman") ``` **❌ Missing logo:** ```python # Don't skip the logo in charts for publication # All published charts should include PolicyEngine logo ``` ## Assets and Resources ### Logo Files **In policyengine-app repository:** ```bash policyengine-app/src/images/logos/policyengine/ ├── blue.png # Primary logo (light backgrounds) ├── white.png # Logo for dark backgrounds ├── blue.svg # Scalable blue logo ├── white.svg # Scalable white logo ├── banners/ # Banner variations └── profile/ # Profile/avatar versions ``` **Raw URLs for direct use:** ```python # Use these URLs in code LOGO_URL = "https://raw.githubusercontent.com/PolicyEngine/policyengine-app/master/src/images/logos/policyengine/blue.png" ``` ### Font Files **Roboto (charts):** - Google Fonts: https://fonts.google.com/specimen/Roboto - Family: Roboto Serif - Weights: 300 (light), 400 (regular), 500 (medium), 700 (bold) **Loading:** ```html ``` ### Color Reference Files **JavaScript (React app):** ```bash cat policyengine-app/src/style/colors.js ``` **Python (calculators, analysis):** ```python # Define in constants.py or at top of file TEAL_ACCENT = "#39C6C0" BLUE_PRIMARY = "#2C6496" DARK_GRAY = "#616161" WHITE = "#FFFFFF" ``` ## Brand Evolution **Current identity (2025):** - Teal primary (#39C6C0) - Blue secondary (#2C6496) - Roboto Serif for charts - Minimal, data-focused design **If brand evolves:** - Colors defined in policyengine-app/src/style/colors.js are source of truth - Update this skill to point to current definitions - Never hardcode - always reference colors.js ## Quick Reference ### Color Codes | Color | Hex | Usage | |-------|-----|-------| | Teal Accent | #39C6C0 | Primary interactive elements | | Blue Primary | #2C6496 | Secondary, links, charts | | Dark Gray | #616161 | Body text | | White | #FFFFFF | Backgrounds | | Teal Light | #F7FDFC | Secondary backgrounds | | Dark Red | #b50d0d | Negative values, errors | ### Font Families | Context | Font | |---------|------| | Charts | Roboto Serif | | Web app | System sans-serif | | Streamlit | Default sans-serif | | Code blocks | Monospace | ### Logo URLs | Background | Format | URL | |------------|--------|-----| | Light | PNG | https://raw.githubusercontent.com/PolicyEngine/policyengine-app/master/src/images/logos/policyengine/blue.png | | Light | SVG | https://raw.githubusercontent.com/PolicyEngine/policyengine-app/master/src/images/logos/policyengine/blue.svg | | Dark | PNG | https://raw.githubusercontent.com/PolicyEngine/policyengine-app/master/src/images/logos/policyengine/white.png | | Dark | SVG | https://raw.githubusercontent.com/PolicyEngine/policyengine-app/master/src/images/logos/policyengine/white.svg | ## Related Skills - **policyengine-app-skill** - React component styling - **policyengine-analysis-skill** - Chart creation patterns - **policyengine-writing-skill** - Content style (complements visual style) ## Resources **Brand assets:** PolicyEngine/policyengine-app/src/images/ **Color definitions:** PolicyEngine/policyengine-app/src/style/colors.js **Examples:** givecalc, salt-amt-calculator, crfb-tob-impacts