# Grav 2.0 Upgrade — Design Spec **Goal:** Upgrade the intotheeast travel blog from Grav 1.7.x to Grav 2.0 RC on a feature branch, validate full Milestone 1 functionality, and prepare a clean production fresh-install path. **Context:** Departure date is 2026-07-15. The production server has never been deployed, so production gets a fresh Grav 2.0 install — no in-place migration required. Local dev uses Docker; production uses PHP 8.4 directly. --- ## Scope Two tracks: 1. **Local dev track** — swap Docker image to Grav 2.0, validate all functionality 2. **Production track** — update `server-install.sh` and `.env` so `make remote-install` deploys Grav 2.0 fresh All work on branch `update-to-2.0`. --- ## Compatibility Assessment | Component | Status | Action required | |---|---|---| | `form`, `login`, `email`, `error`, `problems`, `flex-objects` | ✅ First-party | Auto-updated to 2.0 versions via GPM | | `shortcode-core` | ✅ First-party | Same | | `cache-on-save` (custom) | ✅ Should work | Add Grav 2.0 compat flag to `blueprints.yaml`; uses `onFormProcessed` which is unchanged | | `shortcode-gallery-plusplus` | ✅ Likely works | Plugin arch unchanged; test and confirm | | `add-page-by-form` | ⚠️ Archived Aug 2024 | Try as-is (plugin arch unchanged, may work); if broken, write a custom replacement | | Custom `intotheeast` theme | ✅ Should work | Twig 3 compat mode covers existing templates; test rendering | | `linuxserver/grav` Docker image | ❌ Not supported | Replace with `getgrav/grav` + `GRAV_CHANNEL=beta` | --- ## Track 1 — Local Dev ### Changes **`docker-compose.yml`** Replace: ```yaml image: lscr.io/linuxserver/grav:latest environment: - PUID=1000 - PGID=1000 volumes: - ./user:/config/www/user ``` With: ```yaml image: getgrav/grav environment: - GRAV_CHANNEL=beta volumes: - ./user:/var/www/html/user ``` **`Makefile`** — three targets reference the linuxserver internal path `/app/www/public`; replace with `/var/www/html`: - `install-plugins`: `docker exec -w /app/www/public` → `docker exec -w /var/www/html` - `demo-load` clear cache: `/app/www/public` → `/var/www/html` - `demo-reset` clear cache: same **`user/plugins/cache-on-save/blueprints.yaml`** (create — does not exist yet) — minimal blueprint with Grav 2.0 compat flag: ```yaml name: Cache On Save version: 1.0.0 description: Clears Grav cache on new-entry form submission author: name: Mischa license: MIT dependencies: - { name: grav, version: '>=1.6.0' } grav: version: ['1.7', '2.0'] ``` **`user/config/system.yaml`** — switch GPM to testing channel so `make setup` resolves 2.0-compatible plugin versions: ```yaml gpm: releases: testing ``` ### Validation Checklist (smoke test after `make setup`) Run in order — stop and investigate if any step fails: 1. **Site loads** — `http://localhost:8081` returns the tracker page (200, no PHP errors) 2. **Admin2 loads** — `/admin` renders the new SPA admin (not the old Twig admin) 3. **Login works** — log in via Admin2 with existing credentials 4. **Posting form** — submit `/post` form with title + text; entry appears immediately in `/tracker` 5. **Photo upload** — submit `/post` form with a photo; image renders in the entry 6. **Gallery** — visit an entry with multiple photos; `shortcode-gallery-plusplus` renders gallery with lightbox 7. **Cache invalidation** — submit a second post; it appears without a manual cache clear (validates `cache-on-save`) 8. **Theme rendering** — check tracker, entry, map, post-form, and stats templates for layout/CSS regressions 9. **Playwright suite** — `make test-ui` passes all 25 tests. If any tests fail, investigate whether the failure is a genuine regression (blocker) or a test that needs updating for Admin2's new DOM structure (acceptable — update the test) ### If `add-page-by-form` fails If step 4 fails due to `add-page-by-form` incompatibility, the fallback is to write a custom replacement plugin. The existing `cache-on-save` plugin is a good template — it hooks `onFormProcessed` and that API is unchanged. The replacement would use the same hook to: 1. Build the page path and slug from form fields 2. Create the page file on disk (same logic `add-page-by-form` does in PHP) 3. Clear cache (merging `cache-on-save` functionality) This is ~1 day of work and should be planned as a follow-up task if needed. --- ## Track 2 — Production (Fresh Install) Production has PHP 8.4 (compatible with Grav 2.0's PHP 8.3+ requirement) and has never been deployed. ### Changes **`server-install.sh`** — the download URL for Grav 2.0 RC requires a `?testing` query parameter: Current: ```bash wget --no-verbose "https://getgrav.org/download/core/grav-admin/$GRAV_VERSION" -O grav-admin.zip ``` Updated (conditionally append `?testing` for pre-release versions, or accept a full URL suffix via env var): ```bash wget --no-verbose "https://getgrav.org/download/core/grav-admin/${GRAV_VERSION}${GRAV_CHANNEL_SUFFIX}" -O grav-admin.zip ``` Where `GRAV_CHANNEL_SUFFIX` is `?testing` for RC versions and empty for stable. **`.env`** (not committed — edit on the server directly or locally before `make remote-install`) — update: ``` GRAV_VERSION=2.0.0-rc.9 GRAV_CHANNEL_SUFFIX=?testing ``` When Grav 2.0 goes stable, remove `GRAV_CHANNEL_SUFFIX` and update `GRAV_VERSION` to the stable version number. **`user/config/system.yaml`** — keep `gpm.releases: testing` (already set in Track 1) so production also installs 2.0-compatible plugin versions. ### Production deploy When local validation passes: ```bash make remote-install ``` That's it — fresh Grav 2.0 install from scratch with all plugins, content from Gitea, and the existing `user/` config. --- ## Out of Scope - MCP server setup (`grav-mcp` Node.js binary) — a separate task after Grav 2.0 is stable on production - Admin2 theming or customization - Grav 2.0 REST API integration - Switching `add-page-by-form` to the API-based approach (only if the plugin breaks) --- ## Go/No-Go Criteria Ship to production before departure (2026-07-15) **only if**: - All 9 smoke test steps pass - Playwright suite passes - `add-page-by-form` posting workflow works end-to-end (or a custom replacement is in place and tested) If any of these fail and cannot be resolved with time to spare before departure, stay on Grav 1.7 for the trip and revisit post-trip.