Canvas Design System
Main Site Tokens

App Screen Components

What /app/ is actually made of, family by family, and which families the design system governs.

fact_check
Inventoried on 17 September 2026 from two live captures, signed in: /app/ (home, 238 named nodes across 66 distinct classes) and /app/?view=plan&step=build (the planner, 203 nodes across 67 classes). Counts below are instances on those two screens, not guesses.

What the design system already covers

All 66 functions in includes/components/helpers.php are registered in workshopr-design-system.json. Everything on these screens that belongs to the design system is in it; nothing needs creating.

ComponentClassInstances (home / planner)
ws_button.ws-btn17 / 2
ws_card.ws-card3 / 0
ws_badge.ws-badge2 / 0
ws_sidenav.ws-sidenav1 / 1
ws_task_checklist.ws-task-checklist1 / 0
ws_dna_profile_cta.ws-dna-profile-cta1 / 0
ws_app_footer.ws-app-footer1 / 0
ws_app_bar.ws-app-bar0 / 1
ws_app_dock.ws-app-dock0 / 1
ws_header.wsh-header1 / 1
ws_hero.app-hero wrapper1 / 0

Three families outside the design system

These render most of both screens and none of check-drift's gates reach them. Its own note on the rule is the brief: either move it into includes/components/ and document it, or give it a local gate. Registered in workshopr-design-system.json under externalComponents.

1. Workshop list largest gap

app/includes/workshop-list.php, 24 ws_wl_* functions, plus 32KB of app/css/workshop-list.css. 12 .wl-card instances on home alone, making it the most repeated card on the platform and the least governed. check-drift already reports it as a warning.

ClassesUsed on
.wl-card, .wl-card__top, .wl-card__meta, .wl-stage, .wl-chip, .wl-view, .wl-grid, .wl-page, .wl-select__box home, plan/home, plan/saved, planner/saved.php
2. Dashboard and rail

app/views/home.php, app/includes/dashboard.php, app/includes/rail.php. The up-next band and the rail's tips and film cards are hand-built around ws_card rather than being components of their own.

ClassesUsed on
.dash__hero, .dash__hero-body, .dash__hero-actions, .app-rail__tips-tile, .app-rail__film-tile, .app-rail__quick home
3. Planner

The biggest surface and the least componentised: zero helper functions, so every one of these is raw markup in planner/. Note that ws_energy_arc_card is a registered component, but the builder's progress header uses the separate .energy-arc classes instead of it.

ClassesUsed on
.agenda-item, .item-duration-badge, .item-icon, .item-description, .agenda-progress-header, .activity-sidebar, .category-btn, .category-btn-count, .section-header, .filter-select, .topbar-dropdown, .energy-arc /app/?view=plan&step=build (iframed planner)

Order of work, and why

These are not equal. Promoting a family is a refactor of shipping code, so the order matters more than the count.

#FamilyWhy hereShape of the work
1 Workshop list Most instances, most reuse across four surfaces, and the functions already exist. This is a promotion, not an invention. Move the 24 functions into includes/components/, split the 32KB of CSS, add a demo, and let the existing gates start covering it.
2 Dashboard and rail Small, self-contained, and only used on one screen, so the blast radius is one page. Two or three new ws_* components wrapping what is already ws_card underneath.
3 Planner Biggest and riskiest. It has no helper layer to promote, the CSS is a modular bundle, and the builder autosaves, so a refactor here can write to production. Genuine componentisation from scratch. Should be its own project, not a design-system chore.
warning
None of the three can be promoted without editing app/ or planner/. That is shipping code on the two most-used screens, so each family wants its own change, its own tests, and its own deploy set. Registering them here is the inventory step, not the fix.