Project Scaffolder
A dynamic, interactive CLI-based project generator that simplifies the process of scaffolding new projects through a tree-based question system and custom template executors.
Features
- Interactive Question Tree: Navigate through a logical hierarchy of choices defined in JSON.
- Extensible Architecture: Easily add new templates and questions by adding JSON files and Python executors.
- Styled CLI Output: Uses
richto provide a clean and professional command-line interface with panels, colors, and spinners. - Robust Input Handling: Powered by
inquirerfor intuitive selections and confirmations. - Environment-Aware Output: Projects and virtual environments are created in
temp/during development, keeping generated files out of version control. - Base Executor Pattern: All executors inherit from
BaseExecutor, which provides a consistent lifecycle and a built-in loading spinner that automatically pauses around interactive prompts.
Installation
Prerequisites
- Python 3.8+
Setup
-
Clone the repository:
git clone <repository-url> cd template
-
Install the required dependencies:
pip install -r requirements.txt
-
Configure your environment by creating a
.envfile in the project root:ENVIRONMENT=development
Accepted values:
development,production.
Usage
To start the project generation process, run the main scaffolder script:
python scripts/scaffolder/scaffolder.py
Follow the on-screen prompts to select your project type, language, and other configurations.
Project Structure
template/
├── .env # Environment configuration (ENVIRONMENT=development|production)
├── questions/ # JSON files defining the question hierarchy
├── executors/ # Executor classes for each supported framework
│ ├── base.py # BaseExecutor abstract class (lifecycle + spinner)
│ └── backend/
│ └── python/
│ └── django/ # Django-specific executors
├── processors/ # Core logic: question loading, input handling, template resolution
├── utils/
│ ├── base.py # Subprocess, file, and venv utilities
│ └── env.py # Environment detection and path resolution
├── constants/ # Framework-specific code snippets and configuration strings
├── typings/ # Shared type definitions and dataclasses
└── scripts/ # Entry points for running the scaffolder
How It Works
- Question Loading: The system starts by loading
questions/base.json. - Dynamic Traversal: Based on user selection, it recursively loads child questions from the file system.
- Template Resolution: Once a leaf node (a final choice) is reached, the system identifies the corresponding executor in the
executors/directory. - Execution: The executor's
run()method is called with the gathered parameters. It starts a loading spinner, delegates togenerate(), and stops the spinner when done.
Environment Modes
The ENVIRONMENT variable in .env controls where generated output is placed.
ENVIRONMENT |
Project output | Virtual environment |
|---|---|---|
development |
<project_root>/temp/ |
<project_root>/temp/venv/ |
production |
Current working directory | <project_root>/venv/ |
The temp/ directory is listed in .gitignore so development output is never committed.
Executor Architecture
All executors inherit from BaseExecutor (executors/base.py) and must implement:
| Method | Purpose |
|---|---|
get_venv_environment() |
Set up and return the venv Python path |
install_dependencies(venv_python_executor) |
Install framework packages |
execute_creation_commands(**kwargs) |
Orchestrate the full scaffold |
generate(**kwargs) |
Resolve arguments and drive the above steps |
prepare_directory() is provided as a concrete default on BaseExecutor — it creates the output directory or prompts the user to replace it if one already exists. Override it only if the executor needs different behaviour.
The public entry point is run(**kwargs), which wraps generate() with a rich loading spinner. Use self._stop_status() / self._start_status() around any interactive inquirer prompts inside your executor to prevent the spinner from blocking user input. Use self._update_status(message) to update the spinner label as execution progresses through steps.
Adding a New Executor
- Create a JSON file in
questions/defining the configuration options for the new template. - Link it to the existing question tree via
questions/base.json. - Create a Python file in the corresponding
executors/path and subclassBaseExecutor:
from src.executors.base import BaseExecutor
from typings.base import ExecutorResponseStatus
class MyFrameworkExecutor(BaseExecutor):
def get_venv_environment(self) -> str:
...
def install_dependencies(self, venv_python_executor: str) -> ExecutorResponseStatus:
...
def execute_creation_commands(self, **kwargs) -> ExecutorResponseStatus:
...
def generate(self, **kwargs):
...
if __name__ == '__main__':
args = MyFrameworkExecutor.build_arg_parser().parse_args()
MyFrameworkExecutor().run(**vars(args))
Contributing
Branching
main— stable branch; only merge via pull request- Feature branches should follow the pattern:
feature/<short-description>(e.g.feature/fastapi-executor) - Bug fix branches:
fix/<short-description>(e.g.fix/venv-path-dev-mode)
Workflow
-
Fork or branch from
main:git checkout -b feature/<short-description>
-
Set up your environment:
pip install -r requirements.txt cp .env.example .env # set ENVIRONMENT=development
-
Make your changes following the conventions below, then commit:
git add <files> git commit -m "feat: short description of change"
-
Push and open a pull request against
main.
Adding a Question
Questions live in questions/ as JSON files and mirror the executors/ directory structure. Each file defines a node in the question tree:
{
"type": "list",
"name": "my_option",
"message": "Choose an option",
"choices": ["Option A", "Option B"],
"children": []
}
Leaf nodes (no children) trigger executor resolution — the scaffolder maps the answer path directly to a file in executors/.
Adding an Executor
Follow the steps in Adding a New Executor above. Additional conventions:
- Place the file at
executors/<category>/<language>/<framework>/<name>.pyto match the question path. - Use
self.consolefor all terminal output — never useprint(). - Use
self._update_status(message)to label each distinct step inexecute_creation_commands. - Call
self._stop_status()before anyinquirer.prompt()andself._start_status()immediately after. - All subprocess calls must use the venv Python executor (
get_venv_python_executor()) rather than bare shell commands, so they work correctly in bothdevelopmentandproductionenvironments.
Code Style
- Follow PEP 8.
- All public methods must have docstrings with
:param:and:return:annotations. - Keep
utils/functions generic and stateless — executor-specific logic belongs in the executor class.
Metadata
Release files for dev-scaffolder 0.0.6
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| dev_scaffolder-0.0.6.tar.gz | 142.9 kB | With provenance | Details for dev_scaffolder-0.0.6.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| dev_scaffolder-0.0.6-py3-none-any.whl | Python 3 | none | any | Details for dev_scaffolder-0.0.6-py3-none-any.whl |
Total release size: 569.8 kB
Release files / dev_scaffolder-0.0.6.tar.gz
| Download URL | dev_scaffolder-0.0.6.tar.gz |
|---|---|
| Size | 142.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d15b190ee1fcdd48ad43f9dd8d4966f96b865726ba687e9b4f2aafa039f44284
|
|
BLAKE2b-256 checksum How to use checksums |
46b83b494ad118b63c588ac2aad31736cf14b6169436df1d4f4661527f2a4f47
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Apr 21, 2026.
Transparency logRelease files / dev_scaffolder-0.0.6-py3-none-any.whl
| Download URL | dev_scaffolder-0.0.6-py3-none-any.whl |
|---|---|
| Size | 426.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
715686f43acda30bcd8b2e762e18d79fadec94560e3257abfb39baf6d0b1c383
|
|
BLAKE2b-256 checksum How to use checksums |
8c6835f25f07705543947f69504a774b1cf9c4a788c896b6e18023ed0f10b2e5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Apr 21, 2026.
Transparency logSecurity for dev-scaffolder 0.0.6
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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for dev_scaffolder-0.0.6.tar.gz
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 Apr 21, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.