Generate a client project that is ready for its first pull request: a monorepo of apps, an optional database and cache in Docker Compose, git hooks, CI, releases and a docs site, all wired together and committed.
scaffold is a bash toolbox for engineers who start client projects often and want every one of them built, checked and released the same way. It is pre-1.0; versions are git tags.
- Apps from the adapters you pick:
--web,--apior--app, each in its own directory with its ownmise.toml. - One task contract. Every app answers the same nine
misetasks (install,format,lint,test,build,checklist, …), so CI runs one command per app and never learns the language. - CI as five thin workflows that call shared reusable workflows at
@v1(ADR-0005). - Guardrails: lefthook runs prettier, gitleaks and commitlint locally; Renovate opens dependency bumps.
- Releases: Release Please from Conventional Commits, container images, and an
install.shthat runs the released stack with Docker Compose. - A VitePress docs site checked in CI like any app.
.scaffold.toml, recording the toolbox commit that generated it, soscaffold updatecan bring later toolbox changes in.
| Needed for | Requirement |
|---|---|
| Everything | git and mise; mise install supplies jq, yq and the rest |
laravel-api, laravel-inertia |
PHP 8.3 or later on the host; mise cannot pin it (ADR-0016) |
scaffold new |
A GitHub owner for the project: SCAFFOLD_GITHUB_OWNER, else the signed-in gh user, else git config github.user |
scaffold publish |
gh, signed in with gh auth login |
| CI in a generated project | A .github repository under the project's GitHub owner holding the reusable workflows (ADR-0005) |
| Running a release | Docker |
git clone https://github.com/ttncode/scaffold.git
cd scaffold
mise install
export PATH="$PWD:$PATH"
scaffold listscaffold list prints one row per adapter and service. scaffold loads its pinned jq and yq itself. Call scaffold by its path or through PATH; a symlink to it does not work.
Generate a project outside the toolbox. scaffold new creates it where you run it:
cd ~/playground
scaffold new demo-app --web nextjs --api nestjs --db postgresThe framework generators take several minutes. The result is a directory with one commit, feat: scaffold project.
Run scaffold with no arguments in a terminal for a wizard that builds the same command. The full end-to-end run, from generation to a running release, is Walk through a first project.
| Command | Does |
|---|---|
scaffold new <name> |
Generates and commits a project |
scaffold add <dir> --adapter <adapter> |
Adds an app to an existing project and stages it |
scaffold update [dir] |
Applies toolbox changes since the project was generated; never commits |
scaffold publish [dir] |
Creates the GitHub repository (private by default) and protects main |
scaffold list |
Prints adapters with role and tier, services with kind |
scaffold lint |
Checks every adapter and service against the contract |
Flags, defaults, environment variables and the decision behind each command: Commands.
Each adapter's tier is ADAPTER_TIER in its adapter.env (ADR-0012).
| Adapter | Role | Tier |
|---|---|---|
nextjs |
web | A |
nestjs |
api | A |
laravel-api |
api | A |
flask |
api | A |
laravel-inertia |
app | B |
| Tier | CI runs it | Guarantee |
|---|---|---|
| A | every pull request, and nightly | stays green through every dependency bump |
| B | a pull request that changes adapters/laravel-inertia/, weekly, or on manual dispatch |
verified regularly, not on every push |
| C | not automatically verified | none; no adapter is tier C today |
A database or cache is a directory under services/, not an adapter (ADR-0019).
| Flag | Services | Default |
|---|---|---|
--db |
mysql, postgres, mongodb, none |
mysql with --api or --app, otherwise none (ADR-0020) |
--cache |
redis, none |
none |
There is no DynamoDB: every release ships a compose.yaml for the client to run (ADR-0014), and the only DynamoDB that fits a compose file is an emulator with no production counterpart.
- Start here: repository map, commands, glossary and a reading path
- Tour: how the pieces fit, in nine pages
- Decisions: why they fit that way
- Runbooks: what to do when something specific happens
- Provenance: what is copied from immich, and where it drifted
Setup, test lanes and how to add an adapter or a service: CONTRIBUTING.md. Report vulnerabilities privately as described in SECURITY.md.
MIT, see LICENSE. A generated project gets no license file: its terms belong to the engagement it was generated for.