Files
summercms/internal/build/stubs/new.tmpl
Jakub Zych 5b09b32512 feat(diary): channels, components and config/log.yaml
- stderr and null drivers; per-component levels from log.components
- SUMMER_LOG__ overrides parse as strings and overlay the defaults key by key
- Validation names the key: driver, format, level, days, stack children and cycles, daily path outside the root
- summer new writes config/log.yaml (stack of console and daily, river warn, http info)
- docs/services/logging.md: channels, config/log.yaml, component loggers, daily files, redaction
- Log keys in the configuration docs; ExampleFor backs the docs snippet
2026-10-21 11:48:25 +02:00

199 lines
7.9 KiB
Cheetah

{{define "new/go.mod"}}module {{.Module}}
{{.GoVersion}}
{{.Toolchain}}
require {{.Framework}} v0.0.0
replace {{.Framework}} => {{.Replace}}
{{end}}
{{define "new/config/app.yaml"}}name: {{.Name}}
debug: false
# The application key encrypts data at rest. Set SUMMER_APP__KEY in .env (a
# 32-byte base64 value); keep it out of this file and out of git.
key: ""
{{end}}
{{define "new/config/database.yaml"}}# Set SUMMER_DATABASE__DSN in .env; compose.yaml runs the matching PostgreSQL.
dsn: ""
{{end}}
{{define "new/config/http.yaml"}}body_limits:
# Request body limits in bytes. Keep them YAML numbers: values from the
# environment are strings and are rejected at boot.
default_bytes: 1048576
upload_bytes: 10485760
{{end}}
{{define "new/config/storage.yaml"}}# Uploads bucket, required by summer serve. A file:// URL is a local
# directory under the application working directory.
uploads:
bucket_url: "file://./storage/app/uploads"
public_path_prefix: "/storage/uploads"
{{end}}
{{define "new/config/log.yaml"}}# Logging, shaped like Laravel's config/logging.php: records go to the
# default channel, and a stack sends them to several channels at once.
# Override any key with a SUMMER_LOG__ variable, a double underscore
# separating path segments: SUMMER_LOG__CHANNELS__DAILY__DAYS=30.
default: stack
level: info
channels:
stack:
driver: stack
channels: [console, daily]
console:
# auto: styled lines on a terminal, logfmt otherwise (systemd, Docker);
# json writes JSON lines instead.
driver: console
format: auto
daily:
# One file per day under storage/logs (summer-YYYY-MM-DD.log), kept 14 days.
driver: daily
path: storage/logs/summer.log
days: 14
format: json
level: warn
components:
# Per-component levels. http: warn silences the request log.
river: warn
http: info
{{end}}
{{define "new/env"}}# Local secrets for this application: the database DSN, the application key
# and the admin token secret. .gitignore excludes this file; never commit it.
# Real environment variables override the values here.
SUMMER_DATABASE__DSN={{.DSN}}
SUMMER_APP__KEY={{.AppKey}}
SUMMER_ADMIN__JWT__SECRET={{.AdminSecret}}
{{end}}
{{define "new/env.example"}}# The variables .env sets. summer new wrote a .env with a fresh key; copy this
# file to .env only when you need to start over.
SUMMER_DATABASE__DSN={{.DSN}}
# A 32-byte base64 application key. Generate one with ./bin/{{.Name}} key:generate
# and paste only the key, without the leading check mark.
SUMMER_APP__KEY=
# Signs backend admin tokens; the admin refuses to start without it once a
# plugin registers an admin controller. summer new wrote a random value to .env;
# any long random string works, for example one from ./bin/{{.Name}} key:generate.
SUMMER_ADMIN__JWT__SECRET=
# Uploads bucket; config/storage.yaml already sets this default.
# SUMMER_STORAGE__UPLOADS__BUCKET_URL=file://./storage/app/uploads
# Configuration environment; selects the config overlay (default production).
# SUMMER_ENV=development
{{end}}
{{define "new/compose.yaml"}}# Local development database: docker compose up -d --wait
# PostgreSQL is published on the loopback address only, and the credentials
# match SUMMER_DATABASE__DSN in .env.
services:
postgres:
image: postgres:16
environment:
POSTGRES_USER: summer
POSTGRES_PASSWORD: summer
POSTGRES_DB: {{.Name}}
ports:
- "127.0.0.1:54320:5432"
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U summer -d {{.Name}}"]
interval: 2s
timeout: 3s
retries: 30
volumes:
pgdata:
{{end}}
{{define "new/gitignore"}}/bin/
/tmp/
/storage/
.env
go.work.sum
*.exe
{{end}}
{{define "new/CLAUDE.md"}}# CLAUDE.md
Guidance for AI coding agents working in this repository. `AGENTS.md` is a symlink to this file.
## What this is
`sm-{{.Name}}-app` is a SummerCMS application: a Go program built on the SummerCMS framework, module `{{.Framework}}`. `go.mod` replaces the framework with the local checkout at `{{.Replace}}`. That checkout is shared with every other application next to it: do not edit the framework from here. Change this application, or report the framework problem.
Framework documentation for agents:
- https://summercms.io/docs/llms.txt (index)
- https://summercms.io/docs/llms-full.txt (full text in one file)
## Commands
Run them from this directory.
```sh
docker compose up -d --wait # start PostgreSQL 16 on 127.0.0.1:54320
summer build # generate main.go and plugins.gen.go, build bin/{{.Name}}
summer dev # watch sources and rebuild
summer migrate # run plugin migrations
summer serve # start the HTTP server
summer make:plugin golem15.<name> # scaffold a plugin module under plugins/<name>
summer plugin:add plugins/<name> # register it in summer.yaml, go.mod and go.work
summer make:admin-controller golem15.<plugin> <Name> # scaffold an admin controller with its YAML
summer admin:create --email you@example.com --superuser # create a backend administrator (password prompted)
```
## Layout
- `summer.yaml`: the application manifest (module path, binary name, ordered plugin list).
- `plugins/`: local plugin modules.{{if not .NoPlugin}} `plugins/{{.Name}}` is the starter plugin `golem15.{{.Name}}`; its `routes.go` answers `GET /` with JSON.{{end}}
- `config/`: YAML configuration (`app.yaml`, `database.yaml`, `http.yaml`, `log.yaml`, `storage.yaml`). Any key can be overridden with a `SUMMER_` environment variable, a double underscore separating path segments (`SUMMER_DATABASE__DSN` sets `database.dsn`).
- `.env`: local secrets (database DSN, application key, admin token secret). Never commit it; `.gitignore` excludes it. `.env.example` lists the variables.
- `compose.yaml`: the local PostgreSQL 16.
- `main.go`, `plugins.gen.go`: generated by `summer build` from `summer.yaml`. Do not edit them by hand; they are committed.
- `go.work`: the workspace that joins the application and its plugin modules.
Plugins are Go modules compiled into the binary at build time; there is no runtime plugin loading. Add a plugin with `summer make:plugin` and `summer plugin:add`, then run `summer build`.
## Admin
The backend admin (the admin SPA and its JSON API) lives under `/backend`, at `http://127.0.0.1:8080/backend` with the default `summer serve` address. It is mounted only when a plugin registers an admin controller; until then `summer serve` prints `admin: off`. To add it:
1. `summer make:admin-controller golem15.<plugin> <Name>` scaffolds the controller and its YAML. The generated controller requires the permission `golem15.<plugin>.access_<name>` (`<name>` is the controller name in snake case): declare it in the plugin's `Permissions()` (`pact.HasPermissions`) or the admin refuses to start. Its `NewRecord` returns `nil` until you return the plugin's model.
2. `summer build`, then `summer migrate`.
3. `summer admin:create --email you@example.com --superuser` creates the first administrator; the password is prompted.
`.env` already holds `SUMMER_ADMIN__JWT__SECRET`, which signs admin tokens.
## Naming convention
- `sm-<name>-app`: an application, like this repository.
- `sm-<name>-plugin`: a standalone plugin module.
- `sm-<name>-theme`: a Nuxt/Vue frontend.
{{end}}
{{define "new/next-steps"}}
Next steps, inside sm-{{.Name}}-app:
docker compose up -d --wait
summer build
summer migrate
summer serve
{{if .NoPlugin}}
The app has no plugins yet. Add one with summer make:plugin golem15.<name>
and summer plugin:add plugins/<name>, then run summer build again.
{{else}}
Then, from another terminal:
curl http://127.0.0.1:8080/
{{end}}
Admin, at http://127.0.0.1:8080/backend once a plugin registers an admin
controller (.env already holds SUMMER_ADMIN__JWT__SECRET):
summer make:admin-controller golem15.<plugin> <Name>
summer build
summer migrate
summer admin:create --email you@example.com --superuser
{{end}}