Skip to main content

Boilr Generator

CI Docker E2E

Boilr Generator is a modular scaffolding engine for assembling complete Dockerized application stacks from declarative YAML or JSON manifests.

Instead of maintaining one template for every technology combination, Boilr composes reusable modules. The current built-in stack combines Django, PostgreSQL, and Redis through explicit integration modules.

Boilr is currently maintained by a single contributor and is under active pre-1.0 development.

Features

  • Declarative project manifests
  • Reusable backend, database, cache, and integration modules
  • Typed capabilities, requirements, and bindings
  • Provider selection by module, PEP 440 version constraint, and tags
  • Deterministic dependency resolution and cycle detection
  • Typed extension points and contributions
  • Complete generation plans before filesystem mutation
  • Immutable dry runs with human-readable and JSON output
  • Deterministic project state persisted in .boilr/state.json
  • Read-only filesystem drift inspection
  • Explicit reconciliation of detected resource moves
  • Safe state-aware project updates with dry-run support
  • Module addition, update, retention, and removal planning
  • Dependency-aware module lifecycle ordering
  • Atomic state transactions with interrupted-operation detection
  • Create, overwrite, skip, clean, and replace operations
  • SHA-256 fingerprints and content sizes for planned files
  • Safe path boundaries and structured diagnostics
  • Docker Compose and environment-file generation
  • Linux and Windows support on Python 3.11 through 3.14
  • Wheel and source-distribution verification in CI
  • Real Docker E2E coverage for Django, PostgreSQL, and Redis

Installation

Boilr requires Python 3.11 or newer.

Install from the repository

Clone the repository, create a virtual environment, and install the package:

git clone https://github.com/estebanGarnil/boilr-generator.git
cd boilr-generator
python -m venv .venv

Activate the environment on Linux or macOS:

source .venv/bin/activate

Activate it in Windows PowerShell:

.venv\Scripts\Activate.ps1

Install Boilr:

python -m pip install .

The distribution name is boilr-generator. The installation exposes the boilr command, while the Python package remains boilr_generator. The module entry point is also available as python -m boilr_generator.cli.

Development installation

Install the package with its development dependencies:

uv sync --locked --all-groups

Quick start

Create a project.yml manifest:

project:
  name: my_app
  type: fullstack_web
  version: 1.0.0

modules:
  - key: postgres
    variables:
      db_name: my_app
      db_user: my_app
      db_password: change-me
      db_port: 5432

  - key: redis
    variables:
      redis_host_port: 6379
      redis_database: 0

  - key: django
    variables:
      project_name: my_app
      django_settings_module: config.settings.local
      backend_port: 8000
      secret_key: change-me
      debug: true
      allowed_hosts:
        - localhost
        - 127.0.0.1
    options:
      rest_framework: true
      cors: true

  - key: django-postgres
  - key: django-redis

Preview every planned operation without writing anything:

boilr dry-run project.yml generated-project --info

Generate the project:

boilr generate project.yml generated-project --info

Start the generated stack:

cd generated-project
docker compose up --build

The resulting Compose stack contains three services:

  • backend: Django
  • db: PostgreSQL
  • redis: Redis

The integration modules also add:

  • psycopg[binary] and the PostgreSQL Django backend
  • django-redis and the Django CACHES configuration

The credentials in this example are intended only for local development. Replace them before using a generated project in another environment.

Project manifest

A manifest contains project metadata and an ordered list of selected modules.

project:
  name: my_app
  type: fullstack_web
  version: 1.0.0

modules:
  - key: postgres
    variables:
      db_name: my_app
      db_user: my_app
      db_password: change-me
    options: {}

Project metadata

Field Description
name Project name
type Project category used by the caller
version Project version

Module inputs

Each module selection accepts:

Field Description
key Built-in or registered module key
variables Values declared by the module's variable schema
options Optional feature switches declared by the module
bindings Optional provider-selection criteria for named requirements

Unknown modules, variables, and options are rejected. Required values and declared types are validated before resolution.

Provider selection

When a capability has several possible providers, the consumer can select one through the requirement's binding name:

modules:
  - key: django
    bindings:
      primary_database:
        provider: postgres
        version: ">=1,<2"
        tags:
          - database
          - sql

The available criteria are:

Criterion Meaning
provider Exact provider module key
version PEP 440 version specifier matched against the provider module version
tags Tags that must all be present on the provider

Criteria are combined with logical AND. A direct selection must contain at least one criterion.

If no provider matches, Boilr raises a structured provider-selection error. If a unique requirement still matches multiple providers, Boilr reports the remaining candidates as ambiguous.

Built-in modules

Key Type Contract
django Backend Provides backend.python, requires one database.connection
postgres Database Provides database.connection and the db service
redis Cache Provides cache.connection and the redis service
django-postgres Integration Connects the Python backend to PostgreSQL
django-redis Integration Connects Django to Redis

Django

Required variables:

Variable Type Default
project_name string none
django_settings_module string config.settings.local
backend_port integer 8000
secret_key string none
debug boolean true
allowed_hosts list localhost, 127.0.0.1

Options:

Option Type Default
rest_framework boolean true
cors boolean true

PostgreSQL

Variable Type Default
db_name string none
db_user string none
db_password string none
db_port integer 5432

Redis

Variable Type Default
redis_host_port integer 6379
redis_database integer 0

Command-line interface

boilr [OPTIONS] COMMAND [ARGS]...

Available commands:

Command Description
dry-run Build and display a generation plan without mutating the output
generate Generate a project and persist its initial state
status Inspect project drift without modifying files or state
reconcile Explicitly accept detected resource moves into the state
update Safely apply manifest, resource, and module changes

Preview a generation

boilr dry-run [OPTIONS] MANIFEST_PATH OUTPUT_PATH

Options:

Option Description
--info Show the detailed human-readable plan
--json Print the complete serialized plan
--clean Preview cleanup of the output directory
--debug Show the complete traceback when an error occurs

Even with --clean, a dry run does not create, overwrite, remove, or change permissions on any path.

Example:

boilr dry-run project.yml generated-project --clean --json

Generate a project

boilr generate [OPTIONS] MANIFEST_PATH OUTPUT_PATH

Options:

Option Description
--info Show the generation plan before writing
--clean Plan cleanup before generation
--debug Show the complete traceback when an error occurs

Example:

boilr generate project.yml generated-project --clean --info

Inspect a generated project

Inspect tracked resources without modifying the project:

boilr status generated-project

Request the complete observation as JSON:

boilr status generated-project --json

Reconcile a detected move

Inspect possible resource moves first:

boilr status generated-project --json

Preview explicit acceptance of a move:

boilr reconcile generated-project \
  --accept-move RESOURCE_ID=NEW_PATH \
  --dry-run \
  --json

Apply the reconciliation:

boilr reconcile generated-project \
  --accept-move RESOURCE_ID=NEW_PATH

Reconciliation updates only .boilr/state.json. It does not move or rewrite project files.

Update a generated project

After changing project.yml, preview the state-aware update:

boilr update project.yml generated-project --dry-run --info

Request the complete update contract:

boilr update project.yml generated-project --dry-run --json

Apply the update:

boilr update project.yml generated-project --info

Updates compare the committed state, the observed filesystem, and the newly desired project. Modified tracked resources, untracked destinations, unresolved moves, dependency cycles, and stale plans block execution.

Module additions and removals are planned from the complete manifest. Unchanged generated resources may be safely removed, while user-created files and non-empty containing directories are preserved.

See Generated project lifecycle for the complete state, transaction, reconciliation, and safety contract.

Dry-run JSON contract

The JSON representation contains metadata rather than complete file contents:

Field Description
resolved_project Project metadata and resolved module order
output_path Absolute destination path
initial_output_state Filesystem snapshot used to protect plan execution
directories Directories that execution must create
files Complete file operations without embedded content bytes
removals Exact clean or replace removals
docker_services Generated Compose service names
env_variables Generated environment-variable names
clean_output Whether cleanup was requested
summary Stable operation counters and byte totals

Each planned file includes:

{
  "source_path": "/absolute/source/path",
  "destination_path": "/absolute/output/backend/manage.py",
  "relative_destination_path": "backend/manage.py",
  "operation": "render",
  "action": "create",
  "module": "django",
  "mode": 438,
  "content_size": 684,
  "content_sha256": "..."
}

Possible file actions are create, overwrite, and skip.

The summary reports:

  • selected module count
  • captured initial paths
  • directories to create
  • files to create, overwrite, or skip
  • clean and replace removal counts
  • Docker service and environment-variable counts
  • total prepared bytes and bytes that execution would write

Resolution model

Capabilities and bindings

Modules communicate through typed capabilities.

A provider exposes values:

provides:
  - capability: database.connection
    values:
      engine: postgresql
      host: db
      port: "{{ db_port }}"
      name: "{{ db_name }}"
      user: "{{ db_user }}"
      password: "{{ db_password }}"
      service: db

A consumer declares a named requirement:

requires:
  - capability: database.connection
    binding: primary_database
    optional: false
    unique: true
    contract:
      engine: string
      host: string
      port: int
      name: string
      user: string
      password: string
      service: string

The resolver validates the provider values against the requirement contract and exposes the result to templates as a typed binding:

{{ bindings.primary_database.host }}
{{ bindings.primary_database.port }}
{{ bindings.primary_database.service }}

When unique is false, the binding contains a list of matching providers.

Dependency graph

Bindings create dependency edges. Boilr uses the resulting graph to:

  • order modules deterministically
  • assemble providers before consumers
  • place integration modules after the modules they connect
  • reject dependency cycles

Extension points and contributions

A consumer can expose typed extension points:

extension_points:
  python.dependencies:
    type: list
    merge: append_unique
    default: []

  django.settings:
    type: dict
    merge: deep_merge
    default: {}

  database.backend:
    type: string
    merge: replace
    required: true

An integration module contributes through a declared binding:

contributions:
  - target: backend
    extension_point: python.dependencies
    value:
      - django-redis>=7.0,<8.0

  - target: backend
    extension_point: django.settings
    value:
      CACHES:
        default:
          BACKEND: django_redis.cache.RedisCache
          LOCATION: "{{ bindings.cache.url }}"

Supported merge strategies:

Value type Strategies
Scalar replace
List replace, append, append_unique
Dictionary replace, deep_merge

Required extension points must receive a contribution. Incompatible contributions and duplicate replacements are reported before generation.

Planning and execution

Boilr separates generation into two phases:

manifest
   |
   v
validation and resolution
   |
   v
GenerationPlan
   |
   v
execute(plan)
   |
   v
generated project

Planning

Planning performs:

  • manifest and module-input validation
  • capability resolution and provider selection
  • contribution merging
  • dependency ordering
  • template rendering
  • copy-strategy resolution
  • Docker Compose generation
  • environment generation
  • collision detection
  • output-state capture

It returns a complete GenerationPlan without mutating the filesystem.

Execution

Execution applies only the prepared plan. It does not resolve modules, rerender templates, or regenerate Docker and environment configuration.

Before writing, execution verifies the captured initial output state. A stale or externally modified plan is rejected.

This separation provides two guarantees:

  1. A successful dry run describes every mutation that execution would perform.
  2. Executing an unchanged plan writes the exact prepared bytes and applies the planned removals and modes.

Copy strategies

Strategy Behavior
merge Merge the source tree; source files replace matching destinations while unrelated destinations remain
skip Leave an existing destination tree unchanged
replace Remove the destination safely, then recreate it from the source

Replace and clean removals are restricted to paths inside the project output directory.

Diagnostics and safety

All expected failures derive from BoilrError and expose structured context such as:

  • a stable error code
  • a human-readable message
  • the affected module
  • the manifest or generation field path
  • machine-readable context
  • an optional remediation suggestion

Boilr validates or protects:

  • manifest structure
  • duplicate and unknown modules
  • unknown variables and options
  • required values and input types
  • provider versions and tag criteria
  • missing and ambiguous capabilities
  • binding contracts
  • dependency cycles
  • extension-point targets, types, and conflicts
  • template rendering
  • generated file collisions
  • environment-variable names and values
  • source reads and output writes
  • output, clean, and replacement path boundaries
  • symbolic links and unsupported filesystem entries
  • stale generation plans

Use --debug to include the complete traceback for unexpected failures. Without it, the CLI renders the structured Boilr diagnostic.

Canonical exceptions are exported from:

from boilr_generator.exceptions import BoilrError

Compatibility exports from older exception modules remain available temporarily, but new code should use the canonical module.

Internal architecture

project.yml
    |
    v
ProjectManifest
    |
    v
ModuleRegistry
    |
    v
Resolver
    |-- capabilities and requirements
    |-- provider selections
    |-- typed bindings
    |-- dependency graph
    |-- extension points
    └── contributions
    |
    v
ResolvedProject
    |
    v
GenerationPlan
    |
    v
ProjectGenerator.execute(plan)
    |
    v
Generated project

Technology-specific behavior belongs in modules and integrations. The resolver and generation engine remain framework-agnostic.

Creating a module

Built-in modules are stored by category:

boilr_generator/templates/
|-- backend/
|   └── django/
|-- database/
|   └── postgres/
|-- cache/
|   └── redis/
└── integration/
    |-- django-postgres/
    └── django-redis/

A module contains a module.yml manifest and optional source files:

module/
|-- module.yml
└── files/

The module manifest can define:

Section Purpose
meta Name, key, type, version, description, and tags
role Module role group
dependencies Base and optional generated dependencies
provides Capabilities exposed by the module
requires Named capability requirements and contracts
extension_points Typed contribution targets
contributions Values contributed through bindings
variables Required and defaulted module variables
options Optional module features
assembly Priority and destination root
sources.copy File trees copied with a declared strategy
sources.render Jinja templates and destinations
docker Compose services and volumes
exports.env Generated environment variables
docs Inline module summary and notes

Integration modules often have no source files. They connect other modules by requiring their capabilities and contributing dependencies or configuration through extension points.

When adding a module:

  1. keep technology-specific decisions outside the core engine
  2. declare all variables, options, and capability contracts
  3. use an integration module for cross-technology behavior
  4. add resolver, generation, and conflict tests
  5. add a real Docker E2E scenario when practical

Open an issue before starting a large module contribution.

Development and testing

Install development dependencies:

uv sync --locked --all-groups

Run the complete test suite:

uv run --locked --all-groups python -m pytest -q

Run Ruff:

uv run --locked --all-groups ruff check .

Build the wheel and source distribution:

uv build

Run the Docker E2E test on Linux or macOS:

BOILR_RUN_DOCKER_E2E=1 uv run --locked --all-groups python -m pytest -q tests/e2e/test_docker_stack.py -m docker_e2e -W error

Run it in Windows PowerShell:

$env:BOILR_RUN_DOCKER_E2E = "1"
uv run --locked --all-groups python -m pytest -q tests\e2e\test_docker_stack.py -m docker_e2e -W error
Remove-Item Env:BOILR_RUN_DOCKER_E2E

CI validates:

  • Python 3.11, 3.12, 3.13, and 3.14
  • Ubuntu and Windows
  • the complete test suite
  • Ruff
  • wheel and source-distribution contents
  • installation of the wheel outside the source tree
  • built-in module discovery from the installed wheel
  • generation from the installed package
  • a real Django, PostgreSQL, and Redis Docker stack

Project status and roadmap

Version 0.1.1 is functional and under active development.

The current engine supports:

  • strict manifest and module-input validation
  • declarative capability resolution
  • advanced provider selection
  • typed contributions
  • deterministic and exhaustive planning
  • safe plan execution
  • Dockerized Django, PostgreSQL, and Redis generation
  • cross-platform CI and distribution verification
  • deterministic generated-project state
  • read-only drift observation
  • explicit resource-move reconciliation
  • safe state-aware project updates
  • dependency-aware module lifecycle transitions
  • atomic state transactions

Potential future work includes:

  • a Django API around the generator
  • a web interface
  • a module marketplace
  • additional backend and frontend modules
  • MySQL, MongoDB, and message-queue providers
  • reverse-proxy and deployment modules

Contributing

Contributions are welcome. See CONTRIBUTING.MD for development and contribution guidance.

Useful contributions include:

  • new modules and integrations
  • examples
  • documentation
  • cross-platform tests
  • diagnostics and safety improvements

Why Boilr exists

Modern projects repeatedly need the same foundations: an application framework, database, cache, environment configuration, containers, and service orchestration.

Maintaining a full template for every possible combination does not scale. Boilr instead treats each technology as a reusable module and each cross-technology decision as an explicit integration.

The long-term goal is an interface-agnostic ecosystem in which a CLI, API, web application, or automation can produce the same manifest and rely on the same deterministic generator core.

License

Boilr is distributed under the MIT License.

Metadata

Release files for boilr-generator 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for boilr-generator 0.1.1
File Size Uploaded
boilr_generator-0.1.1.tar.gz 152.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for boilr-generator 0.1.1
File Interpreter ABI Platform
boilr_generator-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 262.3 kB

Release files / boilr_generator-0.1.1.tar.gz

Download URL boilr_generator-0.1.1.tar.gz
Size 152.6 kB
Tags Source
SHA-256 checksum
How to use checksums
0f2e8e925dbb23d0227e6009d71c0b2177e04e1fc5d10e620515f783e2b8807b
BLAKE2b-256 checksum
How to use checksums
f177259ea583cd611c5848ba31a8b39d1aea65a4ad7283c5c9c4b6a43436df02
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release files / boilr_generator-0.1.1-py3-none-any.whl

Download URL boilr_generator-0.1.1-py3-none-any.whl
Size 109.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
af4e394a7ed565a338b8adfd7c4b41886f8db113acec4e53af5e036e0c8e11b0
BLAKE2b-256 checksum
How to use checksums
8fd6c69e703a9bb09fcd5c9bd08a9966da7823a1d27f4eec653664985034ea56
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page