Everything an AI agent needs to build UIs with Eddie. Point Claude, Cursor, Copilot, or any AI tool here.

The One Rule

Every visible UI element must come from an Eddie component or recipe. Consumer projects contain zero custom component styles. No exceptions.

This means:

  • No custom CSS classes (.my-card, .sidebar-item, .form-row)
  • No raw font-family, font-size, font-weight, or line-height
  • No hardcoded colors, spacing pixels, or border values
  • No Google Fonts <link> tags
  • No Tailwind, Bootstrap, or any other CSS framework
  • No inline styles unless using --ed-* CSS custom properties

If Eddie doesn't have a component you need, create a recipe — never write ad-hoc CSS in the consumer project.


What is Eddie?

Eddie is a themeable, framework-agnostic web component library built with Lit and TypeScript. It's published as four npm packages:

  • @brad-frost-web/eddie-web-components — 80+ Lit-based web components
  • @brad-frost-web/eddie-design-tokens — Design tokens (CSS custom properties, SCSS, JSON)
  • @brad-frost-web/eddie-icons — SVG icon sprite library
  • @brad-frost-web/eddie-recipes — Product-specific compositions built on core components

All components use the <ed-*> tag prefix and work in any framework or plain HTML.


Project Setup

1. Install packages

npm install @brad-frost-web/eddie-web-components @brad-frost-web/eddie-design-tokens @brad-frost-web/eddie-icons @brad-frost-web/eddie-recipes

2. HTML: Add theme class

<html lang="en" class="bfw">

Available themes: bfw, bfw-dark, bfw-v9, wowee-zowee, we-are-here, altitude, southleft

3. JS entry point: Import tokens, fonts, and components

// Fonts (from tokens — NEVER add Google Fonts <link> tags) import '@brad-frost-web/eddie-design-tokens/bfw/scss/fonts.scss'; // Tokens (CSS custom properties) import '@brad-frost-web/eddie-design-tokens/bfw/build/css/tokens.css'; // Components (import each one you use) import '@brad-frost-web/eddie-web-components/components/button/button'; import '@brad-frost-web/eddie-web-components/components/heading/heading'; import '@brad-frost-web/eddie-web-components/components/text-passage/text-passage'; // ... import every component you use

4. App CSS: ONLY the project-level reset

The only CSS your app should contain:

html { box-sizing: border-box; } *, *:before, *:after { box-sizing: inherit; } body { background: var(--ed-theme-color-background-default); color: var(--ed-theme-color-content-default); }

That's it. Nothing else. Eddie handles everything.

5. Vite config for local development

If linking to the Eddie monorepo source (not published npm packages):

import path from 'path'; const eddieRoot = path.resolve(__dirname, '../eddie-design-system'); export default defineConfig({ resolve: { alias: { '@brad-frost-web/eddie-web-components': path.join(eddieRoot, 'packages/eddie-web-components'), '@brad-frost-web/eddie-design-tokens': path.join(eddieRoot, 'packages/eddie-design-tokens'), '@brad-frost-web/eddie-icons': path.join(eddieRoot, 'packages/eddie-icons'), '@brad-frost-web/eddie-recipes': path.join(eddieRoot, 'packages/eddie-recipes'), }, }, css: { preprocessorOptions: { scss: { api: 'modern-compiler', includePaths: [ path.join(eddieRoot, 'packages/eddie-design-tokens/core/scss'), path.join(eddieRoot, 'packages/eddie-design-tokens'), path.join(eddieRoot, 'packages'), ], }, }, }, });

Component Lookup Table

When building UI, use this table to find the right Eddie component. Never build these patterns from scratch.

Page Structure

You need... Use this Example
Page shell <ed-header> + <ed-main> Top-level page wrapper
Content width cap <ed-layout-container> Wraps content inside header and main
Sidebar layout <ed-layout variant="left-sidebar"> Two-column with sidebar
Layout columns <ed-layout-section> Children of ed-layout
Content section <ed-section> Has a header slot for section titles
Full-width band <ed-band> Background-colored horizontal strip
Hero area <ed-hero> Full-width hero with image support

Navigation

You need... Use this Example
Top nav <ed-primary-nav> + <ed-primary-nav-item> Main site navigation
Nav wrapper <ed-nav-container> Contains primary nav in the header
Utility links <ed-utility-nav> + <ed-utility-nav-item> Secondary nav (login, settings)
Link list <ed-link-list> + <ed-link-list-item> Vertical list of links
Breadcrumbs <ed-breadcrumbs> + <ed-breadcrumbs-item> Path breadcrumb trail
Pagination <ed-pagination> + <ed-pagination-item> Page navigation

Typography & Content

You need... Use this Example
Heading <ed-heading tagName="h2"> Set tagName for semantic level, variant for visual size
Body text <ed-text-passage> Wraps paragraphs, lists, blockquotes with proper typography
Link <ed-text-link> Styled anchor
Divider <ed-hr> Horizontal rule
Code block <ed-code language="js"> Syntax-highlighted code

Content Display

You need... Use this Example
Content grid <ed-grid variant="3up"> + <ed-grid-item> Variants: 1-2up, 2up, 3up, 4up
Card <ed-card> Content container with optional image
Data table <ed-table> + header/body/row/cell children Structured data
Key-value pairs <ed-key-value-table> + <ed-key-value-table-row> Label + value display
Badge <ed-badge> Status indicator
Tag <ed-tag> Label/category marker
Tag group <ed-tag-list> Wraps multiple tags
Page title <ed-page-header heading="Title"> With optional description and actions
Media + text <ed-media-block> Image/icon alongside text
Feature block <ed-feature> Highlighted feature display

Forms

You need... Use this Example
Text input <ed-text-field label="Name"> Single-line text
Textarea <ed-textarea-field label="Bio"> Multi-line text
Select <ed-select-field label="Country"> Dropdown
Checkbox <ed-checkbox-field> + <ed-checkbox-field-item> Multiple checkboxes
Radio buttons <ed-radio-field> + <ed-radio-field-item> Single selection
Toggle switch <ed-toggle label="Dark mode"> On/off toggle
File upload <ed-file-upload> File picker
Search <ed-search-form> Search input with submit
Range slider <ed-range> Numeric range input
Field help text <ed-field-note> Helper text for form fields
Button <ed-button text="Submit" variant="primary"> Variants: primary, secondary, danger, ghost
Button group <ed-button-group> Groups related buttons

Feedback & Overlays

You need... Use this Example
Alert banner <ed-alert> Inline alert message
Toast message <ed-toast> Temporary notification
Modal dialog <ed-modal> Overlay dialog
Drawer panel <ed-drawer> Slide-in panel
Tooltip <ed-tooltip-trigger> + <ed-tooltip> Hover/focus tooltip
Loading spinner <ed-loading-indicator> Loading state
Progress bar <ed-progress> Progress indicator
Skeleton <ed-skeleton> Loading placeholder

Interactive Patterns

You need... Use this Example
Tabs <ed-tabs> + <ed-tab> Tabbed content
Accordion <ed-accordion> + <ed-accordion-panel> Expandable sections
Show/hide <ed-show-hide> Toggle content visibility
Show more <ed-show-more> Truncate with "show more"

Utility

You need... Use this Example
Icon <ed-icon iconName="arrow-right"> SVG icon from sprite
Logo <ed-logo> Brand logo
Box container <ed-box> Generic styled container
Toolbar <ed-toolbar> Actions bar
Counter <ed-counter> Numeric count display
Dot <ed-dot> Status dot indicator

Common Recipes

Recipes are product-specific compositions in @brad-frost-web/eddie-recipes. Use the <ed-r-*> tag prefix.

Recipe Tag Description
Site Header <ed-r-site-header> Full header with logo + nav + utility nav
Site Footer <ed-r-site-footer> Full footer composition
Project Card <ed-r-project-card> Card for project listings
Promo Block <ed-r-promo-block> Promotional content block
Example Form <ed-r-example-form> Form pattern reference

Design Tokens

Never use raw values. Always use Eddie CSS custom properties.

Spacing

Use var(--ed-spacing-*) for all spacing: 2xs, xs, sm, md, lg, xl, 2xl, 3xl, 4xl, 5xl.

<div style="padding: var(--ed-spacing-md); margin-bottom: var(--ed-spacing-lg);">

Colors

Use semantic color tokens, never raw hex/rgb values:

var(--ed-theme-color-background-default) /* page background */ var(--ed-theme-color-background-subtle) /* secondary background */ var(--ed-theme-color-content-default) /* body text */ var(--ed-theme-color-content-subtle) /* secondary text */ var(--ed-theme-color-border-default) /* default borders */ var(--ed-theme-color-interactive-default) /* links, interactive elements */ var(--ed-theme-color-content-accent-1) /* through accent-8 */ var(--ed-theme-color-content-on-accent-1) /* text ON accent backgrounds */ var(--ed-theme-color-background-accent-1) /* accent backgrounds */

Typography

Eddie components handle their own typography. Use <ed-heading> for headings, <ed-text-passage> for body text. Never set font-family, font-size, or line-height directly.

Borders

var(--ed-border-radius-2) /* through -16, plus -round */ var(--ed-theme-border-width-sm) /* sm, md, lg */

Composition Patterns

Basic Page

<html lang="en" class="bfw"> <body> <ed-header> <ed-layout-container> <ed-nav-container> <ed-logo slot="logo" href="/"></ed-logo> <ed-primary-nav slot="nav"> <ed-primary-nav-item text="Home" href="/"></ed-primary-nav-item> <ed-primary-nav-item text="About" href="/about/"></ed-primary-nav-item> </ed-primary-nav> </ed-nav-container> </ed-layout-container> </ed-header> <ed-main> <ed-layout-container> <ed-page-header heading="Page Title"></ed-page-header> <ed-text-passage> <p>Your content here.</p> </ed-text-passage> </ed-layout-container> </ed-main> </body> </html>

Sidebar Layout

<ed-main> <ed-layout-container> <ed-layout variant="left-sidebar"> <ed-layout-section> <!-- Sidebar content --> <ed-link-list> <ed-link-list-item text="Dashboard" href="/dashboard/"></ed-link-list-item> <ed-link-list-item text="Settings" href="/settings/"></ed-link-list-item> </ed-link-list> </ed-layout-section> <ed-layout-section> <!-- Main content area --> <ed-page-header heading="Dashboard"></ed-page-header> </ed-layout-section> </ed-layout> </ed-layout-container> </ed-main>

Card Grid

<ed-grid variant="3up"> <ed-grid-item> <ed-card> <ed-heading tagName="h3" variant="title">Card Title</ed-heading> <ed-text-passage><p>Card content.</p></ed-text-passage> </ed-card> </ed-grid-item> <ed-grid-item> <ed-card> <ed-heading tagName="h3" variant="title">Card Title</ed-heading> <ed-text-passage><p>Card content.</p></ed-text-passage> </ed-card> </ed-grid-item> <ed-grid-item> <ed-card> <ed-heading tagName="h3" variant="title">Card Title</ed-heading> <ed-text-passage><p>Card content.</p></ed-text-passage> </ed-card> </ed-grid-item> </ed-grid>

Form

<ed-card> <ed-heading tagName="h2" variant="title">Create Account</ed-heading> <form> <ed-text-field label="Full Name" required></ed-text-field> <ed-text-field label="Email" type="email" required></ed-text-field> <ed-text-field label="Password" type="password" required></ed-text-field> <ed-checkbox-field> <ed-checkbox-field-item label="I agree to the terms"></ed-checkbox-field-item> </ed-checkbox-field> <ed-button-group> <ed-button variant="primary" text="Create Account" type="submit"></ed-button> <ed-button text="Cancel" href="/"></ed-button> </ed-button-group> </form> </ed-card>

Creating Recipes (When Eddie Doesn't Have What You Need)

If a UI pattern doesn't exist in Eddie core, create a recipe component — never write custom CSS in the consumer project.

How to create a recipe

  1. Scaffold: npm run eddie-recipes:plop (from repo root)
  2. Choose a project directory (e.g., common/ for shared recipes, or a project-specific folder)
  3. The recipe goes in packages/eddie-recipes/recipes/<project>/<recipe-name>/

Recipe conventions

  • Tag prefix: ed-r- (e.g., <ed-r-pricing-card>)
  • CSS class prefix: ed-r-c- (e.g., .ed-r-c-pricing-card)
  • Extends EdElement (same base class as core components)
  • Uses BEM naming, flat SCSS, and Eddie design tokens
  • Should compose Eddie core components internally

Recipe file structure

recipes/<project>/<recipe-name>/ ├── <recipe-name>.ts # Component class ├── <recipe-name>.scss # Styles (BEM, uses Eddie tokens) ├── <recipe-name>.stories.ts # Storybook stories

Component API Conventions

When working with Eddie components, follow these naming patterns:

  • variant — Primary stylistic variation (e.g., "primary", "secondary", "danger")
  • size — Abbreviated t-shirt sizes: xs, sm, md, lg, xl
  • text — General string content
  • title — Heading content
  • label — Form field labels
  • iconName / iconPosition — Icon integration
  • imgSrc / imgAlt — Image properties
  • tagName — Override the HTML element rendered (e.g., tagName="h3")
  • inverted — Boolean for dark-background color inversion
  • href — Makes component render as a link

What NOT to Do

These are the most common mistakes. If an AI agent does any of these, it's wrong:

  1. Writing custom CSS classes — If you're creating .my-sidebar, .step-indicator, .form-row, stop. Use an Eddie component or create a recipe.
  2. Using Tailwind, Bootstrap, or any CSS framework — Eddie IS the framework. Don't layer anything on top.
  3. Hardcoding fonts — Never add Google Fonts <link> tags. Import fonts.scss from the token package.
  4. Raw pixel values — Use var(--ed-spacing-*) for spacing, var(--ed-border-radius-*) for radii.
  5. Setting typography in app CSS — Use <ed-heading>, <ed-text-passage>, and <ed-text-link>.
  6. Using <div> and <span> with custom styles — There's almost always an Eddie component for it.
  7. Building layout with CSS Grid/Flexbox directly — Use <ed-layout>, <ed-grid>, <ed-layout-container>.
  8. Creating buttons with <button> + custom styles — Use <ed-button>.
  9. Ignoring the import pattern — Every Eddie component must be imported in your JS entry point before use.

For Claude / AI Agents: Behavioral Rules

If you are an AI assistant building UI for a Brad Frost Web project:

  1. ALWAYS use Eddie components. Do not write custom HTML elements with custom CSS. Every UI element has an Eddie equivalent — find it in the table above.
  2. ALWAYS use design tokens. If you need to set a color, spacing, border, or typography value, use an --ed-* CSS custom property. Never hardcode values.
  3. NEVER add CSS frameworks. No Tailwind, Bootstrap, Material UI, or any other UI library. Eddie replaces all of them.
  4. NEVER write custom component CSS in consumer projects. If Eddie doesn't have what you need, create a recipe in the eddie-recipes package.
  5. Import every component you use in the JS entry point. Eddie components are web components and must be registered before use.
  6. Check the component table before building anything. If you're about to write a <div class="card">, stop — use <ed-card>.
  7. Follow the entry point pattern. Every project needs: fonts import → tokens import → component imports → theme class on <html>.
  8. When in doubt, compose. Eddie components are designed to nest and compose. A page is just Eddie components all the way down.

Reference Links