Add pages table + block registry scaffold (page builder step 2)

New `pages` table: slug/title/blocks(JSON-as-text)/status/protected, author
FK, grouped SEO metadata + layout/nav settings columns (added up front per
spec — cheap now, painful to retrofit), published_at mirroring posts.

Block registry scaffold, server and client, defining the pattern without
any block types yet (Wave 1 lands in step 3):
- server/src/blocks: registry (register/get/list, reserved envelope keys,
  container metadata) + validateBlocks (authoritative save-time gate:
  envelope, registered-type, per-block schema, one-level nesting cap) +
  index entrypoint that will register Wave 1 defs.
- client/src/blocks: mirror registry carrying renderer/editor/palette +
  makeBlockId, plus index entrypoint.

Verified: schema applies idempotently against the dev DB (pages table +
indexes present); validator exercised for empty/non-array/unknown-type/
bad-envelope/duplicate-id/nested-container cases.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-09 20:26:14 -05:00
parent 6180e8a071
commit fcef08e9b6
6 changed files with 384 additions and 0 deletions

View File

@@ -0,0 +1,29 @@
// Block registry entrypoint. Requiring this module registers every server-side
// block definition (schema + cache policy) exactly once, then re-exports the
// registry API and the blocks validator. Anything that needs to validate a
// page's blocks or look up a block type should require THIS module, not
// ./registry directly, so the definitions are guaranteed to be loaded.
//
// Wave 1 block definitions are registered below, one require() per block, as
// they are built (spec build order step 3). Until then the registry is empty and
// validateBlocks rejects any block type — which is correct: no page can save a
// block that has no server-side schema yet.
const registry = require('./registry')
const { validateBlocks, MAX_BLOCKS, MAX_SUBBLOCKS } = require('./validateBlocks')
// ── Wave 1 block definitions ──────────────────────────────────────────
// require('./types/heading').register(registry) // added in step 3
// require('./types/richText').register(registry)
// require('./types/image').register(registry)
// require('./types/twoColumn').register(registry)
// require('./types/cta').register(registry)
// require('./types/divider').register(registry)
// require('./types/quote').register(registry)
module.exports = {
...registry,
validateBlocks,
MAX_BLOCKS,
MAX_SUBBLOCKS,
}