# Contributing to LeafWiki First of all: **thank you for your interest in contributing to LeafWiki!** LeafWiki is built to be a **simple, reliable and low-overhead wiki for structured documentation**. Contributions that improve the project while keeping these goals intact are always welcome. Whether you're fixing a typo, reporting a bug, improving documentation, or contributing code — every contribution helps. --- ## Quick start Install [mise](https://mise.jdx.dev/getting-started.html), then in the repository root: ``` bash mise install # Node from .nvmrc, Go as a bootstrap (go.mod selects the exact version) make setup # npm dependencies for the frontend and the e2e tests make dev # backend and Vite together; open http://localhost:5173, Ctrl-C stops both ``` mise is optional: nvm or fnm with `.nvmrc` (`nvm use`) and any Go 1.21 or newer work just as well. `make doctor` shows whether your versions match. Details: [Development setup](#development-setup). [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/perber/leafwiki) Or skip the local setup: the [Dev Container](.devcontainer/devcontainer.json) (GitHub Codespaces, or VS Code with Docker and "Reopen in Container") installs mise, Node, Go and the npm dependencies on creation; run `make dev` in its terminal, port 5173 opens in the browser. It is also the easiest way on Windows, which has no `make`: use "Dev Containers: Clone Repository in Container Volume", since a Git for Windows clone has CRLF line endings that break the shell scripts. The Playwright browser is not included; for E2E runs, `make setup-e2e` and `npx playwright install-deps chromium` in `e2e/`. --- ## Ways to contribute There are many ways to help improve LeafWiki: - Reporting bugs - Suggesting improvements or ideas - Improving documentation - Fixing bugs - Implementing new features If you're unsure whether something is worth contributing — **open an issue and ask**. --- ## Issues vs. Discussions LeafWiki uses both **GitHub Issues** and **GitHub Discussions** — they serve different purposes: - **Discussions** are for anything that isn't clearly scoped yet: ideas, "what if we...", questions about usage, architecture debates, or feature proposals that need back-and-forth before they're actionable. - **Issues** are for concrete, actionable work: confirmed bugs, and features/changes that are clearly scoped and ready to be implemented. If you're unsure whether your idea is ready to be an issue, **start a discussion first**. A maintainer will turn it into an issue once the scope and approach are clear. This avoids issues sitting around with unresolved design questions that end up being implemented in conflicting ways. --- ## Picking up an issue Issues labeled **`good first issue`** or **`help wanted`** are ready to go — feel free to open a PR directly, no need to ask first. For everything else, please don't jump straight to a PR without working through it first: 1. **Comment on the issue** that you'd like to work on it. 2. If anything about the scope or approach is unclear, **ask in the issue** before writing code. Don't guess and let the PR "answer" the open question — that usually leads to rework or a rejected PR. 3. Wait for a maintainer to confirm the issue is ready to be picked up. This also avoids two people working on the same issue at the same time. 4. Once confirmed, open your PR and reference the issue (see [Pull request guidelines](#pull-request-guidelines)). This applies to anything beyond trivial fixes (typos, obvious one-line bugs, docs). For those, feel free to open a PR directly. --- ## Project principles LeafWiki intentionally follows a small set of design principles. Contributions should respect these ideas: - **Markdown stored on disk** - **Minimal operational complexity** - **Single binary deployment** - **Explicit structure over hidden automation** - **Self-hosting friendly** --- ## Before submitting code For **anything larger than a small fix**, please open an issue first. This helps to: - avoid duplicate work - ensure the change fits the project goals - discuss possible approaches Small improvements, documentation updates, and obvious bug fixes can usually be submitted directly. --- ## Development setup Clone the repository: ``` bash git clone https://github.com/perber/leafwiki.git cd leafwiki ``` Install the dependencies and start the backend and the frontend dev server together: ``` bash make setup make dev ``` Open http://localhost:5173 and log in as `admin` / `devpassword`; Vite proxies the API to the backend on port 8080. `make setup-e2e` additionally installs the Playwright browser for local E2E runs. Without `make dev`, start the two in separate terminals: ``` bash cd ui/leafwiki-ui && npm run dev ``` ``` bash cd cmd/leafwiki go run . --jwt-secret=dev --admin-password=devpassword --public-access=true --allow-insecure=true ``` `--admin-password` only applies while no admin exists. If your `cmd/leafwiki/data` was created with another password, delete that directory for a fresh wiki or run `go run . reset-admin-password` in `cmd/leafwiki`, which prints a new one. Before submitting the code execute `npm run format` in the `ui/leafwiki-ui` directory. If you change the e2e tests, please also run `npm run format` in the `e2e` directory. In the repository root, `make ci` runs `make verify` (small repository checks), `make lint`, `make deadcode` (unreachable Go functions), `make test`, `make cross` (build and vet for Windows and macOS) and `make ui-check` (frontend install, lint, format check, tests and build); each also runs on its own. CI additionally runs the linux/386 tests, govulncheck, Trivy, the install-script test, the e2e lint and the E2E suites, and builds the Dev Container (with `make doctor` inside) on PRs that change its inputs. Trivy scans the Go and npm dependencies on every PR (filesystem scans in the backend and frontend workflows). It also scans the built Docker image, weekly, before each release and on PRs that change an image input such as `Dockerfile`, `go.mod` or `package.json` (those files only trigger the image scan; their dependencies are already covered by the filesystem scans). `make scan-image` runs the image scan locally (needs Docker and `trivy`). Go and Node versions: the `toolchain` line in `go.mod` (the `go` command downloads it) and `.nvmrc` (`mise install` or `nvm use`); `make doctor` compares them with what you have. Translating the UI or adding a language? See [docs/i18n.md](docs/i18n.md). How the code is structured: [docs/development/](docs/development/README.md). --- ## Pull request guidelines To keep reviews efficient, please follow these guidelines: - **Every PR must reference an existing issue** (e.g. `Fixes #123`). PRs without a linked issue — or that weren't discussed on the issue first — may be closed and asked to go through the [issue process](#picking-up-an-issue) instead. - Keep pull requests **small and focused** ([size limits](./docs/development/conventions.md#pull-requests)) - Write every commit in the **[commit style](#commit-style)**; PRs are usually rebase-merged, so the commits land on `main` as they are - Clearly **describe the change** - Avoid unrelated formatting changes - Update documentation if necessary PRs that combine multiple unrelated changes may be asked to split. --- ## AI-assisted contributions Using AI coding agents is fine. The rules are the same as for any other contribution, plus a few that matter more when code is generated: - **You are the author.** You must understand every line you submit and be able to explain and change it during review. "The AI wrote it" is not an answer to a review question. - **Say so in the PR.** Tick the AI box in the PR template and name the tool. This doesn't make a PR less welcome; it helps review. - **Test it yourself, by hand.** Generated code often passes its own tests and still does the wrong thing. For **UI changes**, follow [rule 11](./docs/development/rules.md#tests) and tick both UI boxes in the PR template. A screenshot or short recording speeds up review but is not required. UI PRs without the boxes ticked will be asked to test before review. - **Same scope rules.** One focused change per PR, linked to an issue. No drive-by refactors or reformatting the agent decided to do on the side. - **Don't paste unverified AI output into issues or security reports.** Reproduce the problem yourself first. The [rules](./docs/development/rules.md) are the same for people and agents. [AGENTS.md](./AGENTS.md) points agents at them; most tools read it automatically. Developer docs (architecture, source map, processes, ADRs) are in [docs/development/](./docs/development/README.md). --- ## Commit style LeafWiki uses **Conventional Commits**. Please format commit messages like this: ``` type(scope): short description ``` Examples: ``` feat(editor): add keyboard shortcut for headings fix(search): handle empty query correctly docs(readme): clarify installation instructions refactor(api): simplify page loading logic ``` Common commit types: - `feat` – new functionality - `fix` – bug fix - `docs` – documentation changes - `refactor` – internal improvements - `chore` – maintenance work - `test` – tests Also accepted: `perf`, `style`, `ci`, `build`, `revert`. A `!` after the type or scope marks a breaking change (`feat(api)!: …`). Squash `fixup!`/`squash!`/WIP commits before review. If users or admins will notice the change (a default, a flag, a migration, different behaviour), add a `Behavior-Change:` trailer to the commit: one sentence on what they notice and what to do. The release notes list every such trailer at the top, whatever the commit type; without one, a `refactor`, `chore` or other internal commit only shows up as a count. Use one trailer per change; a commit may carry several. `Behaviour-Change:` works too. ``` feat(example): rename the frobnicate setting Behavior-Change: The `frobnicate` setting is now called `frob`; rename it in your config before upgrading. ``` Git only reads trailers from the last paragraph of the message, so: - Keep the value on one line, or indent every continuation line (as above); an unindented second line ends the trailer block and the trailer is lost. - On a squash merge, GitHub's default message stacks the commit bodies and ends with `---------` and `Co-authored-by:` lines. Move the `Behavior-Change:` lines into that last paragraph (next to `Co-authored-by:`), or they won't reach the release notes. The `Commit messages` workflow checks every commit of a PR; run it locally with `make verify-commits BASE=origin/main`. It is informational, not a required check: a PR with messy commits gets squash-merged instead, under a title the maintainer sets. The PR title only matters in that case. --- ## Feature proposals If you'd like to propose a feature, please include: - the **problem or use case** - why existing functionality is insufficient - a rough idea of the expected behavior Good feature requests focus on **practical real-world usage**. --- ## Documentation contributions Documentation improvements are always welcome. Examples include: - improving explanations - fixing errors or typos - adding examples - clarifying installation steps --- ## Code style Please follow the existing project style: the [rules](./docs/development/rules.md) first, the [conventions](./docs/development/conventions.md) for details. In short, prefer clarity over cleverness and avoid abstractions the code doesn't need yet. --- ## Review process All contributions are reviewed before merging. During review we may: - ask for small improvements - suggest alternative implementations - discuss design decisions This helps keep the project consistent and maintainable. --- ## Questions or discussions If you're unsure about something, feel free to open an issue or discussion. Feedback and ideas are always welcome. --- Thanks again for helping improve **LeafWiki** 🌿