Ready-to-build Bazel projects, wired up with the Aspect CLI and best-practice tooling. Pick a language, generate a project, and start shipping — no Bazel boilerplate, no toolchain yak-shaving.
This repo is the source of truth for both paths below: the projects
aspect init scaffolds and the template
repositories published under
github.com/aspect-starters are rendered
from the one template tree here, so they never drift.
Install the Aspect CLI: https://aspect.build/docs/cli/install
aspect initaspect init fetches the latest template, prompts for the languages and features
you want (or pass --preset <name>), and renders a ready-to-build Bazel
workspace — no extra tools required.
Each preset is also published as a GitHub template repository under github.com/aspect-starters — click Use this template (or Fork), or:
git clone https://github.com/aspect-starters/<preset>The Status column shows the latest CI run on each starter's main branch.
| Repo | Stack | Status |
|---|---|---|
| minimal | An empty, correctly-configured Bazel workspace | |
| go | Go | |
| py | Python | |
| js | JavaScript & TypeScript | |
| java | Java | |
| kotlin | Kotlin | |
| scala | Scala | |
| cpp | C & C++ | |
| rust | Rust | |
| ruby | Ruby | |
| shell | Bash / shell | |
| kitchen-sink | Everything — all languages + OCI, protobuf, release stamping, codegen |
Building a polyglot monorepo? Start from
kitchen-sink — every
language and feature wired together — or run aspect init --preset kitchen-sink.
- 🧱 Latest Bazel (bzlmod) with curated flags via
bazelrc-preset.bzl - 🧰 Hermetic dev environment via
bazel_env.bzl+rules_multitool— tools on your PATH, no manual installs - 🎨 Formatting & linting built in with
rules_lint - 📦 Native package-manager integration for the language (pip/uv, pnpm, go.mod, Cargo, Maven, Bundler, …)
- ⚙️ Working GitHub Actions CI that runs
aspect build/test/lint/formaton ephemeral runners — green out of the box - 🐳 OCI containers via
rules_oci(where applicable) - 📌 A pinned Aspect CLI version (
.aspect/version.axl) so your whole team and CI use the same tooling
The rest of this README is for maintainers of the template itself. Found a bug
or want to improve a starter? The starter repos are generated artifacts —
file issues and PRs here, against this repo, not against the aspect-starters
repos.
One shared renderer drives all three consumers (aspect init, this repo's CI,
and the aspect-starters publishing job):
| Path | Purpose |
|---|---|
template/ |
The jinja2 template tree rendered into a new project. |
template-config.json |
Template config as data: presets → feature flags, per-file inclusion rules, the copy-verbatim (no_render) list, and the executable list. Read at runtime by the renderer — aspect init never load()s any template code. |
render.axl |
The generic, template-agnostic renderer. Embedded in aspect init; reads template-config.json for everything template-specific (render(ctx, config, template_dir, out_dir, project_snake, flags)). |
dev.axl |
aspect render-preset task — renders one preset locally (used by CI + publishing). |
user_stories/ |
Executable walkthroughs exercised in CI. |
aspect render-preset --preset py --out /tmp/my_project --name my_projectConditionals in the template use jinja2 ({% if python %} ...) with feature
flags from the selected preset; the project name is substituted as
{{ project_snake }}.
CI renders every preset, regenerates lockfiles, then runs aspect build,
aspect test, and (for lint-enabled presets) aspect lint / aspect format
against the generated workspace — gating template changes before they land on
main. See .github/workflows/ci.yaml.