diff --git a/docs/future/blueprint_milestone/2026-07-08-blueprint-vetting.md b/docs/future/blueprint_milestone/2026-07-08-blueprint-vetting.md new file mode 100644 index 0000000..26c0e23 --- /dev/null +++ b/docs/future/blueprint_milestone/2026-07-08-blueprint-vetting.md @@ -0,0 +1,93 @@ +# Blueprint Vetting — Research & Recommendation + +**Status:** 📋 Not started +**Date:** 2026-07-08 +**Scope:** All custom Grav blueprints (intotheeast theme page blueprints, theme blueprint, site-config extension). Stock Quark blueprints excluded. + +## Files reviewed + +| File | Purpose | +|---|---| +| `user/themes/intotheeast/blueprints/entry.yaml` | Daily journal entry (Admin form) | +| `user/themes/intotheeast/blueprints/story.yaml` | Story pages | +| `user/themes/intotheeast/blueprints/trip.yaml` | Trip pages | +| `user/themes/intotheeast/blueprints/home.yaml` | Home page | +| `user/themes/intotheeast/blueprints.yaml` | Theme blueprint (identity only) | +| `user/blueprints/config/site.yaml` | Site-config extension (`active_trip`, `travelling`) | + +## What's already good + +- Toggle idiom is correct and consistent everywhere: `options: {1: Yes, 0: No}` + `validate: type: bool`. +- `trip.yaml` `autoconnect` keys `'on'`/`'off'` are properly quoted — avoids the YAML 1.1 boolean footgun (`on:` parsing as `true:`). `default: 'on'` is quoted too. +- `user/blueprints/config/site.yaml` follows the standard Grav pattern for extending system site config (fields merge into Admin → Configuration → Site); `validation: loose` present; the `pages` field options (`start_route`, `show_root`, `show_slug`) are all real options. +- `entry.yaml` correctly uses `@extends: {type: default, context: blueprints://pages}` and adds its fields as a new tab, so entries keep the full standard Admin UI. +- Required-field validation on story/home titles and story content is in place. +- `weather_temp_c` has sensible min/max bounds (−60…60). + +## Findings + +### F1 — Only `entry.yaml` extends the default page blueprint (structural) + +`story.yaml`, `trip.yaml`, and `home.yaml` define `form.fields.tabs` from scratch (no `@extends`). In Admin2 those page types show **only** the declared fields — no Options/Advanced tabs, so no slug rename, no ordering, no visibility, no publish dates, no taxonomy from Admin. The custom `header.published` toggles in story/trip partially compensate. + +If the locked-down UI is deliberate, entry is the inconsistent one; if not, story/trip lose real capabilities (they're created repeatedly and may need slug/ordering control). + +**Implementation note if extending:** story/trip use a tab key `content`, which collides with the default blueprint's Content tab — fields merge by key, so the duplicate `header.title`/`content` definitions override rather than duplicate, but the merged result needs a visual check in Admin. Their custom `header.published` toggle also becomes redundant with the default Options-tab toggle — keep one. + +### F2 — `lat`/`lng` are free-text with no validation (data integrity) + +`entry.yaml:27-35` and `story.yaml:64-74` declare latitude/longitude as plain `type: text`. Templates pipe the values straight into `number_format(6, …)` (`user/themes/intotheeast/templates/trip.html.twig:62`, `templates/home.html.twig:56`). PHP casts silently: + +- European decimal comma `"35,0116"` → `35.000000` (marker subtly wrong) +- non-numeric garbage → `0.000000` (marker in the Gulf of Guinea) + +No error surfaces anywhere. Fix: `validate: { type: float, min: -90, max: 90 }` for lat, `±180` for lng. + +### F3 — `transport_mode` option drift (copy-paste divergence) + +Entry offers `plane` (`entry.yaml:77`); story doesn't (`story.yaml:80-86`). The field — along with lat/lng, location, `force_connect` — is duplicated between the two blueprints, which is how drift happens. Grav supports shared partials via `import@`; in-repo example: `user/themes/quark/blueprints/blog.yaml:90` importing `partials/blog-bits.yaml`. + +### F4 — `hero_image` UX inconsistency + +Trip uses `pagemediaselect` (dropdown of uploaded media, `trip.yaml:40-44`); entry and story use free-text filename fields (`entry.yaml:60-64`, `story.yaml:33-37`) where a typo silently breaks the hero. `pagemediaselect` keeps the "blank = first image" fallback while removing typo risk. + +### F5 — Minor items + +| Item | Location | Detail | +|---|---|---| +| `travelling` default mismatch | `user/blueprints/config/site.yaml:15` | `default: false` vs option keys `1`/`0`; works via loose comparison, but `default: 0` matches every other toggle | +| Date type drift | `story.yaml:20-31` vs `trip.yaml:28-38` | story: `datetime` + `format: 'Y-m-d'` (the deliberate Admin2 datepicker fix); trip: plain `date`. Pick one convention | +| `
` in help text | `trip.yaml:61,73` | If Admin2 escapes HTML in help tooltips, users see literal `
` tags | +| `weather_temp_c` step | `entry.yaml:52-58` | HTML number inputs default to step 1 → `19.5` may be rejected client-side; fine if whole degrees are intended | +| `pagemediaselect` accept filter | `trip.yaml:42` | Extension-style `accept: ['.jpg', …]` is the filepicker convention; unverified against Admin2's SPA implementation | + +## Recommendation + +Treat as one small milestone in three parts, in this order: + +### Phase 1 — Data-integrity + drift fixes (no decisions needed, low risk) + +1. **F2:** add `validate: { type: float, min/max }` to all four lat/lng fields (entry + story). +2. **F3:** extract a shared theme partial `user/themes/intotheeast/blueprints/partials/` (e.g. `location-bits.yaml`) holding location name/country, lat/lng (with the new validation), `transport_mode` (superset incl. `plane`), and `force_connect`; `import@` it from entry and story. Follow the Quark example. +3. **F5 quick fixes:** `travelling` default → `0`; standardize date fields on `datetime` + `format: 'Y-m-d'` (matches the established Admin2 datepicker fix). + +### Phase 2 — Structural decision (needs Mischa's call) + +4. **F1:** recommended: add `@extends: default` to **story and trip** (repeatedly-created content pages that benefit from slug/ordering/options control); leave **home** minimal (singleton whose slug must never change). Resolve the Content-tab merge and duplicate-published-toggle notes above. Verify each Admin form visually after the change. +5. **F4:** switch entry + story `hero_image` to `pagemediaselect` (naturally bundles with the Phase 2 Admin verification pass). + +### Verify-once checklist (manual, 5 minutes in Admin2) + +- [ ] Trip page → Cover Image dropdown: do `.gpx` files appear? (If yes, the `accept` filter isn't applying — F5.) +- [ ] `use_gpx` / `autoconnect` help tooltips: rendered line breaks or literal `
`? +- [ ] Decide: whole-degree temperatures OK, or add `step` to `weather_temp_c`? + +### Out of scope + +- Post form (`/post`) field parity — separate surface, not touched by this vetting. +- Theme blueprint (`blueprints.yaml`) — minimal but valid; no theme options exist yet, nothing to add. + +## Open questions + +1. **F1:** Is the locked-down Admin UI for story/trip/home deliberate? (Recommendation above assumes it isn't for story/trip.) +2. Should `transport_mode` for stories include `plane` (superset) or stay intentionally narrower?