# Phase Handover — Experience 11.3 Theme & Layout Engine ## Metadata | Field | Value | | --- | --- | | Phase ID | `experience-11.3` | | Title | Theme & Layout Engine | | Status | Complete | | Service(s) | `experience` (`experience_db`) | | Version | `0.11.3.0` | | Date | 2026-07-26 | | ADR(s) | [ADR-016](../architecture/adr/ADR-016.md), [ADR-008](../architecture/adr/ADR-008.md) | ## Discovery Summary Prior phase delivered versioned components. Gap: replaceable theme packs and dynamic layout shells with directionality, plus site/page bindings without rewriting page trees. Mirrors the Phase 11.2 component/component-version catalog+immutable-version pattern. Templates deferred to 11.4. ## Reusable Components | Component | Location | Reuse notes | | --- | --- | --- | | Theme catalog + versions | `app/models/themes.py` (`ExperienceTheme`, `ExperienceThemeVersion`), `services/themes.py` | Tokens + brand shell immutable once published | | Layout catalog + versions | `app/models/themes.py` (`ExperienceLayout`, `ExperienceLayoutVersion`) | Regions/structure shell immutable once published | | Bindings | `SiteThemeBinding`, `PageLayoutBinding` | Pin a published version; swap without page rewrite | | Policies / specs | `app/policies/themes.py`, `app/specifications/themes.py` | Lifecycle + version + binding rules, list UX | ## Public APIs | Method | Path | Permission | | --- | --- | --- | | CRUD + activate/deprecate/archive | `/api/v1/themes` | `experience.themes.*` | | CRUD + publish/retire | `/api/v1/theme-versions` | `experience.themes.*` | | CRUD + activate/deprecate/archive | `/api/v1/layouts` | `experience.layouts.*` | | CRUD + publish/retire | `/api/v1/layout-versions` | `experience.layouts.*` | | Assign / unassign | `/api/v1/site-theme-bindings` | `experience.themes.*` | | Assign / unassign | `/api/v1/page-layout-bindings` | `experience.layouts.*` | ## Events | Event type | Notes | | --- | --- | | `experience.theme.*` | Theme catalog lifecycle | | `experience.theme_version.*` | Theme version created/updated/published/retired | | `experience.layout.*` | Layout catalog lifecycle | | `experience.layout_version.*` | Layout version created/updated/published/retired | | `experience.site_theme.*` | Site theme bind/replace/unassign | | `experience.page_layout.*` | Page layout bind/replace/unassign | ## Extension Points | Extension point | How to extend | Forbidden uses | | --- | --- | --- | | `ExperienceThemeVersion.tokens` | Frontend CSS variables (ADR-008) | Write Core tenant brand tables | | `ExperienceLayoutVersion.regions` / `structure_shell` | Template phase consumes regions | Store full page trees / CMS | | `ThemeMarketplaceProvider` | External packs via protocol | Shared marketplace DB | ## Known Limitations - No template catalog (11.4) - Bindings require an ACTIVE theme/layout with a PUBLISHED version - Metrics remain discovery-oriented - Visual theme editor UI is frontend-only ## Migration Notes | Item | Detail | | --- | --- | | Alembic revision(s) | `0004_phase_113_themes_layouts` (head) | | Upgrade steps | `alembic upgrade head` | | Downgrade support | Drops bindings, versions, layouts, themes | | Breaking changes | None (additive) | ## Dependencies | Dependency | Type | | --- | --- | | experience-11.2 components | Required prior | | ADR-016 / ADR-008 | Boundaries / branding | ## Quality Gates - [x] Discovery complete - [x] Architecture / boundaries preserved - [x] Tests green - [x] Documentation + manifests + registries updated - [x] Self audit: no template engine leakage; themes replaceable ## Next Phase Entry | Field | Value | | --- | --- | | Recommended next phase | `experience-11.4` Template System | | Entry checklist | Read this handover + phase doc; implement templates only — no forms/surveys yet | ## Completion Sign-Off - [x] Quality gates passed - [x] Tests green - [x] Documentation updated - [x] Progress / next-steps / registries updated - [x] Self audit completed ## Related Documents - [Experience Phase 11.3](../experience-phase-11-3.md) - [Experience Roadmap](../experience-roadmap.md) - [ADR-016](../architecture/adr/ADR-016.md) - [ADR-008](../architecture/adr/ADR-008.md)