Setup & operations

Local setup

Install a development workspace, create the first account and start both application processes.

GroCMS 0.1.0 · Reviewed 15 September 2026

Download this guide

Start from a fresh development workspace

Local development needs the repository, Node.js 24, npm and Docker with its Linux engine available. Run commands from the repository root. The complete application lives in apps/cms, while root npm commands select the workspace and preserve root environment, media and credential paths. There is one root package-lock.json. This procedure prepares a new local installation; it is not the upgrade path for an existing site. If the workspace already contains private environment files or authored content, preserve them and inspect its current state instead of repeating initialization. Editors who only need to work on an existing website can use its administration URL without setting up a development machine.

The infrastructure file starts only this project's PostgreSQL and Mailpit services. The application runs on the host so code edits can be picked up by the development server. Docker's health-based startup conditions distinguish a running process from a service ready to accept connections; the commands below wait for the infrastructure before applying migrations. A reachable Docker CLI with an unavailable Linux engine is not sufficient.

powershell
node --version
npm --version
docker version
npm ci
node scripts/init-local.mjs
docker compose --env-file .env.infrastructure.local -f compose.dev.yaml up -d --wait

Sources: Local installation and verification; Supported Node engine and npm scripts; Private local environment generator; Control startup and shutdown order in Compose.

Understand the generated private configuration

The initializer generates random database and authentication secrets and creates .env.infrastructure.local plus .env.local. It refuses to replace existing files. The first file configures Docker infrastructure; the second configures the host application. Both are ignored by Git. Do not paste their contents into issue reports, screenshots or documentation. For the standard local path, the initializer already puts the matching database URL into both files, so there is no need to copy a password through the terminal.

GroCMS is the product name. Existing GCMS_* environment variables, gcms database and project names, and gcms_* role and test-database identifiers stay unchanged for compatibility. Follow the identifiers in these commands instead of renaming existing configuration, data, backups or tokens. grocms.com is the product website; PUBLIC_URL and BETTER_AUTH_URL must identify the site you actually installed.

Local serviceAddressPurpose
Development websitehttp://localhost:3100Public pages and /admin
PostgreSQL127.0.0.1:55432gcms database; local migrations use its owning role
Mailpit SMTP127.0.0.1:51025Captures invitation and recovery email
Mailpit inboxhttp://localhost:58025Read captured development messages

These are local addresses. The default production Compose web port is 3000; installations can choose another port. Do not change origins casually between localhost and another hostname while diagnosing login: authentication and request-origin checks expect the configured application origin. Media for host development is stored under .data/media, independently of Docker's production media volume.

Sources: Private local environment generator; Development PostgreSQL and Mailpit services.

Migrate, then create the first administrator

powershell
npm run db:migrate
npm run setup

Migration prepares the application and queue schema, constraints and indexes. Setup creates the first administrator, registers routes and publishes a minimal website: one Hello world! Post, one Welcome Page as the homepage, official GroCMS branding with its bundled logo, Inter and approved colours, a basic content template and site settings. No sample images, author profiles, taxonomy terms or promotional layouts are installed. Edit or remove these placeholders through normal administration. With the normal local command, the random account password is written to the ignored .local/administrator.json. Open that file privately, move the credential into your password manager and remove the temporary file once it is safely stored.

Setup creates the first administrator only when no account exists; subsequent users join through invitations. Repeating setup requires the recorded owner's current credentials and preserves existing content, including edited or removed placeholders. To choose the richer Fieldnotes reference demo instead, use the command below in place of the initial setup command. Design-only mode prepares three unpublished design drafts before seeding. The demo accepts only an empty content site or those exact untouched drafts; it refuses to replace the published minimal starter or other authored content.

powershell
npm run setup -- --design-only && npm run seed:demo

Sources: Application and queue migration runner; First account and installation setup; Starter resource creation; Optional demo and untouched-starter guard.

Keep web and worker running separately

powershell
npm run dev

Open http://localhost:3100/admin and sign in with the account created by setup. Keep that terminal open. Start another terminal in the same repository and run the worker command below. The web server handles editing and public page requests, while the worker executes due publication jobs. A schedule can be saved successfully while the worker is stopped; that does not mean it has been executed. Verify the worker is ready before relying on a scheduled publication.

powershell
npm run worker

Invitation and password-recovery messages appear in the Mailpit inbox. Mailpit is a local capture service, so an email appearing there does not establish delivery to an external mailbox. To pause work, stop the two host processes with their terminal interrupt controls, then use the infrastructure stop command. That preserves PostgreSQL and mailbox volumes for the next session. Starting them again does not require setup or demo seeding.

powershell
docker compose --env-file .env.infrastructure.local -f compose.dev.yaml stop

Sources: Supported Node engine and npm scripts; Separate worker process; Development PostgreSQL and Mailpit services.

Create the isolated test database before running tests

The integration suite must use gcms_test, not the authored development database. The test initializer checks the bundled loopback database address, creates a separate database if necessary, writes a distinct private test environment and applies migrations there. Existing mismatched test configuration is preserved and rejected rather than silently redirected. This separation lets the tests exercise real accounts, revisions and publication without contaminating the reference website.

powershell
node scripts/init-test.mjs
npm run verify

The verification command covers TypeScript, lint, Vitest and the production build. Browser suites are separate and require their browser binaries plus a running local reference site. Read the current verification instructions before running fixture-based browser or extension exercises against a populated workspace. If installation fails, record the command, error and service status without environment secrets, and use the troubleshooting guide to identify the failing layer before changing configuration.

powershell
npx playwright install chromium firefox
npm run test:e2e

Sources: Isolated test database initializer; Supported Node engine and npm scripts; Local installation and verification.