m038andClaude Opus 5 185f44bf54 docs(claude-md): fix four stale facts; document testing, dev commands, patches
Audit of the root CLAUDE.md (scored 76/100) found the architecture and
remote-ops coverage strong but the test workflow entirely undocumented and
several facts drifted from the tree.

Corrections (verified against the checkout):
- active_trip was japan-korea-2026; committed value is /trips/denmark-2026
  and no japan-korea trip folder exists. Also note the value is a route.
- Admin2 2.0.10 -> 2.0.12 (installed version).
- demo-load/demo-reset described as italy-only; the Makefile loops over every
  fixture trip under user/docs/demo/trips/.
- user/ gitignore claim omitted the three un-ignored site-owned plugins and
  the secret/env exclusions.

Additions:
- Section 3 "Testing": make test/test-config/test-post/test-ui, the
  auto-created testrunner account, Playwright layout, the auth.setup.js
  storageState dependency, and GRAV_BASE_URL for worktree servers.
- Local dev command table, plus which theme assets are build outputs
  (js/src -> bundles) versus hand-authored (css/style.css, css/tokens.css).
- Custom plugins: story-blocks and entry-actions alongside cache-on-save.
- Local plugin patches: install-plugins overwrites git-ignored third-party
  plugins; deploy/patches/ + apply-plugin-patches is the tracked fix path.
- travel-memories service on 8082; make pixelfed-import.

Every make target and file path referenced was verified to resolve.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-24 20:26:10 +02:00

into the east — Grav CMS

Grav CMS travel blog. Local dev via Docker; production on a VPS managed entirely through make.


Repository structure

Two git repos:

Repo Contents Location
intotheeast.com (this repo) Docker setup, Makefile, scripts, plugins.txt ./
intotheeast.com-content Site config, pages, theme user/ (standalone git repo)

The user/ directory is a standalone git repo — its changes are pushed/pulled independently to Gitea. The Grav Sync plugin on the server automatically pulls from Gitea when content is pushed.


Prerequisites

  • Docker (for local dev)
  • SSH access to the production server
  • Both Gitea repos created and accessible
  • A Gitea personal access token with repo read/write access

Local development setup

cp .env.example .env   # fill in your values — never commit this file
make setup             # start Docker container and install plugins

Site runs at http://localhost:8081.

Clone the user content repo into user/ if not already present:

git clone $USER_REPO user/

First-time server setup

1. Fill in .env — copy .env.example and set all values including REMOTE_USER, REMOTE_HOST, USER_REPO, MAIN_REPO, and Gitea credentials.

2. Run the install:

make remote-install

This SSHes into the server, downloads Grav, clones both repos (user content + this config repo), installs plugins, and prints the server's SSH public key.

3. Add the SSH key to Gitea — copy the printed public key and add it as a read-only deploy key to both Gitea repos. After this, make remote-fetch works without credentials.


Content sync workflow

To pull editor changes locally:

make content-pull   # pull latest user/ content from Gitea → local

To push local changes to Gitea (triggers server sync):

git -C user add -A && git -C user commit -m "content: describe change"
make content-push   # push local user/ commits → Gitea

All commands

Local

Command Description
make start Start the local Docker container
make stop Stop the local Docker container
make setup Start container and install all plugins from plugins.txt
make install-plugins (Re)install plugins from plugins.txt in the local container
make content-push Push local user/ commits to Gitea
make content-pull Pull latest user/ content from Gitea

Remote credentials

Command Description
make remote-env-setup Write Gitea credentials to ~/.env-intotheeast on the server
make remote-env-remove Delete ~/.env-intotheeast from the server

Always run make remote-env-remove when done. Credentials must not persist on the server.

Remote server management

Command Description
make remote-install First-time install: download Grav, clone both repos, install plugins
make remote-fetch Pull latest config repo (Makefile, scripts, plugins.txt) on the server
make remote-install-plugins Install/update plugins from local plugins.txt on the server
make remote-upgrade-grav Upgrade Grav core on the server
make remote-clean Clear Grav cache on the server
make remote-maintenance-on Enable maintenance mode (visitors see offline page)
make remote-maintenance-off Disable maintenance mode

Typical upgrade workflow

make remote-maintenance-on
make remote-upgrade-grav
make remote-install-plugins
make remote-clean
make remote-maintenance-off

Plugins

Plugins are not committed to git. The full list is in plugins.txt — one plugin name per line.

  • Locally: make install-plugins
  • On server: make remote-install-plugins

Template behaviour

Key design decisions that affect how pages render:

Context Sort order Reason
Trip page (trip.html.twig) Ascending (oldest first) Trip reads as a narrative from start to finish
Homepage active-trip feed (home.html.twig) Descending (newest first) Visitors want to see what's happening right now

Homepage modes — controlled by travelling in user/config/site.yaml:

travelling Homepage shows
true Active trip map + chronological feed (newest first)
false Map with highlight markers + curated highlights grid (max 6, 1 per trip, random)

Entries and stories opt into the highlights grid via featured: true in their frontmatter. The active_trip field stores a full page route (e.g. /trips/italy-2026-demo), not a bare slug.

Per-trip map settings — configurable in Admin2 under the Trip tab:

Setting Values Default Notes
use_gpx Yes / No Yes Draws uploaded GPX files as route lines on the map
autoconnect off / on / manual / intelligent_gpx on Controls connector lines between location markers

Connect markers behaviour:

Value Behaviour
off No connector lines; force_connect on entries is also ignored
on Dashed connector between every entry in date order
manual No automatic lines; only entries with force_connect: true are linked
intelligent_gpx Suppresses the connector where a GPX track covers the route; force_connect overrides. Requires use_gpx enabled — falls back to on if GPX is off or no files are present

use_gpx and autoconnect are independent: you can show GPX tracks without connector lines or vice versa.


Security

  • .env is gitignored. Never commit it — it contains your server credentials and Gitea token.
  • GITEA_TOKEN exists only in .env locally, and in ~/.env-intotheeast on the server only during active sessions. Always run make remote-env-remove after use.
  • ~/.env-intotheeast has chmod 600 — readable only by the SSH user.
  • The server pulls from Gitea using its SSH deploy key (read-only). No long-lived token is stored on the server after initial install.
  • scripts/server-install.sh writes ~/.netrc for the initial clone only, and deletes it immediately after via a trap handler — even if the script fails.
  • Credentials are never passed as command-line arguments (they would appear in server process listings). They are passed as environment variables within the SSH session.
S
Description
No description provided
Readme
1.5 MiB
Languages
JavaScript 81.7%
Makefile 10.4%
Shell 6.3%
Python 1.2%
Dockerfile 0.4%