feat: page management — create, rename, move, delete, reorder, enable/disable with page types #28
No reviewers
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Cloonar/deckle!28
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "afk/9"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Turns #4's read-only page tree into full page management with guardrails, per the issue's agent brief.
What's here
Page types (
internal/pagetype,editor/pagetypes/*.yaml): developer-defined sidecars declaring label/icon,kind: page|section,root(creatable at the content root), allowedchildrentypes, anelementsallow-list (validated against element schemas, served for #6 to enforce), and page-level front-matterfieldsin the exact element-param grammar. Same loading discipline asinternal/element: strict decode, per-file actionable errors, invalid files never block valid ones. Served fresh onGET /api/pagetypes.Front-matter write engine (
internal/content): the write halfmeta.gopromised —EncodeFrontMatter(canonical: deterministic bytes, keys sorted at every level, per-format guards self-checked against the serializer),UpdateFrontMatter, andReplaceFrontMatter, which splices an encoded block in front of verbatim body bytes so weight/draft/alias edits work even on pages whose bodiesParserejects. Org front matter stays decode-only with a loud error.Operations (
internal/pageops+ sevenPOST /api/page/*endpoints):root: trueat the root, the section type'schildrenelsewhere); writes a leaf bundle with the type's defaults, recordedtype, anddraft = true; slugs auto-generate from the title, collision-safe, overridableos.Renameof the whole bundle; the old published URL is appended toaliases(every descendant's URL on section renames/moves), existing aliases preserved, never duplicated; multi-file rewrites are prepared and validated before the irreversible renamepagetree.Build, so it cannot drift from what the client sees)draft; delete — file / bundle / recursive sectionSPA (
web/): per-row action cluster (new child, enable/disable, rename, delete), create dialog with type picker + live slug preview, delete confirmation naming the page and its descendant count, HTML5 drag & drop for same-section reorder and cross-section moves (legality mirrors the server; the server stays authoritative), and a page-settings form generated from the page type's fields — widget code shared with the element form via the newFieldInput. Tree refreshes immediately after each mutation; expansion state survives; selection follows renamed/moved pages to their new identity.Sample site:
section+pagetypes exercising the child-type constraints (page not allowed at root, allowed under sections); all content carries itstype.Verification
go vet ./...clean;go test ./...green (9 packages) — all mutation tests run against temp copies of the site, never the checked-in oneweb: 58 vitest tests green,tsc --noEmitclean, production build OKdatekey preserved, 422 field mapping), recursive section delete,typeon the tree,metaon/api/page— all against a livehugo serverthat kept building cleanly throughoutOut of scope (per the brief)
Element CRUD enforcement of the
elementsallow-list (#6), git safety commits/publish (#10, #11), locks/CSRF (#13), media (#12), multi-language UI.Closes #9
🤖 Generated with Claude Code
https://claude.ai/code/session_01DUR1jRbZoNqohK2qDQSZG6
Pull request closed