Files
summercms/CLAUDE.md

7.7 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

What this is

SummerCMS in Go: a content management framework modelled on WinterCMS/OctoberCMS, for the Golem15 stack. An application built on it compiles into one binary: framework modules, the application's plugins, the embedded admin SPA and console commands. Read README.md first (module table, quick start, development commands), then .planning/PROJECT.md and .planning/notes/ for decisions.

The core value: a WinterCMS-shaped app is ported plugin by plugin to a single Go binary without its frontend noticing. When porting endpoints, the existing frontend's requests (Nuxt app, MCP server) define the contract; response shapes are not "improved" during a port.

References: the WinterCMS starter at ../examples/golem15-wintercms-starter, the first port target Płytarium at /media/nvme/dev/golem15/fonoteka.

Commands

go vet ./...
go test -short ./...                         # fast loop, no Docker
go test ./...                                # also the testcontainers Postgres/Mailpit tests (needs Docker)
go test -short ./modules/cabana -run TestName  # one test
cd examples/hello && go test ./...           # separate workspace module, not covered by the root ./...

go install ./cmd/summer                      # the CLI
go test ./cmd/summer -run TestDocsTree       # docs checker
summer docs:build --check                    # docs checker (identifiers, links, anchors, src= snippets, command names)
summer docs:sync                             # refresh src= code copies in docs/ after changing their source

npm --prefix admin ci
npm --prefix admin run test | typecheck | build | dev
scripts/check-admin-openapi.sh [--check]     # swag annotations in cabana -> admin/openapi/admin.json -> admin/src/api/schema.d.ts
scripts/check-admin-dist.sh                  # committed modules/boardwalk/dist must match a fresh admin build
scripts/check-phaseN.sh                      # per-phase verification gates

Docker-backed tests skip under -short; a TestMain that starts containers must call flag.Parse() and check testing.Short() (go test passes -test.short=true, so scanning os.Args for -test.short misses it). If the Docker socket is denied although the user is in the docker group, the shell session predates the group; run the tests through sudo -u golem to pick up a fresh group list. Keep go vet and go test ./... green at every commit.

Architecture

  • One Go module, git.golem15.com/golem15/summercms; each package is imported as .../modules/<name>. Module names follow a beach theme, and each README carries a **Name:** mnemonic; a new module gets a fitting beach name, a README in the standard structure and a row in the root README.md table.
  • Compiled plugins. A plugin implements capability interfaces from pact (routes, config, migrations, middleware, commands, admin screens, translations, mail, jobs). summer build reads the application's summer.yaml, generates plugins.gen.go and main.go (internal/build) and builds the binary. party orders plugins by Requires() and runs Register(app) then Boot(app); backpack.App is the per-instance container (config, typed service registry via app.Lookup[T](), event bus, activated plugins). No runtime plugin loading (stdlib plugin, yaegi) without a decision note.
  • Request path. surf assembles plugin routes and named middleware onto a stdlib net/http ServeMux; bouncer authenticates (JWT, and personal API tokens resolved via cabana); towel carries actor/locale through context.Context; wire keeps JSON byte-compatible with the PHP (Laravel) backend.
  • Admin. Plugins describe lists, forms, filters and relations in WinterCMS-style YAML (columns.yaml, fields.yaml). cabana compiles them at boot and serves a JSON admin API (swag-annotated, see admin_openapi.go); boardwalk embeds the Vue 3 SPA from admin/, whose build output is committed in modules/boardwalk/dist. Before tagging a release that changes admin/, rebuild, commit the dist and pass check-admin-dist.sh (.planning/notes/2026-10-07-embedded-admin-release-gate.md).
  • Data. lagoon: GORM on Postgres only, per-plugin gormigrate migrations, model helpers, attachments (lagoon/attach). conga: River jobs on the same pool plus the summer_jobs record. YAML is parsed with goccy/go-yaml, never gopkg.in/yaml.v3 (archived).
  • Dependencies. Standard library first. A new dependency needs a research doc or a phase/decision note naming it (.planning/research/STACK.md has the decided set and versions).

Sibling repositories

The meta repo (..) holds the framework and its consumers side by side. Consumers require a tagged framework version (vX.Y.Z tags on master) and replace it with ../summercms.go during development:

  • fonoteka.go: Płytarium application (go.work workspace; app-specific plugins stay in-repo).
  • sm-*-app: other applications (sm-grzybyfunkcjonalne-app, sm-summercmsio-app, sm-bm-app).
  • sm-*-plugin: shared core plugins in their own repos, module path = repo path, mounted in apps as git submodules at plugins/<vendor>/<name> (.planning/notes/core-plugins-own-repos.md). Commit and push the plugin first, then the pointer bump in the app as a separate commit.
  • vue-journal-layer: public Nuxt layer consumed by site apps as a pnpm git dependency pinned by tag.

Framework code never names a consuming application (READMEs, docs, examples use neutral names like blog or acme).

Documentation rules

  • A change to a module's exported API, config keys, CLI commands or dependencies updates that module's README.md and the affected docs/ pages in the same commit.
  • Module README structure: H1 name, one-sentence summary, import line, **Name:** mnemonic, then Overview, Features, Usage, API reference, optional Configuration and CLI commands, Dependencies, Testing. The root table's purpose text reuses the summary sentence.
  • Every identifier in a README or docs page must exist in the package (the docs checker enforces it). Config keys are not checked automatically; review them by hand.

MSD workflow

Work goes through MSD (/msd-* commands; the older GSD tooling is retired): /msd-quick for small tasks (.planning/quick/), /msd-fast for trivial edits, /msd-debug, and /msd-discuss-phase → /msd-plan-phase → /msd-execute-phase for roadmap phases (.planning/ROADMAP.md, .planning/phases/). Urgent work is inserted as decimal phases (/msd-phase --insert). Don't edit the repo outside an MSD workflow unless the user says so.

Project rules that override MSD defaults:

  1. Lean planning. Few, large plans per phase. Before writing PLAN.md files, present the suggested plan count with a one-line scope each and wait for confirmation.
  2. Unit tests are the last plan of every phase. Earlier plans may carry smoke tests but are not blocked on coverage.
  3. State through handlers. Update .planning/STATE.md with msd_run query state.* handlers, not raw edits.
  4. g15office sync. Todos and phase milestone tasks are mirrored in g15office (.planning/G15OFFICE.md); post a short comment when a phase advances.

Commits and concurrency

  • No co-author tags. One logical change per commit; planning docs and code in separate commits.
  • Several Claude sessions often work in this repo at once (different phases, quick tasks). Stage files explicitly by path (never git add -A), leave other sessions' uncommitted edits (often STATE.md, state.json) alone, and check for in-flight edits before touching shared files such as cabana.
  • Don't push, tag or deploy without the user's go-ahead; deploys are documented per application (for example ../sm-grzybyfunkcjonalne-app/DEPLOY.md).