System element library: all v1 ContentElements as shortcode templates + sidecars #14

Closed
opened 2026-07-11 13:01:23 +02:00 by dominik.polakovics · 2 comments

What to build

The shipped element library (docs/DECISIONS.md D23), each as layouts/shortcodes/X.html + editor/elements/X.yaml, fully editable through the generated forms and rendering correctly in preview:

  • Structure: grid (row + columns with a fixed responsive width set), spacer
  • Content: text, text-media, image, gallery, hero, quote, video-embed (privacy-friendly click-to-load), accordion (nested item shortcodes), page-teasers (lists child pages of a chosen section), html (developer-flagged, hidden from the picker by default)
  • Inline: button, icon

Markup is semantic and theme-agnostic (classes only, no inline styles) so themes style it; the basic theme (separate issue) provides the styling.

Acceptance criteria

  • Every element above has a template + sidecar; the picker shows them grouped (Structure/Content) with icons
  • Grid nests other elements in columns per placement rules; accordion items are managed as nested block elements
  • video-embed loads no third-party resources until click-to-load consent
  • page-teasers renders titles/summaries/links of a section's non-draft child pages
  • html element does not appear in the default picker; a sidecar flag exposes it
  • Round-trip tests from #2's corpus cover every element's serialized form; each element has a rendered example on the sample site

Blocked by

## What to build The shipped element library (docs/DECISIONS.md D23), each as `layouts/shortcodes/X.html` + `editor/elements/X.yaml`, fully editable through the generated forms and rendering correctly in preview: - Structure: `grid` (row + columns with a fixed responsive width set), `spacer` - Content: `text`, `text-media`, `image`, `gallery`, `hero`, `quote`, `video-embed` (privacy-friendly click-to-load), `accordion` (nested item shortcodes), `page-teasers` (lists child pages of a chosen section), `html` (developer-flagged, hidden from the picker by default) - Inline: `button`, `icon` Markup is semantic and theme-agnostic (classes only, no inline styles) so themes style it; the basic theme (separate issue) provides the styling. ## Acceptance criteria - [ ] Every element above has a template + sidecar; the picker shows them grouped (Structure/Content) with icons - [ ] Grid nests other elements in columns per placement rules; accordion items are managed as nested block elements - [ ] video-embed loads no third-party resources until click-to-load consent - [ ] page-teasers renders titles/summaries/links of a section's non-draft child pages - [ ] `html` element does not appear in the default picker; a sidecar flag exposes it - [ ] Round-trip tests from #2's corpus cover every element's serialized form; each element has a rendered example on the sample site ## Blocked by - #3
Author
Owner

This was generated by AI during triage.

Agent Brief

Category: enhancement
Summary: Ship the complete v1 element library: every system element as a Hugo shortcode template (layouts/shortcodes/X.html) plus an editor sidecar (editor/elements/X.yaml), with semantic theme-agnostic markup, full editability through the schema-generated forms, round-trip test coverage for every element, and a rendered example of each on the sample site.

Dependency note: this issue is hard-blocked by #3 (sidecar schema loading/validation, schemas API, generated forms, canonical save path) — the scheduler handles ordering. #3 ships the schema machinery plus two demonstration elements; this issue fills the library out to the full v1 set using the same sidecar shape and field types, changing the machinery only if a library element genuinely cannot be expressed. The issue body's docs/DECISIONS.md D23 reference points at a file that is not committed — this brief is self-contained.

Current behavior:
The content engine round-trips shortcode-based content losslessly (its test corpus already exercises grid/column nesting, accordion with nested items, and a hero containing inline buttons — as syntax fixtures only). Once #3 lands, sidecars in editor/elements/ are discovered, validated, served via the API, and rendered as generated param forms, with canonical save and live preview working end-to-end — but only for the couple of demonstration elements #3 adds. There is no shipped element library: an editor cannot build a real page out of grids, heroes, galleries, accordions, and the rest.

Desired behavior:

Every element below exists as a shortcode template plus a sidecar, is fully editable through the generated forms (all params expressible with #3's nine field types), and renders correctly in the live preview.

Structure group:

  • grid — a row container holding nested column shortcodes; each column holds arbitrary block elements. Column widths come from a fixed responsive set of fractions (e.g. full, 1/2, 1/3, 2/3, 1/4, 3/4 — the exact set is the implementer's choice but must be small, documented, and expressed as classes); free-form widths are not offered. Responsive collapse behavior belongs to the theme.
  • spacer — self-closing; a size step from a small fixed scale, emitted as a class.

Content group:

  • text — a markdown body, no chrome.
  • text-media — markdown body plus an image, with a side/position param (e.g. media left or right) emitted as a class.
  • image — single image with alt and optional caption; semantic figure/figcaption markup.
  • gallery — multiple images. #3's field types are scalar, so multi-image content is modeled structurally (e.g. nested per-image item shortcodes, mirroring the accordion pattern) — whatever the shape, it must round-trip canonically and be editable element-by-element.
  • hero — heading (and similar params) plus a markdown body that may contain inline button shortcodes mid-text.
  • quote — quotation body plus attribution params; blockquote-based semantic markup.
  • video-embed — privacy-friendly click-to-load: the initial page renders a local placeholder/facade that performs zero third-party network requests (no provider thumbnails, scripts, or fonts); only an explicit user click loads the provider embed (privacy-enhanced endpoints where the provider offers them). The consent mechanism is a small self-contained script/markup shipped with the site — no external dependency, no framework.
  • accordion — a container of nested item shortcodes, each item carrying a title param and a markdown body; items are managed as nested block elements. Prefer natively interactive semantic markup (e.g. details/summary) so the element works unstyled and without JS.
  • page-teasers — given a section (and optionally a limit), renders title, summary, and link for that section's non-draft child pages; draft pages never appear even when the preview server builds drafts.
  • html — raw passthrough body rendered verbatim. Its sidecar carries a developer-only flag: the element is hidden from the element picker by default and only exposed when the flag/sidecar says so; existing html elements on a page remain visible and editable regardless.

Inline group:

  • button — self-closing inline shortcode (href, label, optional variant) rendering an anchor; usable mid-sentence inside element bodies.
  • icon — self-closing inline shortcode identified by an icon name; the markup identifies the icon (class or data attribute) so themes can render the glyph.

Markup contract. All templates emit semantic, theme-agnostic HTML: meaningful elements, a consistent documented class vocabulary, classes only — no inline styles, no CSS shipped by this issue, no JS except video-embed's minimal consent loader, and no third-party assets anywhere. Accessibility basics are in the markup itself (alt on images, real headings, focusable/labelled interactive parts). The library must look acceptable-but-unstyled on a bare site; making it pretty is the theme's job.

Sidecar contract. Every sidecar provides label, icon identifier, picker group (structure/content/inline), schema version, body policy, and params, using #3's shape and field types. Containers and their items declare placement metadata (what may nest where — grid columns accept block elements, accordion accepts only its items, items name their container, inline elements are body-level); this issue declares the rules so #6 can enforce them. All sidecars must load through #3's validator with zero errors and appear in the schemas API with their group and icon metadata; if #6's picker exists by implementation time, it shows the elements grouped Structure/Content with icons — otherwise grouping is verified through the API.

Tests and demonstration. The content engine's corpus round-trip suite gains at least one canonical fixture per element (covering nesting for grid and accordion and inline button/icon inside bodies), so every element's serialized form is locked in. The sample site gains example pages demonstrating every element, building cleanly and rendering in the preview.

Key interfaces:

  • The sidecar schema shape and nine field types from #3 — consumed, not redesigned. If an element is inexpressible (e.g. gallery), prefer structural nesting over inventing new field types.
  • Placement metadata in sidecars — declared here, enforced by #6.
  • The shortcode templates' class vocabulary and DOM structure — this is the contract the theme (#15) styles against; keep it stable and document it (names, modifiers, nesting).
  • The content engine's canonical serializer — every element's authored form must be canonical (fixtures parse and re-serialize to identical bytes).

Acceptance criteria:

  • Each of grid (with its column shortcode), spacer, text, text-media, image, gallery, hero, quote, video-embed, accordion (with its item shortcode), page-teasers, html, button, and icon has both a shortcode template and a sidecar
  • All sidecars pass #3's validation with zero errors and are served with group (structure/content/inline) and icon metadata; the picker, where present (#6), shows them grouped with icons
  • Grid columns nest arbitrary block elements and use widths from the fixed documented set; sidecar placement metadata declares the container/item rules for grid and accordion
  • Accordion items are nested block shortcodes, each editable as its own element with title and body
  • Loading a page containing video-embed triggers no third-party network request until the user clicks; after the click the video plays
  • page-teasers lists title, summary, and link of the chosen section's non-draft child pages; a draft child never appears
  • The html element does not appear in the default element picker; its sidecar flag exposes it; its body renders verbatim
  • button and icon work inline inside element bodies (e.g. mid-sentence in a hero) and round-trip canonically
  • No template emits inline styles or references third-party assets; the only script is video-embed's self-contained consent loader
  • The round-trip corpus contains at least one canonical fixture per element and the suite passes
  • The sample site demonstrates every element on example pages; the site builds and renders in the live preview, and every element's params are editable through the generated form

Out of scope:

  • Theme styling, CSS, navigation, and the preview-marker (ce/attrs) partial — the basic theme issue (#15)
  • The element picker UI, add/remove/reorder/nest interactions, and placement enforcement (#6) — this issue only declares placement metadata
  • Rich-text editing of bodies (#7) and inline chip UX for button/icon in the RTE (#8)
  • The media library and image picker (#12) — image params here are plain path references per #3
  • Click-to-select from the preview (#16)
  • Any new field types or schema-machinery redesign beyond what the library strictly requires
> *This was generated by AI during triage.* ## Agent Brief **Category:** enhancement **Summary:** Ship the complete v1 element library: every system element as a Hugo shortcode template (`layouts/shortcodes/X.html`) plus an editor sidecar (`editor/elements/X.yaml`), with semantic theme-agnostic markup, full editability through the schema-generated forms, round-trip test coverage for every element, and a rendered example of each on the sample site. **Dependency note:** this issue is **hard-blocked by #3** (sidecar schema loading/validation, schemas API, generated forms, canonical save path) — the scheduler handles ordering. #3 ships the schema machinery plus two demonstration elements; this issue fills the library out to the full v1 set using the same sidecar shape and field types, changing the machinery only if a library element genuinely cannot be expressed. The issue body's `docs/DECISIONS.md D23` reference points at a file that is not committed — this brief is self-contained. **Current behavior:** The content engine round-trips shortcode-based content losslessly (its test corpus already exercises grid/column nesting, accordion with nested items, and a hero containing inline buttons — as syntax fixtures only). Once #3 lands, sidecars in `editor/elements/` are discovered, validated, served via the API, and rendered as generated param forms, with canonical save and live preview working end-to-end — but only for the couple of demonstration elements #3 adds. There is no shipped element library: an editor cannot build a real page out of grids, heroes, galleries, accordions, and the rest. **Desired behavior:** Every element below exists as a shortcode template plus a sidecar, is fully editable through the generated forms (all params expressible with #3's nine field types), and renders correctly in the live preview. *Structure group:* - **grid** — a row container holding nested column shortcodes; each column holds arbitrary block elements. Column widths come from a **fixed responsive set** of fractions (e.g. full, 1/2, 1/3, 2/3, 1/4, 3/4 — the exact set is the implementer's choice but must be small, documented, and expressed as classes); free-form widths are not offered. Responsive collapse behavior belongs to the theme. - **spacer** — self-closing; a size step from a small fixed scale, emitted as a class. *Content group:* - **text** — a markdown body, no chrome. - **text-media** — markdown body plus an image, with a side/position param (e.g. media left or right) emitted as a class. - **image** — single image with alt and optional caption; semantic `figure`/`figcaption` markup. - **gallery** — multiple images. #3's field types are scalar, so multi-image content is modeled structurally (e.g. nested per-image item shortcodes, mirroring the accordion pattern) — whatever the shape, it must round-trip canonically and be editable element-by-element. - **hero** — heading (and similar params) plus a markdown body that may contain inline `button` shortcodes mid-text. - **quote** — quotation body plus attribution params; `blockquote`-based semantic markup. - **video-embed** — privacy-friendly click-to-load: the initial page renders a local placeholder/facade that performs **zero third-party network requests** (no provider thumbnails, scripts, or fonts); only an explicit user click loads the provider embed (privacy-enhanced endpoints where the provider offers them). The consent mechanism is a small self-contained script/markup shipped with the site — no external dependency, no framework. - **accordion** — a container of nested item shortcodes, each item carrying a title param and a markdown body; items are managed as nested block elements. Prefer natively interactive semantic markup (e.g. `details`/`summary`) so the element works unstyled and without JS. - **page-teasers** — given a section (and optionally a limit), renders title, summary, and link for that section's **non-draft** child pages; draft pages never appear even when the preview server builds drafts. - **html** — raw passthrough body rendered verbatim. Its sidecar carries a developer-only flag: the element is **hidden from the element picker by default** and only exposed when the flag/sidecar says so; existing `html` elements on a page remain visible and editable regardless. *Inline group:* - **button** — self-closing inline shortcode (href, label, optional variant) rendering an anchor; usable mid-sentence inside element bodies. - **icon** — self-closing inline shortcode identified by an icon name; the markup identifies the icon (class or data attribute) so themes can render the glyph. *Markup contract.* All templates emit semantic, theme-agnostic HTML: meaningful elements, a consistent documented class vocabulary, **classes only — no inline styles**, no CSS shipped by this issue, no JS except video-embed's minimal consent loader, and no third-party assets anywhere. Accessibility basics are in the markup itself (alt on images, real headings, focusable/labelled interactive parts). The library must look acceptable-but-unstyled on a bare site; making it pretty is the theme's job. *Sidecar contract.* Every sidecar provides label, icon identifier, picker group (structure/content/inline), schema version, body policy, and params, using #3's shape and field types. Containers and their items declare placement metadata (what may nest where — grid columns accept block elements, accordion accepts only its items, items name their container, inline elements are body-level); this issue **declares** the rules so #6 can enforce them. All sidecars must load through #3's validator with zero errors and appear in the schemas API with their group and icon metadata; if #6's picker exists by implementation time, it shows the elements grouped Structure/Content with icons — otherwise grouping is verified through the API. *Tests and demonstration.* The content engine's corpus round-trip suite gains at least one canonical fixture per element (covering nesting for grid and accordion and inline button/icon inside bodies), so every element's serialized form is locked in. The sample site gains example pages demonstrating every element, building cleanly and rendering in the preview. **Key interfaces:** - The sidecar schema shape and nine field types from #3 — consumed, not redesigned. If an element is inexpressible (e.g. gallery), prefer structural nesting over inventing new field types. - Placement metadata in sidecars — declared here, enforced by #6. - The shortcode templates' class vocabulary and DOM structure — this is the contract the theme (#15) styles against; keep it stable and document it (names, modifiers, nesting). - The content engine's canonical serializer — every element's authored form must be canonical (fixtures parse and re-serialize to identical bytes). **Acceptance criteria:** - [ ] Each of grid (with its column shortcode), spacer, text, text-media, image, gallery, hero, quote, video-embed, accordion (with its item shortcode), page-teasers, html, button, and icon has both a shortcode template and a sidecar - [ ] All sidecars pass #3's validation with zero errors and are served with group (structure/content/inline) and icon metadata; the picker, where present (#6), shows them grouped with icons - [ ] Grid columns nest arbitrary block elements and use widths from the fixed documented set; sidecar placement metadata declares the container/item rules for grid and accordion - [ ] Accordion items are nested block shortcodes, each editable as its own element with title and body - [ ] Loading a page containing video-embed triggers no third-party network request until the user clicks; after the click the video plays - [ ] page-teasers lists title, summary, and link of the chosen section's non-draft child pages; a draft child never appears - [ ] The html element does not appear in the default element picker; its sidecar flag exposes it; its body renders verbatim - [ ] button and icon work inline inside element bodies (e.g. mid-sentence in a hero) and round-trip canonically - [ ] No template emits inline styles or references third-party assets; the only script is video-embed's self-contained consent loader - [ ] The round-trip corpus contains at least one canonical fixture per element and the suite passes - [ ] The sample site demonstrates every element on example pages; the site builds and renders in the live preview, and every element's params are editable through the generated form **Out of scope:** - Theme styling, CSS, navigation, and the preview-marker (`ce/attrs`) partial — the basic theme issue (#15) - The element picker UI, add/remove/reorder/nest interactions, and placement **enforcement** (#6) — this issue only declares placement metadata - Rich-text editing of bodies (#7) and inline chip UX for button/icon in the RTE (#8) - The media library and image picker (#12) — image params here are plain path references per #3 - Click-to-select from the preview (#16) - Any new field types or schema-machinery redesign beyond what the library strictly requires
Author
Owner

Closing as superseded: the maintainer has decided on a clean-slate reset of the project (issue #29, PR #30). The v1 implementation this issue builds on is being removed and the plan will be re-drawn from scratch; this spec is retired rather than actioned.

Closing as superseded: the maintainer has decided on a clean-slate reset of the project (issue #29, PR #30). The v1 implementation this issue builds on is being removed and the plan will be re-drawn from scratch; this spec is retired rather than actioned.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
Cloonar/deckle#14
No description provided.