Files

7.1 KiB

CLAUDE.md

0. Project specifics

Only ever write changes in this folder (travel-blog-intotheeast/) or its subfolders.

Folder explanation

  • ./: Grav CMS dev environment for intotheeast travel blog
  • scripts/: Server install and maintenance scripts
  • user/: Site content, config, pages, and theme (standalone git repo — do not modify from here)
  • docs/: All plans, specs, and project documentation (moved here from user/docs/ on 2026-06-19)

Current stack

  • Grav: 2.0.0-rc.10 (baked into the custom Docker image via Dockerfile)
  • Admin: Admin2 v2.0.0-rc.15 (plugin slug: admin2, NOT admin)
  • Docker image: getgrav/grav with GRAV_CHANNEL=beta
  • PHP session: session.save_path = /tmp set in php/php-local.ini

Dev server

The Docker dev server runs at http://localhost:8081 (mapped from container port 80 in docker-compose.yml).

Trip entity architecture

The site is structured around Trip entities. Key facts:

  • Active trip is set in user/config/site.yamlactive_trip: japan-korea-2026
  • Trip pages live at user/pages/01.trips/<slug>/
  • Each trip has: 01.dailies/, 02.map/, 03.stats/, 04.stories/
  • Site nav in base.html.twig has Home + Past Trips only — does not link to trip sub-sections
  • Post form parent (post-form.mdpageconfig.parent) must be kept in sync with active_trip
  • The trip page (trip.html.twig) uses a client-side filter bar (All content / Journal / Stories) — do NOT add nav links back to /dailies, /stats, /stories on the trip page
  • Stats are shown inline on the trip page via a toggle; the standalone /stats sub-page still exists as a URL but is not linked from the trip page
  • GPX route files live as media on the trip page itself, served via leaflet-gpx CDN
  • Manage GPX files (view/upload/delete) at /gpx-manager — requires admin login; filenames are auto-slugified on upload

GPX file management

GPX files are stored as page media on the trip page (user/pages/01.trips/<slug>/). They are picked up automatically by map.html.twig via trip_page.media.all.

The GPX manager page (user/pages/03.gpx-manager/) provides a browser UI at /gpx-manager:

  • Auth: enforced by Login plugin via access.admin.login: true in frontmatter — shows login form if not authenticated
  • Template: user/themes/intotheeast/templates/gpx-manager.html.twig
  • API: uses Grav API v1 with session cookie auth (session_enabled: true in user/plugins/api/api.yaml)
    • List: GET /api/v1/pages{route}/media
    • Upload: POST /api/v1/pages{route}/media (multipart)
    • Delete: DELETE /api/v1/pages{route}/media/{filename}
  • Slugification: filenames are slugified client-side before upload (spaces/special chars → hyphens, lowercase); the file is sliced to a plain Blob so the third argument to FormData.append is always used as the filename
  • Media type: .gpx is registered in user/config/media.yaml so Grav serves and tracks these files

To add GPX files without the browser UI, drop them directly into user/pages/01.trips/<slug>/ and run make content-push.

Switching to a new trip

Two places hardcode the active trip slug. Grav's config and page frontmatter are static YAML — no variable substitution is possible, so these cannot read from site.yaml automatically. Both must be updated together when starting a new trip, or entries will be posted to the wrong folder.

File Key Example value
user/config/site.yaml active_trip italy-2027
user/pages/02.post/post-form.md pageconfig.parent /trips/italy-2027/dailies

Note: system.yaml home.alias is permanently set to /home (the real home page) and does not need to change when switching trips.

After updating, also create the new trip's page tree under user/pages/01.trips/<new-slug>/ with the standard four subfolders.

Environment

Never read .env — it contains sensitive credentials. You may pass it to commands (e.g. docker compose, make) but never read its contents directly. Ask the user if you need environment-specific information.

Remote operations

Always use make commands for anything on the production server (make remote-install-plugins, make remote-clean, etc.) — never SSH directly since credentials live in .env. If a remote operation isn't covered by an existing make command, either ask the user to run it manually or suggest adding a new make command if it seems reusable.

Content sync

  • make content-push — commit and push user/ to Gitea (triggers production pull via webhook)
  • make content-pull — pull latest from Gitea to local
  • plugins.txt is manually maintained — installing a plugin via Admin does NOT update it
  • make demo-load — load demo content into italy-2026-demo trip (12 journal entries + 4 stories + 7 GPX files); source in user/docs/demo/trips/italy-2026-demo/
  • make demo-reset — remove the entire italy-2026-demo pages folder and clear cache (full reset; re-run demo-load to restore)

User repo gitignore

Only these folders are tracked in the user/ Git repo: pages/, config/, accounts/, themes/. The plugins/ and data/ folders are excluded.

1. Environment modes

Rule: do not switch modes during development

Never toggle between development and production mode mid-session. If a caching or config issue appears, fix it at the application level (plugin, template logic) rather than temporarily flipping a mode flag to work around it. Mode switches introduce inconsistent state and make bugs harder to reproduce.

Development mode (current)

Active settings in user/config/system.yaml:

Setting Dev value Why
twig.cache false Theme file edits take effect immediately; no stale compile errors

With these settings, Grav rebuilds templates on every request. This is intentionally slower but means you never need to flush cache after editing a .html.twig file.

Production mode (not yet configured)

Before going live, change in user/config/system.yaml:

Setting Prod value Why
twig.cache true Templates compiled once and reused; safe because theme files don't change at runtime

Pre-launch smoke test required: with twig.cache: true, submit one post via /post and confirm the entry appears in /trips/italy-2026-demo/dailies immediately. This verifies the cache-on-save plugin (BUG-001 fix) works correctly with caching enabled.

What the cache-on-save plugin handles

The custom plugin at user/plugins/cache-on-save/ clears Grav's page-tree cache on every new-entry form submission. This ensures new posts appear in the tracker feed immediately in both modes — it does not depend on whether Twig caching is on or off.

2. Local development setup

Full setup guide: docs/guides/local-setup.md

Superpowers skill paths

Specs: docs/working/specs/YYYY-MM-DD-<topic>-design.md Plans: docs/working/plans/YYYY-MM-DD-<topic>.md

The brainstorming and writing-plans skills default to docs/superpowers/; these lines override that default.