# Contributing

> Work on Tinka itself: get the code, run the checks, build a package with its tests and docs, and commit on the version branch.

This page is for people and agents working on Tinka itself, not on an App built with it. Tinka holds every change to the same standard: code, tests and a docs page ship together, and one Command checks all of it. The sections below follow a change from getting the code to committing it.

:::note
The Tinka repository is private during the alpha. You need a GitHub account with access to clone it.
:::

## Get the code

Tinka needs Go 1.27 or later. Clone the repository; its default branch is `1.x`, the Version branch for Tinka 1, and there is no `main`:

```sh
git clone git@github.com:mucolabs/tinka.git
cd tinka
```

Install the Tinka CLI from your checkout. Inside the repository, it forwards the contributor Commands, such as `tinka verify`, to the repository’s own tooling:

```sh
go install ./cmd/tinka
```

Agents start with `AGENTS.md` at the repository root: it maps every directory and links the files that govern them. `GLOSSARY.md` defines the project’s vocabulary, and every page, comment and commit uses its terms.

## The workspace layout

The repository holds two Go modules, tied together for local work by `go.work`:

- **The root module**, `github.com/mucolabs/tinka`: Core in the root package, the packages beside it (`cli`, `di`, `env`, `log`, `encryption`, `password`, `events`, `health`, `tinkatest`), and the `tinka` and `act` Commands under `cmd/`. This is what Apps depend on.
- **The `dev` module**: the contributor Commands and the docs site renderer. Its dependencies, such as the linter and the Markdown renderer, live in its own `go.mod`, so they never reach an App.
- **The starter kits** under `kits/`: `_skeleton` and `_core`, embedded in the Tinka CLI. Each keeps its `go.mod` as `go.mod.kit`, and its directory starts with an underscore so the go command doesn’t build it as part of Tinka.

To try a change in a new App, point `tinka new` at your checkout with `--local`, so the App builds against your code instead of a release:

```sh
tinka new blog --local ~/code/tinka
```

`package.json` and the `*.config.ts` files deploy the docs site. Nothing in Tinka depends on Node.

## Run the checks

`go run ./dev verify` runs every check at once: `gofmt`, `go mod tidy` for both modules outside the workspace (the way `go install` builds them), `golangci-lint` (which includes `go vet`) and `go test -race`. The tests build the docs too, so a broken page fails verify. Test results stay cached, so unchanged packages don’t run again, and verify lowers its own priority so the machine stays responsive. With the Tinka CLI installed, `tinka verify` runs the same thing.

```sh
go run ./dev verify
```

The CI workflow runs this one command and nothing else. A new check goes in `dev/verify.go`, never in the workflow file.

Preview the docs with live reload at `localhost:3000`, or build the static site, into `dev/site/dist` unless you pass a directory:

```sh
go run ./dev docs serve
go run ./dev docs build
```

## How a package is built

Tinka grows one package at a time, and each one follows the same steps, recorded in `handbook/README.md` with the status of every package:

::::steps

:::step{title="Research"}
Study the problem and survey how the Go standard library, `golang.org/x` and trusted Go packages solve it. Write the notes to `handbook/research/`.
:::

:::step{title="Agree on the approach"}
Describe the approach and its trade-offs to the maintainer, and agree on it before writing code.
:::

:::step{title="Build it with its tests"}
Write the package with the standard library’s `testing` package only. Output is checked against golden files, refreshed with `-update`, such as `go test ./cli -update`.
:::

:::step{title="Ship the docs with it"}
The same change adds or updates its docs page, any new terms in `GLOSSARY.md`, and a decision record under `docs/adr/` when the decision is hard to reverse, surprising and a real trade-off.
:::

::::

The docs describe Tinka on its own terms. They never compare it with another framework or runtime; each such comparison, and the reason behind it, goes in the package’s page under `handbook/`, which is never published. A change is done when all of it lands together and `go run ./dev verify` passes.

## Dependencies

Every dependency becomes a dependency of every App, so Tinka adds none lightly. The root module uses the standard library first, then `golang.org/x`. A module from anywhere else needs the maintainer’s agreement before it’s added, with the evidence the `tinka-dependencies` skill asks for: one job, a stable v1 or later, wide use, active maintenance, few dependencies of its own, a measured cost in startup time and binary size, and an MIT, BSD or Apache 2.0 license. The rule covers test-only dependencies and the `dev` module too.

## Writing docs

Load the `tinka-docs-writer` skill in `.agents/skills/` before planning, writing or reviewing a page under `docs/content`. It sets where a page goes, its template, the voice and the authoring syntax. Every page must be listed in `docs/content/nav.json`: the build fails on a page missing from it, bad frontmatter, an unknown `:::` block or fence option, or a link to a page that does not exist.

Every color, size and motion value on the docs site, and on any other Tinka surface, comes from `DESIGN.md`. A value that isn’t there doesn’t ship until it’s added there first.

## Commits and branches

Commit finished work on `1.x`. Messages follow Conventional Commits, with a scope naming the area and a lowercase summary of what the change does:

```text
feat(act): act build builds the App for production
fix(http): record 101 Switching Protocols only once a hijack succeeds
feat(kits): the skeleton tests with tinkatest, in parallel
```

The types are `feat`, `fix`, `docs`, `refactor`, `test` and `chore`. Releases are tags on the Version branch: `v1.0.0-alpha.N`, then `-beta.N`, then `v1.0.0`.

:::warning
Every push to `1.x` deploys the docs site, so a push publishes whatever docs the branch holds. Run `go run ./dev verify` before you push, and push only when the change is ready to be read.
:::

See also: [Philosophy](philosophy.md), [Installation](installation.md), [FAQs](faqs.md)
