The CWA is in heavy development
The CWA is still in alpha and not ready for production - some code and implementations are likely to change. If you would like to try out the CWA, please enjoy what we have provided and feel free to provide feedback, or get involved on GitHub.
Introduction

Installation

Scaffold a new CWA project with the interactive CLI — it picks your features, wires CI/CD, and gets Docker running in one go.

Prerequisites

  • Docker Desktop (or Docker Engine + Compose)
  • Node ≥ 18 and pnpm (for running the CLI and the Nuxt app locally)

PHP, Composer, and all API dependencies run inside Docker — nothing else to install.

1. Scaffold your project

Run the interactive CLI:

pnpm create cwa my-project

The CLI will ask four questions:

PromptOptions
Project nameThe directory to create
CI/CD pipelineGitHub Actions, GitLab CI, or none
FeaturesNavigation links, HTML content editor, image uploads, blog, nested pages, forms (multiselect)
Include fixtures?Scaffolds sample content so the site works out of the box

After answering, the CLI downloads the template, strips unused feature code from nuxt.config.ts, and generates a README.md tailored to your choices. It then offers to run docker compose up -d and pnpm install in one step — accept both.

The CLI reads a cwa-manifest.json file hosted in the template repo. Feature options and their file exclusions are driven by this manifest, so the CLI always reflects the latest template state without needing a CLI update.
Nightly builds:pnpm create cwa@dev tracks the dev branch of the template. Use @latest (the default) for stable releases.

2. Generate JWT keys

Authentication uses JWT tokens. Generate a key pair once:

docker compose exec php sh

Inside the container:

mkdir -p config/jwt
php -r "print bin2hex(random_bytes(26));"

Copy the passphrase, then copy .env to .env.local and set it:

cp .env .env.local
# Edit .env.local: JWT_PASSPHRASE=<your passphrase>

Generate the keys:

openssl genpkey -out config/jwt/private.pem -aes256 -algorithm rsa -pkeyopt rsa_keygen_bits:4096
openssl pkey -in config/jwt/private.pem -out config/jwt/public.pem -pubout
exit

3. Load fixtures

If you selected Include fixtures during setup, load them once the API container is healthy:

docker compose exec php bin/console doctrine:fixtures:load

This creates a default admin account (admin / admin) and seeds the site structure — layout, pages, and example components.

4. Start the dev server

cd my-project/app
pnpm dev
URLWhat's there
https://localhostYour Nuxt application
https://localhost/_apiAPI (JSON-LD)
https://localhost/adminCWA admin panel
The stack uses self-signed certificates. Accept the browser warning or trust the CA at api/frankenphp/caddy/certs/.

Log in at https://localhost/login with admin / admin. Click Edit to enter edit mode and see the inline CMS.


What Docker handles automatically

When the php container starts, the entrypoint:

  • Runs composer install if vendor/ is empty
  • Waits for PostgreSQL to be ready
  • Runs pending database migrations

You never need to run these manually.


CI/CD

If you chose GitHub Actions during setup, four workflows are pre-wired in .github/workflows/:

WorkflowTriggerWhat it does
ci.ymlEvery pushBuild + test; deploy review environment on PRs
production.ymlManualDeploy canary or production
cleanup.ymlPR closedTear down review environment
performance.ymlManualRun sitespeed tests

Images push to GHCR. The workflows use the same bin/devops/ shell scripts as the GitLab CI option. Required secrets and variables are listed in the CLAUDE.md of the template repo and in the workflow files themselves.


Manual setup (alternative)

If you prefer to create a GitHub repository first and clone from there:

With the GitHub CLI:

gh repo create my-website \
    --template="components-web-app/components-web-app" \
    --private --clone

Or generate from GitHub:

Generate a new repository from the template on GitHub

Then follow steps 2–4 above. You'll configure features manually rather than through the CLI.


What's next