CLI · ADR
0002: Scaffold with init and npm create
Context#
A tool that needs “only Markdown and one config file” still has a first five minutes: a config with the right import, a project folder with a _project.yml, one record that shows the format, npm scripts, a .gitignore, and a CI workflow so the site is published from day one. Writing these by hand from the README is slow and error-prone, and a decision log often starts inside an existing repository that already has a package.json.
Decision#
inkan init [dir] copies a starter repository from the package and wires up package.json. It never overwrites a file that already exists, so it is safe to run inside an existing repository. npm create @tilaven/inkan is a thin wrapper, published as create-inkan, that runs the same init in a new folder.
The starter is complete: it builds and deploys without edits. Everything in it is a plain file you can change or delete afterwards.
How to use it#
A new repository#
npm create @tilaven/inkan@latest my-decisionscd my-decisionsnpm installnpm run devnpm create @tilaven/inkan [dir] resolves the @tilaven/inkan package it depends on and runs inkan init <dir>. When you give no folder name it uses decisions-site. After init you still run npm install yourself; the output ends with the exact next commands.
An existing repository#
npm install -D @tilaven/inkannpx inkan initWithout an argument init targets the current folder (or --root). With npx inkan init docs the files land in docs/, which is how this site is laid out. Run the CLI from that folder afterwards, or pass --root docs.
What init creates#
| File | Purpose |
|---|---|
inkan.config.ts | defineConfig with title, tagline, url and repo to fill in. |
decisions/_authors.yml | One example author (jane.doe), to show the format. |
decisions/platform/_project.yml | A first project named Platform with icon, description and owner. |
decisions/platform/adr/0001-record-architecture-decisions.md | A first ADR with a Mermaid diagram, so the site is not empty. |
AGENTS.md | Instructions for coding agents: where records live, how to create one, what statuses mean. |
.github/workflows/decisions.yml | Builds every pull request and publishes main to GitHub Pages. |
.gitlab-ci.yml | Builds merge requests and publishes the default branch to GitLab Pages. |
Dockerfile, nginx.conf, .dockerignore | Two-stage image: build with Node, serve dist/ with nginx. |
.gitignore | node_modules/ and dist/. |
package.json | Created, or updated in place (see below). |
The dotfiles are stored in the package as _gitignore and _dockerignore and renamed on copy, because npm drops .gitignore from published packages. init prints every file it added with a + and marks package.json with ~.
How package.json is handled#
If there is no package.json, init creates one:
{ "name": "my-decisions", "private": true, "type": "module", "scripts": { "dev": "inkan dev", "build": "inkan build", "preview": "inkan preview", "new": "inkan new" }, "devDependencies": { "@tilaven/inkan": "^0.1.0" }}If one exists, init only adds to it:
- The four scripts are added. Scripts you already have, including ones with the same names, are kept as they are.
"type": "module"is set only whentypeis missing. The config file is an ES module, so a repository that uses CommonJS keeps.tsfor the config and is otherwise unaffected.@tilaven/inkanis added todevDependenciesat the installed version, unless it is already independencies.
Nothing else in the file is touched, and key order of your existing fields is preserved.
Existing files are never replaced#
init skips any file that already exists at the destination and keeps going. Running it twice is harmless. This also means a second init does not refresh an old workflow file: delete it first if you want the current one.
After init#
- Set
title,urlandrepoininkan.config.ts.repoenables the edit and “New ADR” buttons;urlis used in feeds andllms.txt. - Rename the
platformfolder or add your own projects. A folder with records is enough;_project.ymladds the display name. - Push. The GitHub workflow needs Pages set to “GitHub Actions” as the source; the GitLab pipeline publishes to Pages on the default branch. Both set
BASE_PATH=/<repository name>for project pages; remove that line for a custom domain. See GitHub and GitLab Pages. - Optional:
docker build -t decisions .for a self-hosted image. See Docker and nginx.
Note
The CI files and the Dockerfile use Node 22 and run npm install or npm ci. The Dockerfile expects a package-lock.json, so commit the lockfile that npm install created.
Consequences#
- One command gives a repository that builds and deploys. New users see a working site before reading any documentation.
- Safe in existing repositories: nothing is overwritten and
package.jsonis extended, not replaced. - The starter is a snapshot. Files it created are yours from then on; updates to the package’s starter do not propagate to them, which is intended for CI files you will edit anyway.
npm create @tilaven/inkanpins the@tilaven/inkanversion it was published with. Use@latestto get the current one.- The starter ships files for every target (GitHub, GitLab, Docker). Delete the ones you do not use.
History 1
- ImplementedInkan maintainers
9e5e535commit diff