Files
intotheeast-com/docs/research/story-editing.md
T

8.7 KiB
Raw Blame History

Story Editing Research

Brainstorming session — 2026-06-20. Notes on options for improving the story editing experience in Admin2. Not a plan — a reference to revisit once real story writing reveals what actually matters.


The core problem

Stories use shortcode syntax ([scrolly-section image="x.jpg"]…[/scrolly-section]) authored in a single big markdown textarea in Admin2. Three pain points, roughly equal weight:

  1. Fragile syntax — easy to typo a shortcode and get no useful error
  2. Writing blind — no preview while editing; you don't see the result until you view the page
  3. Mobile unusable — Admin2 is desktop-focused; the markdown textarea on a phone is painful

What Keystatic / Sanity / Shorthand taught us

All three tools represent content as a typed, ordered list of blocks — not a text string.

In Keystatic the editing flow is: write prose normally → click "+" → pick a block type from a list → fill in a form with labelled fields → the block appears as an opaque card in the editor. Authors never see markup. Each block type (hero, gallery, scrolly section) has a typed schema (image picker, text fields, selects). Sanity's Portable Text uses the same model. Shorthand (used by BBC, Reuters, National Geographic) is a purpose-built CMS for exactly this kind of immersive storytelling — their section vocabulary is the best reference for what block types matter in practice.

Key insight: the gap between Grav and these tools is entirely on the authoring side. Grav's rendering (Twig templates, shortcodes, parallax effects) is perfectly capable. The problem is that Admin2 was not designed for structured block content authoring.


Snow Fall block vocabulary

The canonical block types that appear across all immersive storytelling platforms:

Block What it does Fields
Hero Full-bleed opening image/video + title. Chapter opener. image, headline, subtitle, text position, animation (static / ken-burns)
Narrative text Prose reading column. The writing block. body (markdown)
Full-bleed media Single image/video edge-to-edge, no text. Visual pause. image, caption, credit
Image + caption Photo at configurable width with caption below. image, caption, credit, width (column / full / bleed)
Scrollytelling Text panels scroll over a fixed or animated background. background image, panels (each: headline + body)
Photo gallery Multi-image carousel/grid → lightbox. images (each: file + caption + credit)
Pull quote Typographically large extracted quote. quote text, attribution, optional background
Chapter break Major section transition with background image. image, title, chapter number
Grid / side-by-side 23 column photo+text pairs. columns array
Embed YouTube, Vimeo, audio, map. URL, caption

Current Grav shortcodes cover: hero (ken-burns), scrollytelling (scrolly-section), gallery (snap-gallery), pull-quote, chapter-break. Missing from the vocabulary: narrative text as an explicit block, full-bleed media, image+caption, grid, embed.


The two fundamental approaches

A — Blueprint-as-blocks (no shortcodes)

Replace the markdown body with a list field in the story blueprint. Each list item is a block with a type selector + type-specific sub-fields. Content lives in frontmatter YAML; the Twig template loops over blocks and renders each one with the right partial. No shortcode syntax at all.

Solves all three pain points. Admin2 form fields are mobile-reasonable. Structure is explicit and impossible to mis-type.

One limitation: Grav's native list field doesn't hide/show fields based on the selected type. Every block card shows ALL fields for ALL block types; the template ignores the unused ones. It's visually cluttered but functionally correct. This is a solvable UX problem (Grav roadmap, or a future Admin2 extension) — the data model stays the same when it improves.

B — Enhanced markdown (keep shortcodes, improve authoring UX)

Keep the markdown textarea; add tooling on top to reduce friction. Multiple options here (see section below), but all hit an architectural constraint: Admin2 serves its SPA via echo $html; exit which bypasses Grav's entire output pipeline. Standard plugin hooks for injecting assets don't fire in Admin2. Any JS-based editor enhancement requires either a fragile output-buffering hack or patching Admin2's pre-built app/index.html directly.


15 options researched

Options that work natively (no Admin2 hacking required)

1. Blueprint-as-blocks — structured YAML fields per block, native Admin2 form rendering. Best long-term solution for non-technical story editing and mobile. Medium effort (blueprint YAML + Twig template rework). The field-clutter limitation is real but acceptable.

2. page-inject sub-pages — each story block is a standalone Grav sub-page; the parent story injects them in sequence via [plugin:page-inject]. Editing = opening sub-pages individually. More flexible than blueprint-as-blocks for reusable content but creates more pages to manage and Admin2 navigation friction.

3. New shortcodes via YAML + Twig — shortcode-core supports YAML-configured Twig shortcodes out of the box (shortcode-core.yaml + a Twig file in the theme). No plugin needed. Used to add full-bleed and image-caption to the story-blocks plugin.

4. Obsidian + Gitea git sync — write stories in Obsidian on desktop or mobile with snippet templates for shortcodes. Push to Gitea; webhook deploys to production. Zero dev work. Good mobile writing experience. No image upload from mobile; requires comfort with git.

5. /story-editor custom page — a purpose-built page (like /gpx-manager) that presents story blocks as drag-reorderable cards with typed forms, talks to the Grav API, designed mobile-first. Highest effort; best mobile result. Would use the "one custom plugin" slot.

Options blocked by Admin2's architecture

All of these require injecting JavaScript or CSS into Admin2 pages, which is architecturally blocked (Admin2 bypasses Grav's output pipeline with echo $html; exit):

  • EasyMDE / SimpleMDE drop-in (split-pane markdown preview)
  • CodeMirror 6 autocomplete + syntax highlighting for shortcodes
  • Toast UI Editor (WYSIWYG ↔ markdown toggle)
  • Tiptap custom shortcode nodes
  • Milkdown
  • Slash-command / shortcode palette
  • Toolbar-at-bottom CSS (mobile improvement)
  • Web Speech API dictation button

Workaround: patch Admin2's pre-built app/index.html directly. Survives until the next Admin2 update; a make patch-admin2 command would re-apply it. Viable for a personal blog but adds a maintenance step.

Paid option

Grav Editor Pro ($75) — TipTap/ProseMirror-based WYSIWYM editor, confirmed Admin2- compatible (listed as an optional dependency in the Admin2 README ≥ v2.0.1). When paired with shortcode-core, shortcodes appear as visual green blocks with a modal form per type. This is the cleanest story editing experience available without building it yourself. Ruled out based on preference to avoid paid tools.


Honest CMS comparison: Grav vs Keystatic for storytelling

Wrong conclusion: Grav can't do Snow Fall storytelling.

Right conclusion: Grav's rendering side (parallax, scrollytelling, ken-burns, galleries) is fully capable. The authoring experience for structured block content is the genuine weak point — and the options to improve it cleanly within Admin2 are limited.

Keystatic + a modern frontend (Astro, Next.js) would give a better editorial experience for story authoring, but at the cost of migrating away from Grav and building a separate frontend. For a solo travel blogger who is the only author, Grav with an improved shortcode setup or blueprint-as-blocks is good enough. Keystatic's advantage is significant for publications with multiple non-technical editors writing daily.


What was actually done (2026-06-20)

  • Added full-bleed shortcode to story-blocks plugin (PHP class + CSS)
  • Added image-caption shortcode to story-blocks plugin (PHP class + CSS), with width parameter: column (default) / full / bleed
  • Next step when ready to revisit: write some actual stories, then decide whether blueprint-as-blocks or the app/index.html patch route is worth pursuing

References