From e0640220f26fa1c25d3b1cc33e6c3e4ad5d5815b Mon Sep 17 00:00:00 2001 From: Jakub Zych Date: Thu, 8 Oct 2026 12:08:35 +0200 Subject: [PATCH] docs(14.3-03): document summer new and the one-command start - installation: one-liner first, what the script does and its overrides, running the generated app, summer new without the script, then the examples/hello walkthrough; the obsolete known-issues callout is gone (D-18) - go modules and workspaces: what summer new writes (relative replace, framework detection order, committed relative go.work, no root go.sum); plugin:add adds a relative go.work path - console scaffolding: Creating an application with --framework, --no-plugin, --no-git, the files written, first commit and naming convention (D-01) - console introduction, llms note in site.yaml, root README quick start --- README.md | 32 +++++++-- .../architecture/go-modules-and-workspaces.md | 45 +++++++++++- docs/console/introduction.md | 4 +- docs/console/scaffolding.md | 46 +++++++++++- docs/setup/installation.md | 72 ++++++++++++++++--- docs/site.yaml | 1 + 6 files changed, 178 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index a4664fd..a9663a6 100644 --- a/README.md +++ b/README.md @@ -7,17 +7,39 @@ SummerCMS is a content management framework for Go, inspired by WinterCMS. An ap - **Compiled plugins.** A plugin is a Go module that implements the capability interfaces in [pact](modules/pact/README.md). The `summer build` command reads the application's `summer.yaml` manifest, generates the plugin import list and builds the binary. Plugins are registered at build time and never loaded at runtime. [party](modules/party/README.md) orders them by dependency and runs their register and boot lifecycle. - **YAML-driven admin.** Plugins describe admin lists, forms, filters and relations in WinterCMS-style YAML (`columns.yaml`, `fields.yaml`). [cabana](modules/cabana/README.md) compiles those definitions at boot and serves them as a JSON admin API, and [boardwalk](modules/boardwalk/README.md) serves the embedded Vue admin SPA that renders them. - **Headless API.** Plugins declare HTTP routes and middleware. [surf](modules/surf/README.md) assembles them onto a standard library `net/http` ServeMux, and [wire](modules/wire/README.md) keeps JSON responses byte-compatible with a PHP (WinterCMS/Laravel) backend. -- **Scaffolding CLI.** The `summer` tool builds and watches applications and scaffolds plugins, models, migrations, console commands, jobs and admin controllers. Every application binary also carries runtime commands such as `migrate`, `serve` and `route:list`. +- **Scaffolding CLI.** The `summer` tool creates, builds and watches applications and scaffolds plugins, models, migrations, console commands, jobs and admin controllers. Every application binary also carries runtime commands such as `migrate`, `serve` and `route:list`. ## Requirements - Go 1.27. - PostgreSQL 15 or newer for any application that uses the data layer ([lagoon](modules/lagoon/README.md)). - Node.js 22.6 or newer, only when working on the admin SPA in `admin/`. -- Docker, only for the integration tests that start PostgreSQL or Mailpit containers through testcontainers-go. +- Docker, to run the PostgreSQL 16 database of an application created by `summer new` (its `compose.yaml`), and for the integration tests that start PostgreSQL or Mailpit containers through testcontainers-go. ## Quick start +Create an application with one command. The script checks for Go 1.27 and Docker, clones the framework at its latest release tag into `./summercms`, installs the `summer` CLI and runs `summer new demo`: + +```sh +curl -fsSL https://summercms.io/new | bash -s -- demo +cd sm-demo-app +docker compose up -d --wait # PostgreSQL 16 on 127.0.0.1:54320 +summer build +summer migrate +summer serve # then: curl http://127.0.0.1:8080/ +``` + +The [sunrise](modules/sunrise/README.md) module holds the script and documents its `SUMMERCMS_REPO`, `SUMMERCMS_DIR` and `SUMMERCMS_REF` overrides. + +With a framework checkout already in place, install the CLI from it and run `summer new` in the directory next to the checkout; it finds a sibling `summercms` or `summercms.go` checkout, or takes `--framework `: + +```sh +go -C summercms install ./cmd/summer +summer new demo +``` + +### The example application + `examples/hello` is a small application with three compiled plugins. Install the `summer` CLI from the repository root, then build the example: ```sh @@ -53,10 +75,6 @@ The `migrate`, `migrate:status`, `migrate:rollback`, `serve` and admin commands `summer migrate`, `summer migrate:status`, `summer migrate:rollback` and `summer serve`, run from the application directory, delegate to the built binary in `bin/`. -### Known issues - -- The committed `examples/hello/main.go` is older than what `summer build` generates now, so building the example (or running its tests, which build it) leaves that file modified. Restore it with `git checkout -- examples/hello/main.go` if you do not intend to commit it. - ## Repository layout | Path | Contents | @@ -100,7 +118,7 @@ The `migrate`, `migrate:status`, `migrate:rollback`, `serve` and admin commands ## Using SummerCMS in an application -The framework is a single Go module, `git.golem15.com/golem15/summercms`; each framework package is imported from `git.golem15.com/golem15/summercms/modules/`. An application requires that module and, during development, points it at a local checkout with a `replace` directive. For an application module `acme` in a sibling directory: +The framework is a single Go module, `git.golem15.com/golem15/summercms`; each framework package is imported from `git.golem15.com/golem15/summercms/modules/`. An application requires that module and, during development, points it at a local checkout with a `replace` directive. `summer new` writes this `go.mod` for you, with a relative `replace` to the framework checkout and a committed `go.work` (see [Go modules and workspaces](docs/architecture/go-modules-and-workspaces.md)). Written by hand, for an application module `acme` in a sibling directory: ``` module git.golem15.com/acme/acme diff --git a/docs/architecture/go-modules-and-workspaces.md b/docs/architecture/go-modules-and-workspaces.md index 25a02be..bf57150 100644 --- a/docs/architecture/go-modules-and-workspaces.md +++ b/docs/architecture/go-modules-and-workspaces.md @@ -1,6 +1,6 @@ --- title: Go modules and workspaces -description: Require the framework module, develop plugins as local modules in a Go workspace, list them in summer.yaml and fork a plugin with a replace directive. +description: Require the framework module, see what summer new writes, develop plugins in a Go workspace, list them in summer.yaml and fork a plugin. section: architecture order: 20 --- @@ -26,6 +26,47 @@ replace git.golem15.com/golem15/summercms => ../summercms.go `summer make:plugin` copies this framework `replace` into the new plugin's `go.mod`, rewritten relative to the plugin directory, so the plugin builds against the same checkout. +## Applications created by summer new + +`summer new acme` writes these files for you in `sm-acme-app`, next to the framework checkout. The application module is `git.golem15.com/golem15/sm-acme-app`, and its `go.mod` replaces the framework with a relative path, so the directory pair can move together or be cloned elsewhere: + +```text +module git.golem15.com/golem15/sm-acme-app + +go 1.27.0 + +toolchain go1.27.0 + +require git.golem15.com/golem15/summercms v0.0.0 + +replace git.golem15.com/golem15/summercms => ../summercms +``` + +The starter plugin `golem15.acme` is added through `summer plugin:add`, so the same `go.mod` also gets a `require` of `git.golem15.com/golem15/sm-acme-app/plugins/acme` and a `replace` pointing at `./plugins/acme`. + +`summer new` picks the framework checkout in this order: + +1. the path given with `--framework`, relative to the current directory or absolute; a wrong path is an error, not a reason to keep looking; +2. a sibling directory named `summercms`, then `summercms.go`; +3. the source tree the `summer` binary was built from, when it was built from a checkout without `-trimpath`. + +Every candidate counts only when its `go.mod` declares the module `git.golem15.com/golem15/summercms`; the directory name alone is not enough. Without a match, `summer new` stops and asks for `--framework`. + +The application also gets a `go.work` that is committed with it. It lists the application itself and, unless `--no-plugin` was given, the starter plugin, both as relative `use` paths: + +```text +go 1.27.0 + +toolchain go1.27.0 + +use ( + . + ./plugins/acme +) +``` + +There is no `go.sum` in the application root: builds go through the workspace, and `go.work.sum`, which Go writes on the first build, is listed in `.gitignore`. The starter plugin keeps its own `go.mod` and `go.sum` like any other plugin module. + ## The summer.yaml manifest The manifest in the application root names the application module, the binary `summer build` writes to `bin/`, and the plugins in activation order: @@ -48,7 +89,7 @@ A plugin you develop inside the application lives in `plugins/` as its own - it adds the plugin to `summer.yaml`; - it adds a `require` and a `replace` pointing at the local directory to the application's `go.mod`; -- it adds the plugin directory to the nearest `go.work`, creating one in the application root when there is none. +- it adds the plugin directory to the nearest `go.work` as a path relative to that file, such as `./plugins/blog`, creating a `go.work` in the application root when there is none. With a `go.work` in place, `go build`, `go test` and your editor see every local plugin module together. `summer build` uses the nearest `go.work` it finds; without one it builds in module mode. diff --git a/docs/console/introduction.md b/docs/console/introduction.md index 1987d2a..e67db20 100644 --- a/docs/console/introduction.md +++ b/docs/console/introduction.md @@ -10,7 +10,7 @@ WinterCMS has one console entry point, `php artisan`. SummerCMS has two programs | Program | Where it comes from | What it does | |---------|---------------------|--------------| -| `summer` | Installed once from the framework with `go install ./cmd/summer`. | Builds and watches applications, scaffolds plugins and their parts, records API parity fixtures and builds these docs. | +| `summer` | Installed once, by the `curl -fsSL https://summercms.io/new \| bash -s -- ` one-liner or from a framework checkout with `go install ./cmd/summer`. | Creates, builds and watches applications, scaffolds plugins and their parts, records API parity fixtures and builds these docs. | | The application binary, for example `./bin/acme` | Written by `summer build` into the application's `bin/` directory. | Runs the application: the HTTP server, migrations, workers, the scheduler, admin accounts and every command its plugins add. | The application binary is what you deploy, so everything that must run in production, such as migrations and workers, is a command of the binary rather than of `summer`. @@ -45,6 +45,6 @@ During development you often work from the application directory with `summer` a ## The sections of this chapter - [Setup and maintenance](setup-and-maintenance.md) lists every command of the application binary. -- [Scaffolding](scaffolding.md) covers `summer build`, `summer dev` and the `make:` commands. +- [Scaffolding](scaffolding.md) covers `summer new`, `summer build`, `summer dev` and the `make:` commands. - [Writing commands](writing-commands.md) shows how a plugin adds its own commands. - [Utilities](utilities.md) covers the parity and documentation commands of `summer`. diff --git a/docs/console/scaffolding.md b/docs/console/scaffolding.md index 9be5718..49dfd1a 100644 --- a/docs/console/scaffolding.md +++ b/docs/console/scaffolding.md @@ -1,12 +1,12 @@ --- title: Scaffolding -description: Build and watch an application, and generate plugins, models, migrations, console commands, jobs and admin controllers with the summer make commands. +description: Create an application with summer new, build and watch it, and generate plugins, models, migrations, commands, jobs and admin controllers. section: console order: 30 --- # Scaffolding -The `summer` tool builds applications and generates the files a plugin is made of, the way `create:plugin`, `create:model` and the other `create:` commands do in WinterCMS. Every generated file compiles as written, so you can build straight after running a command. +The `summer` tool creates and builds applications and generates the files a plugin is made of, the way `create:plugin`, `create:model` and the other `create:` commands do in WinterCMS. Every generated file compiles as written, so you can build straight after running a command. ## Building and watching @@ -22,6 +22,48 @@ summer dev Do not edit `main.go` or `plugins.gen.go`: `summer build` rewrites them from the manifest. +## Creating an application + +`summer new` creates a new application in the current directory, the way `composer create-project` starts a WinterCMS project. It takes the application name and writes `sm--app`: + +```sh +summer new acme +``` + +The name must be lower-case letters and digits, starting with a letter. Go keywords such as `go` or `type`, and the names `main` and `internal`, are refused because the starter plugin package would not compile or could not be imported. `summer new` also refuses any existing `sm--app`, even an empty directory, and never merges into one. When a step fails after it created the directory, it removes the directory again, so you can rerun the same command. + +| Flag | Effect | +|------|--------| +| `--framework ` | The framework checkout to build against. Without it, `summer new` looks for a sibling `summercms` or `summercms.go` checkout, then the source tree the `summer` binary was built from. [Go modules and workspaces](../architecture/go-modules-and-workspaces.md) describes the detection. | +| `--no-plugin` | Skip the starter plugin; `summer.yaml` then lists no plugins, and the application still builds and serves. | +| `--no-git` | Skip `git init` and the first commit. | + +The application gets these files: + +| File | Contents | +|------|----------| +| `go.mod` | Module `git.golem15.com/golem15/sm--app`, requiring the framework through a relative `replace`. | +| `go.work` | The workspace with the application and its plugin modules, as relative paths. It is committed. | +| `summer.yaml` | The manifest: module path, binary name and plugin list. | +| `config/` | `app.yaml`, `database.yaml`, `http.yaml` and `storage.yaml`, enough for `serve` and `route:list`. | +| `.env`, `.env.example` | The database DSN and a freshly generated application key. `.env` is readable by its owner only and never committed; `.env.example` lists the variables without the key. | +| `compose.yaml` | PostgreSQL 16 on `127.0.0.1:54320`, with credentials matching `.env`. | +| `.gitignore` | `bin/`, `tmp/`, `storage/`, `.env` and `go.work.sum`. | +| `CLAUDE.md`, `AGENTS.md` | Instructions for AI coding agents: the commands, the layout, the links to the documentation for agents and the naming convention. `AGENTS.md` is a symlink to `CLAUDE.md`. | +| `plugins/` | The starter plugin `golem15.`, created by the same code as `summer make:plugin` and registered by the same code as `summer plugin:add`. Its `routes.go` answers `GET /` with a JSON greeting. | +| `main.go`, `plugins.gen.go` | Generated from `summer.yaml`, as `summer build` does. | + +Unless you pass `--no-git`, `summer new` initialises a git repository on `main` and commits everything except `.env`. When git has no user name or email configured, that first commit uses the author `SummerCMS ` and prints a warning; your git configuration is not changed. Finally it prints the next steps to run inside `sm-acme-app`: + +```sh +docker compose up -d --wait +summer build +summer migrate +summer serve +``` + +Golem15 names repositories by what they hold: `sm--app` for an application such as the one `summer new` writes, `sm--plugin` for a standalone plugin module and `sm--theme` for a Nuxt or Vue frontend. + ## Creating a plugin `summer make:plugin` takes a plugin ID in `vendor.plugin` form and creates the plugin module in `plugins/` of the current application, with the directory layout described in [Plugin registration](../plugins/registration.md): diff --git a/docs/setup/installation.md b/docs/setup/installation.md index 4a46b8d..0966daf 100644 --- a/docs/setup/installation.md +++ b/docs/setup/installation.md @@ -1,6 +1,6 @@ --- title: Installation -description: Install the Go toolchain, PostgreSQL and the summer CLI, then build, configure, migrate and serve your first SummerCMS application. +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 --- @@ -24,11 +24,69 @@ 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 ends with the `export PATH=...` line to run and to add to your shell profile. +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` and a freshly generated `SUMMER_APP__KEY`. 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. + +## 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. -- Docker, only for the integration tests that start PostgreSQL or Mailpit containers. +- 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. @@ -47,7 +105,7 @@ summer --help export PATH="$(go env GOPATH)/bin:$PATH" ``` -The tool 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: +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 ./... @@ -127,13 +185,9 @@ 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. -> [!WARNING] -> Known issues in the current framework: -> -> - The committed `examples/hello/main.go` is older than what `summer build` generates now, so building the example leaves that file modified. Restore it with `git checkout -- examples/hello/main.go` if you do not intend to commit it. - ## 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). diff --git a/docs/site.yaml b/docs/site.yaml index e83fea0..dc21d83 100644 --- a/docs/site.yaml +++ b/docs/site.yaml @@ -10,6 +10,7 @@ llms_notes: - "The data layer supports PostgreSQL only." - "SummerCMS is headless: it serves a JSON API and an admin SPA, with no frontend themes." - "It targets Go 1.27." + - "A new application starts with `curl -fsSL https://summercms.io/new | bash -s -- `, or with `summer new ` next to a framework checkout." sections: - name: setup title: Setup