Scaffold FastAPI microservices from a stable core template plus declarative
module manifests (bsg-generator).
# From this repo (editable)
uv sync
uv run bsg-generator
# Or install the tool globally
uv tool install .
bsg-generatorInteractive flow: project name → service profile (or custom modules) → repository host (GitHub / GitLab / None) → optional Docker Compose sidecars → venv prompt.
# Non-interactive
bsg-generator create --name my_service --profile auth-service --non-interactive
bsg-generator create --name my_service --profile messaging \
--compose-services rabbitmq --non-interactive --venv
bsg-generator create --name my_service --non-interactive --vcs none --no-git
bsg-generator list-profiles
bsg-generator list-modulesProject names must be valid Python packages: letters, digits, underscores (no hyphens).
- Declarative modules under
generator-core/modules/<id>/(manifest.yaml,files/,fragments/) patched into fixedEXTENSION_*markers - Module Python deps merged into
pyproject.tomlonly when that module is selected - Auth, JWT, and password hashing live in the
authmodule (not core) - Shared
MessageBrokerfacade forrabbitmq/kafka(FastStream) - Atomic generate (temp dir +
os.replace), validation before write - Post-steps:
.env.example+.env, ruff format/check; optional--venv - Git init by default (
--no-gitto skip); CI for--vcs github|gitlabor none - Makefile, Docker image with migration-aware entrypoint, optional Caddy prod override
Extension marker contracts: docs/contracts.md.
Selecting rabbitmq / kafka as modules wires the Python client only
(external broker). Broker containers, Flower, RustFS, and Caddy are added on the
“Add Docker Compose services” step (or via --compose-services):
| Option | When available |
|---|---|
rabbitmq |
rabbitmq module selected |
kafka |
kafka module selected |
flower |
celery module selected |
rustfs |
s3 module selected |
caddy |
always |
generator-core/
core_template/ # FastAPI core with EXTENSION_* markers
modules/ # auth, redis, celery, email, mfa, items, …
profiles.yaml
VERSION # core-template compatibility contract
src/generator/ # contracts, manifest, engine, CLI
tests/
redis ──► redis-cache
redis ──► celery ──► flower, celery-beat ──► scheduler-api (also needs auth)
redis ──► rate-limit ──► auth ──► mfa, oauth
auth ──► users-profiles ──► roles-permissions
items ──► auth
email ──► mfa, push-notifications
s3 ──► rustfs (Compose checkbox)
rabbitmq XOR kafka (shared MessageBroker facade)
openai, external-api, prometheus, opentelemetry, caddy, logging-elasticsearch
Profiles: minimal, auth-service, auth-mfa-service, auth-oauth-service,
items-service, users-service, notifications-service, celery-tools,
observability, messaging, messaging-kafka, full, plus interactive custom.
The caddy module (or Compose checkbox / --compose-services caddy) adds
docker-compose.prod.yml. Dev keeps the API port open; prod closes it and
fronts TLS via Caddy:
make prod-up # -f docker-compose.yml -f docker-compose.prod.yml
make prod-logs
make prod-downSet DOMAIN and ACME_EMAIL in .env (localhost uses Caddy’s internal CA).
While major is 0 (beta): 0.MINOR.PATCH — minor for features/hardening,
patch for hotfixes. Tool version (pyproject.toml) is independent of
generator-core/VERSION.
Pushing a new project.version on main creates a GitHub Release
(.github/workflows/release.yml).
uv sync
uv run pytest
uv run pre-commit install
uv run pre-commit run --all-filesOverride template paths with BSG_CORE_TEMPLATE / BSG_MODULES_DIR if needed.
Custom template/module trees are treated as trusted code; Jinja rendering uses
a sandboxed environment to block classic SSTI class-traversal payloads.
The opentelemetry module ships an OTel Collector config that exports traces to
the collector debug exporter only — wire a real backend before production.
- Validate name, target, module graph, conflicts (nothing written yet)
- Assemble in a temp dir: core + module files + marker patches + dep merge
- Atomic
os.replaceinto the target - Write
.env/.env.example, run ruff; optional venv - Write CI for selected VCS; init git unless
--no-git