6.8 KiB
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.yamlautoconnectkeys'on'/'off'are properly quoted — avoids the YAML 1.1 boolean footgun (on:parsing astrue:).default: 'on'is quoted too.user/blueprints/config/site.yamlfollows the standard Grav pattern for extending system site config (fields merge into Admin → Configuration → Site);validation: loosepresent; thepagesfield options (start_route,show_root,show_slug) are all real options.entry.yamlcorrectly 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_chas 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 |
<br> in help text |
trip.yaml:61,73 |
If Admin2 escapes HTML in help tooltips, users see literal <br> 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)
- F2: add
validate: { type: float, min/max }to all four lat/lng fields (entry + story). - 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), andforce_connect;import@it from entry and story. Follow the Quark example. - F5 quick fixes:
travellingdefault →0; standardize date fields ondatetime+format: 'Y-m-d'(matches the established Admin2 datepicker fix).
Phase 2 — Structural decision (needs Mischa's call)
- F1: recommended: add
@extends: defaultto 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. - F4: switch entry + story
hero_imagetopagemediaselect(naturally bundles with the Phase 2 Admin verification pass).
Verify-once checklist (manual, 5 minutes in Admin2)
- Trip page → Cover Image dropdown: do
.gpxfiles appear? (If yes, theacceptfilter isn't applying — F5.) use_gpx/autoconnecthelp tooltips: rendered line breaks or literal<br>?- Decide: whole-degree temperatures OK, or add
steptoweather_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
- F1: Is the locked-down Admin UI for story/trip/home deliberate? (Recommendation above assumes it isn't for story/trip.)
- Should
transport_modefor stories includeplane(superset) or stay intentionally narrower?