feat(customization): PageBuilder named page variants + activation (ADR-0001)#167
Merged
Conversation
Decouple three previously-conflated concepts (ADR-0001): a page schema exists, a schema is active, and the built-in fixed view. Each slot now owns a library of named variants plus an explicit active selection at realm and application level (app overrides realm; inherit/built-in/variant). Fixes the field-tested UX traps: "reset to default" is now a UI-only editor buffer load (never a destructive server delete), a variant can be deactivated without deleting it, and multiple variants per slot are supported with activation chosen in realm/app settings. Backend: new PageVariant/RealmPageSlot/AppPageSlot domain types with a lazy migration from the legacy single-schema Pages dict; variant CRUD + set-active endpoints for realm and app; activation-aware effective resolution (app -> realm -> built-in); app-info keeps its wire shape (effective active schema per slot). Frontend: overview lists variants with usage badges + an active selector; variant-scoped editor with non-destructive reset and a name field; app settings Pages tab gains inherit/active selection + variant management. Verified: 1426 unit tests + 10 PageBuilder integration tests green; frontend type-check + build green; DevTools smoke of create -> activate -> runtime render -> deactivate -> built-in fallback -> delete. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Reworks the PageBuilder into a named-variant + activation model (ADR-0001), decoupling three concepts the initial single-schema design (#166) conflated: a schema exists ≠ it is active ≠ the built-in fixed view.
Motivated by field testing on auth-test.cocoar.dev, which surfaced three UX traps:
Model
Per slot (
login/logout/password-forgot) a realm/app owns a library of named variants plus an active selection:{ Variants[], ActiveVariantId? }—null⇒ built-in.{ Variants[], InheritActive, ActiveVariantId? }— inherit realm, or override to built-in / an app variant.Activation is a settings decision: the Pages overview has an Active for realm selector per slot (and badges which variant is live so the edit blast-radius is visible); apps set Active for this app in Settings → Pages. "Reset to default" in the editor is now a UI-only buffer load — nothing persists until Save, and Save creates/updates a variant, never deletes.
Changes
Backend
PageVariant/RealmPageSlot/AppPageSlotdomain types;RealmSettings.PageSlots+ApplicationSettings.PageSlots.Pagesdict → one active "Custom" variant.CustomizationPagesEndpoints: variant CRUD + set-active for realm and app.EffectiveSettingsresolution is activation-aware (with legacy fallback);/api/app-infokeeps its wire shape (effective active schema per slot).RealmSettingsDtono longer carries page schemas (moved to the dedicated endpoints).Frontend
usePagesApicomposable; editor route is nowpages/:slug/:variantId(newto author).Docs / ADR
docs/platform/pages.mdupdated; ADR-0001 recorded (Atlas, areamodgud).Feature flag — safe to merge
Everything stays behind
AppSettings.Features.PageBuilder(operator-level, defaults false). Supersedes the single-schema storage from #166 (same flag, still dark). Built-in hardcoded views +?safemode=1remain the always-safe fallback.Verification
EffectiveSettingstests).type-check+ production build green.🤖 Generated with Claude Code