- NewOptions.AdminSecret: summer new writes SUMMER_ADMIN__JWT__SECRET to .env (still 0600), generated from 32 crypto/rand bytes when empty and validated as at least 32 .env-safe characters - .env.example gets an empty SUMMER_ADMIN__JWT__SECRET= placeholder with a comment; the secret never reaches the printed next steps - The next steps and the generated CLAUDE.md explain the admin at /backend: make:admin-controller, build, migrate and summer admin:create --email you@example.com --superuser - Goldens use a fixed, non-secret admin secret fixture - Scaffolding, installation and users-and-permissions docs updated
208 lines
10 KiB
Markdown
208 lines
10 KiB
Markdown
---
|
|
title: Installation
|
|
description: Create a SummerCMS application with one command, or install the summer CLI and build, migrate and serve the reference application by hand.
|
|
section: setup
|
|
order: 20
|
|
---
|
|
# Installation
|
|
|
|
SummerCMS is a Go module. An application requires it, lists its plugins in a `summer.yaml` manifest and builds everything into one binary with the `summer` CLI. This page starts with the one-command path that creates a new application, then walks through the manual path: installing the tool from a framework checkout and building the small reference application that ships with it.
|
|
|
|
## Create an application with one command
|
|
|
|
```sh
|
|
curl -fsSL https://summercms.io/new | bash -s -- demo
|
|
```
|
|
|
|
The script checks for Go 1.27 and Docker, fetches the framework at its latest release tag into `./summercms`, installs the `summer` CLI and runs `summer new demo`, which writes a ready-to-run application to `sm-demo-app`. Start its database, then build, migrate and serve it:
|
|
|
|
```sh
|
|
cd sm-demo-app
|
|
docker compose up -d --wait
|
|
summer build
|
|
summer migrate
|
|
summer serve
|
|
```
|
|
|
|
## What the script does
|
|
|
|
Run the one-liner from the directory that should hold both the framework checkout and the application. `bash -s -- demo` passes the application name to the piped script; the name must be lower-case letters and digits, starting with a letter.
|
|
|
|
1. It checks the prerequisites. Go older than 1.27 or missing, or a missing git, stops the script with an install hint before anything is cloned. A missing Docker or Docker Compose plugin is only a warning, because the application needs them to run its database, not to be created.
|
|
2. It clones the framework into `./summercms` and checks out the newest `vX.Y.Z` release tag, detached. When `./summercms` already exists, the script fetches tags and moves the checkout forward to the newest release only when that is a fast-forward. It refuses, without changing anything, a directory that is not a framework checkout, a checkout with changes to tracked files and a checkout that is on a branch.
|
|
3. It installs the `summer` CLI from that checkout with `go install ./cmd/summer`. When the Go install directory is not on your `PATH`, the script reads your login shell from `SHELL` and ends with `fish_add_path <dir>` in fish, which keeps the directory for new sessions, or with `export PATH="<dir>:$PATH"`, to add to `~/.zshrc` in zsh, `~/.bashrc` in bash or your shell profile in any other shell.
|
|
4. It runs `summer new demo` next to the checkout, with `--framework` pointing at it, which writes `sm-demo-app` and prints the next steps. The script itself ends with the `cd` line into the new application.
|
|
|
|
The script stops before cloning when the name is invalid or `sm-demo-app` already exists. Three environment variables change its defaults:
|
|
|
|
| Variable | Default | Purpose |
|
|
|----------|---------|---------|
|
|
| `SUMMERCMS_REPO` | `https://git.golem15.com/golem15/summercms` | Repository to clone. |
|
|
| `SUMMERCMS_DIR` | `summercms` in the current directory | Framework checkout; the application is created next to it. |
|
|
| `SUMMERCMS_REF` | the newest release tag | Tag or commit to check out instead. |
|
|
|
|
Set them on the `bash` side of the pipe, for example `curl -fsSL https://summercms.io/new | SUMMERCMS_DIR=fw bash -s -- demo`. The [sunrise](../../modules/sunrise/README.md) module holds the script itself.
|
|
|
|
## Run the application
|
|
|
|
The generated application brings its own database and configuration:
|
|
|
|
- `compose.yaml` runs PostgreSQL 16, published on `127.0.0.1:54320` only, so it does not clash with a PostgreSQL already on port 5432.
|
|
- `.env` holds the matching `SUMMER_DATABASE__DSN`, a freshly generated `SUMMER_APP__KEY` and a random `SUMMER_ADMIN__JWT__SECRET` for the admin. It is excluded by `.gitignore`; `.env.example` lists the same variables.
|
|
- `config/` holds `app.yaml`, `database.yaml`, `http.yaml` and `storage.yaml`, enough for `summer serve` and `route:list`.
|
|
|
|
From `sm-demo-app`, start the database, build the binary, run the migrations and serve:
|
|
|
|
```sh
|
|
docker compose up -d --wait
|
|
summer build
|
|
summer migrate
|
|
summer serve
|
|
```
|
|
|
|
From another terminal, the starter plugin `golem15.demo` answers on the root route:
|
|
|
|
```sh
|
|
curl http://127.0.0.1:8080/
|
|
```
|
|
|
|
It returns `{"message":"Hello from SummerCMS","plugin":"golem15.demo"}`. Stop the database with `docker compose down`, or `docker compose down -v` to delete its data as well.
|
|
|
|
`summer serve` prints the URL to open and the admin status. The admin lives at `http://127.0.0.1:8080/backend` once a plugin registers an admin controller; until then the status line reads `admin: off` and names the steps. When the admin is there, create the first administrator:
|
|
|
|
```sh
|
|
summer admin:create --email you@example.com --superuser
|
|
```
|
|
|
|
[Admin controllers](../backend/admin-controllers.md) shows how to add a controller, and [Users and permissions](../backend/users-and-permissions.md) how administrators sign in.
|
|
|
|
## Create an application without the script
|
|
|
|
When you already have a framework checkout, or want to read the code before running anything, do the script's steps yourself. Clone the framework into `summercms`, install the tool from it and run `summer new` in the directory next to the checkout:
|
|
|
|
```sh
|
|
git clone https://git.golem15.com/golem15/summercms
|
|
go -C summercms install ./cmd/summer
|
|
summer new demo
|
|
```
|
|
|
|
`summer new` finds a sibling `summercms` or `summercms.go` checkout by its module path. For a checkout anywhere else, pass it explicitly with `summer new demo --framework ../path/to/summercms`. [Scaffolding](../console/scaffolding.md) lists every flag and the files `summer new` writes.
|
|
|
|
The rest of this page is the manual path: it installs the tool and builds `examples/hello`, the small reference application in the framework repository.
|
|
|
|
## Requirements
|
|
|
|
- Go 1.27.
|
|
- PostgreSQL 15 or newer for any application that uses the data layer. A generated application runs PostgreSQL 16 in Docker.
|
|
- Docker, for the database of a generated application and for the integration tests that start PostgreSQL or Mailpit containers.
|
|
|
|
You do not need Node.js to build an application or these docs. It is needed only when you work on the admin SPA itself.
|
|
|
|
## Install the summer CLI
|
|
|
|
Clone the framework repository, then install the `summer` tool from its root:
|
|
|
|
```sh
|
|
go install ./cmd/summer
|
|
summer --help
|
|
```
|
|
|
|
`go install` writes the binary to `$(go env GOPATH)/bin`, usually `~/go/bin`. If `summer --help` reports `command not found`, that directory is not on your `PATH`. In bash or zsh, add it for the current shell, and to `~/.bashrc` or `~/.zshrc` to keep it:
|
|
|
|
```sh
|
|
export PATH="$(go env GOPATH)/bin:$PATH"
|
|
```
|
|
|
|
In fish, `fish_add_path` adds it and keeps it for new sessions without a profile edit:
|
|
|
|
```sh
|
|
fish_add_path (go env GOPATH)/bin
|
|
```
|
|
|
|
The tool creates, builds and watches applications, scaffolds plugins, models, migrations and admin controllers, and builds this documentation. Check that the framework compiles and its unit tests pass:
|
|
|
|
```sh
|
|
go vet ./...
|
|
go test -short ./...
|
|
```
|
|
|
|
`go test -short` skips the tests that need Docker. Run `go test ./...` without `-short` when Docker is available.
|
|
|
|
## Check your install
|
|
|
|
Console commands in SummerCMS are plain `bonfire.Command` values: a name in `namespace:verb` form, its arguments and flags, and a run function that reads input and writes output. The `summer` tool and every application binary are built from such values, and `bonfire.Call` runs one in-process, which is how tests call commands. This example comes from the framework's own tests, so it compiles and runs whenever you run `go test ./...`:
|
|
|
|
```go src=modules/bonfire/example_test.go#ExampleCall
|
|
commands := []bonfire.Command{{
|
|
Name: "acme:greet",
|
|
Description: "Greet someone by name",
|
|
Args: []bonfire.Arg{{Name: "name", Required: true}},
|
|
Run: func(ctx context.Context, in bonfire.Input, out bonfire.Output) error {
|
|
name, _ := in.Argument("name")
|
|
out.Printf("Hello, %s\n", name)
|
|
return nil
|
|
},
|
|
}}
|
|
|
|
if err := bonfire.Call(context.Background(), commands, "acme:greet", []string{"blog"}, os.Stdout); err != nil {
|
|
fmt.Println(err)
|
|
}
|
|
// Output: Hello, blog
|
|
```
|
|
|
|
If the tests above pass, this example ran and printed `Hello, blog`. See the [bonfire](../../modules/bonfire/README.md) reference for flags, prompts and styled output.
|
|
|
|
## Build the example application
|
|
|
|
`examples/hello` has three compiled plugins. From the framework root, build it with `summer build`, which generates `plugins.gen.go` and `main.go` from `summer.yaml` and writes the binary to `bin/hello`:
|
|
|
|
```sh
|
|
cd examples/hello
|
|
summer build
|
|
./bin/hello --help
|
|
./bin/hello greeter:hello
|
|
./bin/hello key:generate
|
|
```
|
|
|
|
`greeter:hello` prints the example's layered configuration and `key:generate` prints a fresh application key. Neither needs a database.
|
|
|
|
## Create the database
|
|
|
|
The commands that touch data open PostgreSQL. Create a database for the example:
|
|
|
|
```sql
|
|
CREATE DATABASE hello;
|
|
```
|
|
|
|
## Configure the application
|
|
|
|
Configuration comes from YAML files in `config/`. Any key can be overridden with a `SUMMER_` environment variable, in which a double underscore separates path segments: `SUMMER_DATABASE__DSN` sets `database.dsn`. [Configuration](configuration.md) explains the layers.
|
|
|
|
Point the binary at the database, give it the application key and an uploads bucket. Replace the `<secret>` markers with your own values, and never commit them:
|
|
|
|
```sh
|
|
export SUMMER_DATABASE__DSN='postgres://acme:<secret>@127.0.0.1:5432/hello?sslmode=disable'
|
|
export SUMMER_APP__KEY='<value printed by key:generate>'
|
|
export SUMMER_STORAGE__UPLOADS__BUCKET_URL='mem://'
|
|
```
|
|
|
|
## Migrate and serve
|
|
|
|
Run the migrations, list the routes and start the server on the loopback address:
|
|
|
|
```sh
|
|
./bin/hello migrate
|
|
./bin/hello route:list
|
|
./bin/hello serve --addr 127.0.0.1:8080
|
|
curl http://127.0.0.1:8080/items/1
|
|
```
|
|
|
|
From the application directory, `summer migrate`, `summer migrate:status` and `summer serve` run the same commands through the built binary, building it first when it is missing.
|
|
|
|
## Next steps
|
|
|
|
- Read [Coming from WinterCMS](coming-from-wintercms.md) if you are porting a WinterCMS plugin.
|
|
- Read the [Architecture introduction](../architecture/introduction.md) to see how the pieces fit.
|
|
- Read [Go modules and workspaces](../architecture/go-modules-and-workspaces.md) for what `summer new` writes into `go.mod` and `go.work`.
|
|
- Scaffold your own plugin with `summer make:plugin` as described in [Plugin registration](../plugins/registration.md).
|