Skip to content

Project Structure

Nick Hamze edited this page Apr 21, 2026 · 2 revisions

Project Structure

The Fifty repo is a monorepo: each theme is a top-level subdirectory, all shared tooling lives in bin/, and there is no per-theme node_modules, no per-theme build output, and no per-theme package.json.

fifty/
├── obel/          # base theme (the reference implementation — read first)
├── chonk/         # neo-brutalist variant
├── selvedge/      # workwear / indigo variant
├── lysholm/       # Nordic home goods variant
├── bin/           # shared CLI tooling (run from the monorepo root)
├── playground/    # shared Playground PHP helpers (see playground/AGENTS.md)
├── docs/          # generated GH Pages site of short URLs (see bin/build-redirects.py)
├── tests/         # committed visual-regression baselines (PNG)
├── tmp/           # gitignored: snap output, playground server logs, blueprint scratch
├── AGENTS.md      # repo-root agent guide (every footgun + guardrail in one file)
├── README.md      # the elevator pitch and the live demo links
├── LICENSE        # GPL-2.0+, applies to every theme
└── .editorconfig  # shared editor config

Per-theme layout

Each theme directory is self-contained from WordPress's perspective:

obel/
├── theme.json         # THE design system — every token, every block override
├── style.css          # WP's required header file (no actual CSS)
├── functions.php      # tiny WP filter set (sale-flash, view-transition names, etc.)
├── templates/         # full-site-editing templates (~25 files)
├── parts/             # template parts (header, footer, mini-cart drawer, etc.)
├── patterns/          # block patterns the editor exposes
├── styles/            # style variations (alternate token sets)
├── assets/            # SVGs, fonts, screenshots — never JS, never CSS
├── playground/        # blueprint.json, content.xml, image fixtures
├── screenshot.png     # WP appearance screen thumbnail
├── AGENTS.md          # per-theme agent rules
├── INDEX.md           # generated token + template + style-variation map
├── CHANGELOG.md       # human-readable per-theme history
└── SYSTEM-PROMPT.md   # short LLM system prompt for one-shot edits

The theme.json is the load-bearing file in every theme. Everything visual flows from it. There are zero .css files in any theme directory (the style.css is a one-line metadata header WP requires).

Shared tooling (bin/)

Script Role
check.py The single pre-commit gate. Runs every static check + (optional) snap-gated visual sweep.
snap.py Visual-snapshot framework. Boots WordPress Playground, drives Playwright, captures screenshots + diagnostics, diffs against committed baselines. See Visual Snapshots.
snap_config.py Routes, viewports, inspector selectors, interactions, budgets, noise filters. The single config file for snap.py.
clone.py Scaffolds a new sibling theme from Obel with the names rewritten.
build-index.py Regenerates a theme's INDEX.md (token map, template list, block style list).
build-redirects.py Regenerates docs/<theme>/<page>/index.html short URLs that GH Pages serves.
validate-theme-json.py Validates a theme's theme.json block names against live Gutenberg + WC sources.
list-templates.py Prints every template the theme could ship and the URL it serves.
list-tokens.py Inspects design tokens defined in theme.json.
seed-playground-content.py Populates <theme>/playground/{content,images}/ from the canonical W&O source.
sync-playground.py Inlines playground/*.php into every theme's playground/blueprint.json.
append-wc-overrides.py Generates and appends WooCommerce override CSS chunks into each theme's styles.css.

Every script accepts a positional theme name, defaults to the cwd if it contains a theme.json, and most support --all to operate on every theme. See Tooling for the full reference.

Generated artifacts

The repo intentionally keeps generated artifacts close to their source so the diffs make sense to reviewers:

  • <theme>/INDEX.md — committed; regenerated by bin/build-index.py.
  • <theme>/playground/blueprint.json — committed; the embedded PHP/SQL is regenerated by bin/sync-playground.py.
  • docs/<theme>/<page>/index.html — committed; regenerated by bin/build-redirects.py.
  • tests/visual-baseline/<theme>/<viewport>/<route>.png — committed; regenerated when a visual change is intentional via bin/snap.py baseline.
  • tmp/snaps/** — gitignored; latest snap output, findings JSON, axe reports.
  • tmp/diffs/** — gitignored; per-pixel diff overlays vs the committed baselines.
  • bin/vendor/axe.min.js — gitignored; auto-downloaded from a version-pinned CDN URL on first snap run.

Clone this wiki locally