Skip to content
This repository was archived by the owner on May 9, 2026. It is now read-only.

feat(admin): sections surface MVP (T-5D.1-4, ADR-0021/0024)#142

Merged
slavasolutions merged 3 commits into
release/v1.0from
feat/v1-sections-surface
May 7, 2026
Merged

feat(admin): sections surface MVP (T-5D.1-4, ADR-0021/0024)#142
slavasolutions merged 3 commits into
release/v1.0from
feat/v1-sections-surface

Conversation

@slavasolutions

Copy link
Copy Markdown
Contributor

Summary

Closes T-5D.1 / T-5D.2 / T-5D.3 (basic) / T-5D.4. Defers T-5D.5/6/7/8 to v1.x (drag-and-drop, visual block-picker, click-to-focus from preview, per-instance file storage strategy).

Site-mode admins with at least one block schema can now author a sections page end-to-end — add typed sections, edit each block's fields via per-type SchemaForm, reorder via up/down buttons, delete.

Files

Path Role
`apps/admin/src/lib/site-context.ts` Loads block schemas + theme tokens from the bucket. Cached at process scope; `null` for headless admins
`apps/admin/src/surfaces/sections/types.ts` `SectionInstance` + `SectionsManifest` shape, `toManifest` defensive coercion, `newSectionId` helper
`apps/admin/src/surfaces/sections/SectionCard.tsx` Header (type label + reorder + delete) + body (per-block fields via SchemaForm). Unknown block types render an inline error
`apps/admin/src/surfaces/sections/AddSectionPicker.tsx` Minimal v1 picker; empty-state when no block types defined
`apps/admin/src/surfaces/sections/SectionsSurface.tsx` Manifest stack + dispatcher; useMemo for block-schema → ClearSchema conversion
`apps/admin/src/surfaces/sections/index.tsx` Validator returns `ok()` when site-mode + at least one block schema
`apps/admin/src/components/PageItemEditor.tsx` + `PagePageEditor.tsx` Accept `siteContext` prop, thread to surface.validate + Component
`apps/admin/src/pages/content/[type]/[item]/index.astro` + `pages/[...slug].astro` Pass `await loadSiteContext()` to the editor islands

Self-review pass

Spawned a code-review agent before opening this PR. Initial verdict: block-merge — site-mode gate was incomplete (the dispatcher passed `{}` as ctx, so sections surface's validator always failed). Fixed in-PR:

  • New `loadSiteContext()` helper + `SiteContext` prop on both page editors + .astro callers thread it through.
  • Memo fix on SectionsSurface (useMemo for types/schemaForType).

Verdict after fix: ready to merge.

Tests (18/18, was 11)

  • 11 surface-registry cases (added `sections passes when site-mode + block schema present`)
  • 7 manifest helper cases (toManifest defensive coercion, newSectionId uniqueness)

`pnpm --filter @clearcms/admin typecheck` → 0 errors.

Storage strategy

V1 ships the inline-in-pageData strategy (sections live as `value.sections: SectionInstance[]` on the page document). Per-instance file storage (`writeBlock` / `blockInstancePath`) is a v1.x follow-up once the inline path is proven on real sites.

Coordination

Phase 5D = S1 solo. Baton currently S2 (Eng B's Phase 7 docs window) — drafted in parallel per the surface-independence rule. Will mark ready when baton flips back.

🤖 Generated with Claude Code

slavasolutions and others added 2 commits May 7, 2026 06:25
Replaces the Phase 4 SectionsPlaceholder with a real composition UX.
Site-mode admins with at least one block schema can now author a
sections page end-to-end: add block instances, edit each block's
fields via per-type SchemaForm, reorder via up/down buttons, delete.

Files:
- surfaces/sections/types.ts — SectionInstance, SectionsManifest,
  toManifest defensive coercion, newSectionId crypto-random helper.
- surfaces/sections/SectionCard.tsx — header (type label + reorder +
  delete) + body (per-block fields via SchemaForm with block-schema
  converted to ClearSchema). UnknownBlockType renders inline error.
- surfaces/sections/AddSectionPicker.tsx — minimal select + add UI;
  empty state when no block types exist.
- surfaces/sections/SectionsSurface.tsx — manifest stack + dispatcher.
- surfaces/sections/index.tsx — validator now returns ok() when
  siteContext + at least one block schema. Component = SectionsSurface.

Storage strategy: v1 ships inline-in-pageData. Per-instance block
files (writeBlock + blockInstancePath) land as v1.x follow-up. dnd-
kit reorder, visual block picker, click-to-focus from preview also
deferred to v1.x — operator can author end-to-end with the MVP.

Tests: 11 surface-registry cases (added "sections passes when site-
mode + blocks" branch) + 7 manifest helper cases.

Closes T-5D.1 / T-5D.2 / T-5D.3 (basic) / T-5D.4. Defers T-5D.5/6/7/8.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ge from review)

Self-review on T-5D found a hard blocker: PageItemEditor and
PagePageEditor passed `{}` as the surface validation context, so
sections surface's validator (which requires `ctx.siteContext`)
returned failed() unconditionally — surface never actually mounted.

Fix:
- New `lib/site-context.ts` with `loadSiteContext()` + cache. Reads
  every theme/blocks/*.schema.json and theme/tokens.json into a
  SiteContext shape. Returns null in headless mode.
- PageItemEditor + PagePageEditor accept `siteContext?: SiteContext |
  null` prop, thread it through to surface.validate() + Component.
- .astro callers (item editor + page editor) pass `await
  loadSiteContext()` as the prop.

Plus the memo fix from the same review:
- SectionsSurface uses useMemo for types + schemaForType conversion
  (was rebuilt every render). Removed useCallback that was no-op
  due to props-deps capturing every-render onChange.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ite-context

CI failure on PR #142: SectionsSurface imported blockSchemaToClearSchema
from lib/schemas.ts, which transitively imports @clearcms/storage's
readJson/writeJson — pulled the FS adapter (node:fs/promises, node:path)
into the client bundle and exploded with "join is not exported by
__vite-browser-external".

Fix: move the BlockSchema → ClearSchema dialect conversion into
loadSiteContext() (server-side .astro path). The SiteContext that
arrives at the editor island already carries ClearSchema-shaped block
schemas, so SectionsSurface no longer needs to import any conversion
helper or anything else from lib/schemas.ts. Bundle stays clean.

Local `astro build` now succeeds; CI should match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@slavasolutions slavasolutions merged commit 3f399d2 into release/v1.0 May 7, 2026
1 check passed
@slavasolutions slavasolutions deleted the feat/v1-sections-surface branch May 7, 2026 10:38
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant