Getting started

Try it locally in thirty seconds, then point it at a GitHub repo when you're ready.

Try it locally

No GitHub needed. Local mode serves and edits a plain directory.

git clone https://github.com/nullism/trunkcms
cd trunkcms
TRUNKCMS_CONTENT_DIR=./testdata/site go run ./cmd/trunkcms

Open http://localhost:8080 for the site and http://localhost:8080/admin to edit. Local mode offers three dev logins, dev-admin, dev-editor and dev-author, so you can try each role. Saves are written straight into the content directory, and edits you make to those files by hand show up within about two seconds.

Note This writes to testdata/site. Copy it somewhere first if you want to keep the fixture clean.

You can also render a content directory to static files:

go run ./cmd/trunkcms build -dir ./testdata/site -out ./public

Run against GitHub

1. Create the content repo

For example nullism/myblog. Keep it private so drafts stay hidden. It can be empty: trunkcms serves a placeholder and the dashboard offers to initialize it.

2. Create a GitHub App

In GitHub, go to Settings → Developer settings → GitHub Apps:

  • Callback URL: https://myblog.com/admin/callback
  • Webhook URL: https://myblog.com/admin/webhook, with a random secret
  • Repository permissions: Contents, read & write. Subscribe to Push events.
  • Generate a private key and a client secret, then install the App on the content repo only.
  • Under Advanced, make the App public. Otherwise GitHub shows a 404 to anyone but the App’s owner when they try to sign in. Public only means other accounts can sign in through it. Access is still decided by repo permission and users.yaml.

3. Run the image

The image is on Docker Hub as nullism/trunkcms. There’s no Dockerfile per blog: one image, configured with environment variables.

docker run -p 8080:8080 \
  -e TRUNKCMS_REPO=nullism/myblog \
  -e TRUNKCMS_SITE_URL=https://myblog.com \
  -e TRUNKCMS_GITHUB_APP_ID=123456 \
  -e TRUNKCMS_GITHUB_PRIVATE_KEY_FILE=/secrets/app.pem \
  -e TRUNKCMS_GITHUB_CLIENT_ID=Iv1.abc \
  -e TRUNKCMS_GITHUB_CLIENT_SECRET=... \
  -e TRUNKCMS_WEBHOOK_SECRET=... \
  -e TRUNKCMS_SESSION_KEY="$(openssl rand -base64 32)" \
  -v "$PWD/secrets:/secrets:ro" \
  nullism/trunkcms

On Kubernetes, Cloud Run, ECS or Lambda, the same values go in the platform’s env and secret config. There’s a Kubernetes example in the repo.

4. Sign in

Visit /admin and sign in with GitHub. Anyone with push access to the repo is an admin. If the repo is empty, click Initialize site.

From then on, editing outside the UI works the same way. A git push from a laptop, a merged PR, or GitHub’s web editor all fire the push webhook, and the site rebuilds.