# 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?