No description
  • Rust 44.3%
  • Nix 28.5%
  • TypeScript 25.3%
  • Python 1.4%
  • HTML 0.5%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
jingus ae3b135057
Some checks failed
ci / flake-check (push) Successful in 16s
ci / templates (push) Failing after 1m18s
Merge pull request 'feat: rust-cli template (clap/color-eyre/tracing/tokio CLI, crane build with dep caching)' (#4) from t3code/ddf43383 into main
Reviewed-on: #4
2026-10-20 15:03:09 -05:00
.forgejo/workflows feat: templates repo with standards, CI, and python-uv starter 2026-10-16 15:52:25 -05:00
nix-modules feat: rust-cli template (clap/color-eyre/tracing/tokio CLI, crane build with dep caching) 2026-10-16 21:23:56 -05:00
templates feat: rust-cli template (clap/color-eyre/tracing/tokio CLI, crane build with dep caching) 2026-10-16 21:23:56 -05:00
.envrc feat: direnv .envrc support and template catalog in readme 2026-10-16 16:02:38 -05:00
.gitignore feat: direnv .envrc support and template catalog in readme 2026-10-16 16:02:38 -05:00
AGENTS.md feat: templates repo with standards, CI, and python-uv starter 2026-10-16 15:52:25 -05:00
flake.lock feat: templates repo with standards, CI, and python-uv starter 2026-10-16 15:52:25 -05:00
flake.nix feat: templates repo with standards, CI, and python-uv starter 2026-10-16 15:52:25 -05:00
README.md feat: rust-cli template (clap/color-eyre/tracing/tokio CLI, crane build with dep caching) 2026-10-16 21:23:56 -05:00

starters

Reusable project starters. Every starter is a self-contained nix flake you can instantiate with nix flake init, built to the standards below. Repos created from a starter get a hermetic build, a devshell, locked inputs, static-analysis gates, and forgejo CI out of the box.

Using a template

nix flake show git+https://git.jingus.dev/jingus/starters   # list templates
nix flake init -t git+https://git.jingus.dev/jingus/starters#<name>
# or from a local checkout:
nix flake init -t path:/path/to/starters#<name>

Starters

python-uv-cli

A type-safe Python 3 CLI starter: uv for dependencies and virtualenvs, typer for the CLI, ruff for lint + format, strict mypy for types, and a nix flake for the build system, devshell, and CI. Ships locked inputs on both sides (flake.lock + uv.lock), ruff/mypy/smoke checks as nix derivations, an attic-cached forgejo workflow, an optional direnv .envrc, and a validate self-test app.

nix flake init -t git+https://git.jingus.dev/jingus/starters#python-uv-cli

See templates/python-uv-cli for the full picture.

expo-axum

A mobile app + API starter: an Expo (React Native) TypeScript app with a vite-powered web target (oxlint/oxfmt/vitest for tooling), a Rust Axum backend on Postgres via SeaORM (Argon2id + hashed-session bearer auth behind a custom extractor), crane nix builds with dependency caching, a deterministic docker image, deploy-rs stubs for NixOS, a one-command dev Postgres, and forgejo CI with the two canonical gates plus identity-tagged image publishing.

nix flake init -t git+https://git.jingus.dev/jingus/starters#expo-axum

See templates/expo-axum for the full picture.

rust-cli

A Rust CLI starter: clap (derive API) for argument parsing, color-eyre for error reports, tracing for structured logs, and tokio for async execution. Ships a crane nix build where dependencies compile once and source changes never recompile them, an optimized release profile (thin LTO, stripped), clippy/fmt/test/smoke checks as cached derivations, locked inputs on both sides (flake.lock + Cargo.lock), an attic-cached forgejo workflow, and a validate self-test app.

nix flake init -t git+https://git.jingus.dev/jingus/starters#rust-cli

See templates/rust-cli for the full picture.

Standards

These are the rules a template must follow to live here. The root flake's checks and CI enforce most of them mechanically; reviewers (and agents) should enforce the rest.

Nix first, flakes always

  • Every template is a nix flake, and the flake is the build system: packages.<name> builds the project hermetically (no network, no host toolchains beyond nix itself).
  • Flake structure follows the dendritic pattern with flake-parts and import-tree: a minimal flake.nix (inputs only) whose outputs are mkFlake ... (import-tree ./nix-modules).
  • nix-modules/parts.nix declares the supported systems.
  • One file per concern inside nix-modules/: shell.nix (devshell + perSystem.formatter), checks.nix (validation derivations), apps.nix (the validate app), and packages/<name>.nix per package.
  • Locked inputs are committed: flake.lock always, plus the language lockfile (uv.lock, Cargo.lock, ...). Locks are updated in this repo by CI-red-driven nix flake update / lock-refresh commits — never deleted.
  • Build inputs are narrowed with lib.fileset so unrelated files (lockfiles, CI, nix code) cannot invalidate build caches.

Reproducibility

  • A fresh clone must reach a working state with nothing but nix: nix develop for hacking, nix build/nix run for artifacts.
  • Nothing may depend on tools installed outside nix. For one-off tasks, prefer ephemeral shells — nix shell nixpkgs#<tool> -c <cmd> — over any installation.
  • Python templates pin the interpreter through the devshell (e.g. UV_PYTHON) so uv's virtualenv and the nix build share one version.

Type-safety and static analysis

  • Templates are fully annotated and check with the ecosystem's strictest practical checker in checks.* derivations (mypy --strict for Python, clippy/deny for Rust, ...). Typed libraries ship their marker (py.typed etc.).
  • Formatting and linting (nixfmt for nix, ruff for Python, ...) are checks.* derivations too — they run in nix flake check and get cached like any other build.

Devshells

  • devShells.default provides every tool needed to develop the project: language toolchain, formatters, linters, editor support (e.g. nil).
  • The devshell is the only supported way to get tooling. Never document (or perform) global installs.
  • Templates ship an .envrc containing use flake so direnv users get the devshell automatically on cd. direnv is optional — nix develop is the always-available path — and .direnv/ stays gitignored.

Self-validation contract

  • Every template exposes apps.<system>.validate, runnable from the project root (nix run .#validate). It must verify, at minimum: lockfile freshness, a clean dependency sync from the lockfile, and a smoke test of the built entry point.
  • nix flake check must pass on a freshly initialized copy.

CI

  • Every template ships .forgejo/workflows/ci.yml targeting runs-on: nix, using jingus/actions attic-cache for binary caching and running the two canonical gates:
    1. nix flake check
    2. nix run .#validate
  • The root workflow (this repo) additionally instantiates every template the way a user would (nix flake init -t path:...#<name>) and runs both gates on the initialized copy, so a template can only be merged if it actually works as a starting point.

Bookkeeping

  • Register new templates in nix-modules/templates.nix with a description. The templates check fails if flake.templates and the templates/ directory contents ever drift apart.
  • Every template has a README.md explaining instantiation, the dev loop, verification, and any dual-source trade-offs (e.g. uv.lock vs nixpkgs dependencies).

Adding a new template

  1. mkdir templates/<name> and scaffold it to the standards above (copying an existing template is encouraged).
  2. Register it in nix-modules/templates.nix.
  3. Generate and commit both lockfiles (nix flake lock, language lock).
  4. Verify locally:
    nix flake check                                   # root
    cp -r templates/<name> /tmp/<name>-check
    cd /tmp/<name>-check && nix flake check && nix run .#validate
    nix flake init -t path:/path/to/starters#<name>  # in an empty dir
    
    (Run validate on the copy — it creates a .venv in its working directory, which must not pollute the template itself.)
  5. Commit; root CI re-validates everything.

Repository layout

flake.nix                       # root flake: inputs only
nix-modules/
  parts.nix                     # supported systems
  templates.nix                 # flake.templates registry (checked)
  checks.nix                    # wellformedness + nixfmt checks
  shell.nix                     # devshell + formatter
templates/
  python-uv-cli/                    # the templates themselves (flakes)
  expo-axum/
  rust-cli/
.envrc                          # direnv → root devshell (optional)
.forgejo/workflows/ci.yml       # root validation CI
AGENTS.md                       # rules for agents working in this repo

Agents (human or otherwise) working on this repository must read AGENTS.md first — the short version: never modify global state; use devshells and ephemeral nix shells for everything.