Skip to content

Commit f6f79b2

Browse files
committed
docs: refresh portfolio docs
1 parent 76bbdd5 commit f6f79b2

2 files changed

Lines changed: 65 additions & 104 deletions

File tree

.portfolio/qa.md

Lines changed: 63 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,136 +1,97 @@
11
# Project Q&A
22

3-
## Project Overview
3+
## Overview
44

5-
**quickforge** is a modern Python project bootstrapper that creates production-ready Python projects with a single command. It solves the problem of repetitive project setup by generating complete project structures with 2025's best toolchain already configured: uv for package management, ruff for linting/formatting, basedpyright for type checking, and pytest for testing. The target users are Python developers who want to start new projects quickly without spending hours configuring build tools, CI/CD pipelines, and development environments.
5+
**quickforge** is a Python CLI that bootstraps a complete, modern Python project with one command. It solves the recurring tax of wiring up a package manager, linter, formatter, type checker, test runner, CI config, and editor settings every time you start something new. The target user is a Python developer who wants a fresh project on uv + ruff + basedpyright + pytest without spending an afternoon assembling boilerplate.
66

7-
## Key Features
8-
9-
### 1. One-Command Project Creation
10-
11-
Run `quickforge new myproject` and get a complete, working project with:
12-
- Proper package structure (src layout)
13-
- All tools configured in pyproject.toml
14-
- GitHub Actions CI/CD pipeline
15-
- Pre-commit hooks ready to install
16-
- VS Code settings optimized for the toolchain
17-
- Test skeleton with pytest and coverage
18-
19-
### 2. Multiple Project Types
20-
21-
I support five project types tailored to different use cases:
22-
- **library**: PyPI-publishable packages with src layout
23-
- **cli**: Command-line tools with Typer integration
24-
- **api**: FastAPI/Flask web services
25-
- **app**: Standalone applications
26-
- **script**: Single-file scripts with PEP 723 inline dependencies
27-
28-
### 3. Interactive and Scriptable
7+
## Problem Solved
298

30-
The CLI works in two modes:
31-
- **Interactive**: Prompts guide you through all options with descriptions
32-
- **Non-interactive**: Pass flags for CI/CD usage (`--yes` skips all prompts)
9+
Most Python scaffolding tools either ship outdated defaults (setup.py, black + isort + flake8, mypy) or require so much customization up front that you might as well configure things by hand. quickforge picks one opinionated stack — the one I'd configure manually in 2025 — and emits it correctly in seconds. It also goes the other direction: `audit` and `upgrade` modernize existing projects without trashing user-authored configuration.
3310

34-
### 4. Project Auditing
11+
## Target Users
3512

36-
The `quickforge audit` command analyzes existing projects and identifies:
37-
- Legacy tooling (black, flake8, mypy) that could be modernized
38-
- Missing type annotations and coverage
39-
- Configuration improvements
40-
- Security best practices
13+
- **Python developers starting a new project** — get a working library, CLI, FastAPI service, app, or PEP 723 script with sensible defaults already wired
14+
- **Maintainers of legacy projects** — migrate from Poetry/pip/setuptools to uv and from black/isort/flake8/mypy to ruff + basedpyright without rewriting pyproject.toml by hand
4115

42-
### 5. Automated Migration
16+
## Key Features
4317

44-
The `quickforge upgrade` command migrates projects from:
45-
- Poetry/pip/pipenv/setuptools to uv
46-
- black/isort/flake8 to ruff
47-
- mypy to basedpyright
18+
### One-command project creation
19+
`quickforge new myproject` produces a `src/` layout package, configured `pyproject.toml`, pytest skeleton, GitHub Actions CI, pre-commit hooks, and VS Code settings. Both interactive prompts and a fully scriptable `--yes` mode are supported.
4820

49-
It preserves comments and formatting in existing configuration files.
21+
### Five project archetypes
22+
`library`, `cli` (Typer), `api` (FastAPI), `app`, and `script` (PEP 723 inline dependencies). Each archetype renders only the templates relevant to it, so a CLI project doesn't ship empty FastAPI scaffolding.
5023

51-
### 6. Feature Addition
24+
### Audit and upgrade
25+
`quickforge audit` detects the existing toolchain by signature (lock files, pyproject sections, tool-specific configs) and scores the project from 100. `quickforge upgrade` migrates Poetry/pip/pipenv/setuptools to uv and black/isort/flake8/mypy to ruff + basedpyright, while preserving inline comments via `tomlkit`.
5226

53-
Add optional features to existing projects with `quickforge add`:
54-
- github-actions: CI/CD workflow
55-
- docker: Dockerfile and docker-compose.yml
56-
- docs: MkDocs with Material theme
57-
- pre-commit: Git hooks configuration
58-
- vscode: IDE settings and extensions
59-
- devcontainer: Dev container for VS Code
27+
### Modular feature add-ons
28+
`quickforge add` injects Docker, GitHub Actions, MkDocs, pre-commit, VS Code settings, or a devcontainer into an existing project. Each feature has its own template set and is independently testable.
6029

6130
## Technical Highlights
6231

63-
### Challenge: Comment-Preserving TOML Updates
64-
65-
When upgrading projects, I needed to modify pyproject.toml without destroying users' carefully written comments and documentation. I solved this by using `tomlkit` instead of standard TOML libraries. tomlkit parses TOML into a document model that preserves whitespace, comments, and formatting, allowing surgical modifications.
32+
### Comment-preserving TOML edits during upgrades
33+
Standard `tomli`/`tomli-w` round-trips destroy comments and reflow whitespace, which is unacceptable when modifying a user's hand-written `pyproject.toml`. The upgrader uses `tomlkit`, which parses TOML into a document model that retains formatting, so migrations land as surgical edits rather than rewrites. See `src/quickforge/upgrader.py`.
6634

67-
### Challenge: Cross-Platform Path Handling
35+
### Signature-based toolchain detection
36+
The auditor identifies the active package manager, linter, formatter, and type checker by looking for `poetry.lock`, `Pipfile.lock`, `[tool.black]` sections, `.flake8` files, etc. — not by asking the user. This makes audit and upgrade work on any project without configuration. Detection logic lives in `src/quickforge/auditor.py`.
6837

69-
Template paths needed to work across macOS, Linux, and Windows. I used `pathlib.Path` throughout and carefully handled path separators in templates. The src layout path is dynamically computed based on project type.
38+
### Atomic generation with cleanup on failure
39+
Project creation is a linear pipeline (`validate -> create dirs -> render templates -> write files -> git init -> validate output`). Each stage tracks what it created; on failure, the generator unwinds and removes partial directories rather than leaving a half-formed project on disk. See `src/quickforge/generator.py`.
7040

71-
### Challenge: Atomic Project Generation
41+
### Conditional template rendering
42+
Templates are tagged by archetype and feature flags. `cli.py.j2` is rendered only for `--type cli`; the FastAPI router only for `--type api`; Docker, MkDocs, devcontainer files only when their flags are set. The generated tree contains only files the user actually asked for.
7243

73-
If generation fails midway, users shouldn't be left with a broken partial project. I implemented cleanup logic that removes partially created directories on failure, and validation that verifies the generated project is syntactically correct before reporting success.
44+
## Engineering Decisions
7445

75-
### Innovation: Detection-Based Auditing
46+
### tomlkit vs tomli for upgrades
47+
- **Constraint**: Upgrading a project must not destroy comments or formatting in `pyproject.toml`
48+
- **Options**: `tomli` + `tomli-w` (lossy round-trip), regex-based edits (fragile), `tomlkit` (round-trip preserving)
49+
- **Choice**: `tomlkit` for the upgrader's write path; `tomli` for read-only parsing where round-tripping isn't needed
50+
- **Why**: `tomlkit` keeps the user's documentation intact, which is the whole point of in-place migration
7651

77-
Rather than requiring users to declare their tooling, the auditor automatically detects what tools are in use by checking for lock files, configuration sections, and tool-specific files. This zero-configuration approach means it works on any Python project.
52+
### Typer vs Click vs argparse
53+
- **Constraint**: Need a CLI with subcommands, rich help, and good DX, without writing parser boilerplate
54+
- **Options**: argparse (verbose), Click (mature but decorator-heavy), Typer (Click underneath, infers from type hints)
55+
- **Choice**: Typer
56+
- **Why**: Function signatures double as the CLI definition, Rich integration is built in, and Click's ecosystem is still available underneath when needed
7857

79-
### Innovation: Template Condition System
58+
### Detection-based audit vs explicit declaration
59+
- **Constraint**: Need to audit arbitrary user projects, not just ones generated by this tool
60+
- **Options**: Require a `quickforge.toml` config file, infer from `pyproject.toml` alone, fingerprint by files on disk
61+
- **Choice**: File fingerprinting plus `pyproject.toml` parsing
62+
- **Why**: Zero-configuration UX; works on projects that have never heard of quickforge, including legacy setup.py / Pipfile / Poetry repos
8063

81-
Templates are conditionally rendered based on project configuration. For example, `cli.py.j2` is only rendered for CLI projects, while `main.py.j2` is rendered for app and API projects. This keeps the generated code minimal and relevant.
64+
### src/ layout for the generated default
65+
- **Constraint**: New projects should resist a known Python footgun (importing the in-tree package instead of the installed one during testing)
66+
- **Options**: Flat layout (simpler), src/ layout (industry standard, immune to in-tree shadowing)
67+
- **Choice**: src/ layout
68+
- **Why**: PyPA recommends it, tests run against the installed package, and IDE refactoring is more reliable
8269

8370
## Frequently Asked Questions
8471

85-
### Q1: Why create another project scaffolding tool?
86-
87-
I found that existing tools either generate outdated structures (using setup.py, black, mypy) or require significant configuration. I wanted a tool that embodies 2025 best practices out of the box, with zero configuration needed for the common case. quickforge generates exactly what I would set up manually for a new project.
88-
89-
### Q2: Why uv instead of Poetry or pip?
90-
91-
uv is 10-100x faster than pip and Poetry because it's written in Rust. It handles dependency resolution, virtual environments, and Python version management in one tool. The speed difference is noticeable on every operation, making development more pleasant.
92-
93-
### Q3: Why ruff instead of black and flake8?
94-
95-
ruff combines linting (flake8, pylint) and formatting (black, isort) into one tool that's 10-100x faster. Having one configuration section instead of three separate tools simplifies maintenance. ruff also has more rules and better autofix capabilities.
96-
97-
### Q4: Why basedpyright instead of mypy?
98-
99-
basedpyright is faster (3-5x), has better error messages, and integrates seamlessly with VS Code. It's stricter by default, which catches more bugs. The "based" fork adds additional checks beyond standard pyright.
100-
101-
### Q5: Can I customize the generated templates?
102-
103-
Currently, templates are bundled with the package and not user-customizable. This is intentional to ensure consistency and correctness. If you need significant customization, you can use quickforge as a starting point and modify the generated files, or fork the project.
104-
105-
### Q6: Does quickforge support monorepos?
106-
107-
Not currently. Each invocation creates a single project. For monorepos, I'd recommend using uv workspaces directly. This might be added in a future version.
108-
109-
### Q7: How does the audit scoring work?
110-
111-
The audit starts at 100 points and deducts based on findings:
112-
- Critical issues: -20 points
113-
- Errors: -10 points
114-
- Warnings: -5 points
115-
- Info: -1 point
72+
### Why another Python scaffolder?
73+
Most existing tools encode a 2018-era stack (setup.py, black, isort, flake8, mypy, pip) and treat modern tools as add-ons. quickforge inverts that: uv, ruff, basedpyright, and pytest are the defaults; legacy tools are not options. The generated project is what I'd produce manually if I had unlimited time on day one.
11674

117-
A score above 80 is considered healthy, 60-80 needs attention, and below 60 indicates significant technical debt.
75+
### Why uv instead of Poetry or pip?
76+
uv is written in Rust and resolves dependencies an order of magnitude faster, manages Python versions itself, and produces a portable `uv.lock`. It also accepts the same `pyproject.toml` standards that Poetry helped establish, so the migration cost is small.
11877

119-
### Q8: What happens if the upgrade fails?
78+
### Why ruff instead of black + isort + flake8?
79+
One tool replaces three, with a single config block in `pyproject.toml` and substantially faster runs. The autofix surface is wider, and rule coverage is broader than the combined set it replaces.
12080

121-
Before making any changes, `quickforge upgrade` creates a timestamped backup of all configuration files in `.quickforge_backup_TIMESTAMP/`. If something goes wrong, you can restore from this backup. The upgrade also supports `--dry-run` to preview changes without applying them.
81+
### Why basedpyright instead of mypy?
82+
basedpyright (a fork of pyright) is significantly faster, stricter by default, and produces clearer error messages with better editor integration. For new projects starting fresh, the stricter defaults catch bugs the day they're written.
12283

123-
### Q9: Why is the coverage requirement set at 80%?
84+
### Can I customize the generated templates?
85+
Not at the moment — templates are bundled with the package. The intent is that the generated output is opinionated. If you need a different stack, fork the project or modify the generated files after creation.
12486

125-
I believe 80% is a pragmatic target that encourages good testing habits without becoming burdensome. It allows for untested edge cases and configuration code while ensuring core functionality is covered. The threshold is configurable in the generated pyproject.toml.
87+
### Does it support monorepos?
88+
No. Each `quickforge new` invocation produces a single project. For monorepos, use uv workspaces directly on top of the generated projects.
12689

127-
### Q10: How do I contribute to quickforge?
90+
### How does the audit score work?
91+
The auditor starts at 100 and deducts per finding by severity (critical -20, error -10, warning -5, info -1). 80+ is healthy, 60–80 needs attention, under 60 indicates real technical debt. The threshold is configurable.
12892

129-
The project is open source on GitHub. To contribute:
130-
1. Clone the repository
131-
2. Run `uv sync --extra dev` to install dependencies
132-
3. Run `uv run pre-commit install` to set up hooks
133-
4. Make changes and ensure `uv run pytest` passes
134-
5. Submit a pull request
93+
### What happens if an upgrade fails partway?
94+
`quickforge upgrade` writes a timestamped backup to `.quickforge_backup_<timestamp>/` before changing anything. `--dry-run` prints the planned changes without writing. If the migration aborts mid-way, the backup is the recovery path.
13595

136-
I welcome contributions for new project types, additional features, and bug fixes.
96+
### Why 80% as the default coverage gate?
97+
80% is the inflection point where coverage starts catching real regressions without becoming theater. It leaves room for untested edge cases and config glue while requiring meaningful tests for core paths. The number lives in the generated `pyproject.toml` and is easy to change.

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
**Modern Python project bootstrapper with 2025's best toolchain.**
1010

11-
🚀 **Zero Config****Blazing Fast** • 🔧 **Modern Tools**🎯 **Production Ready**
11+
Zero Config • Modern Tools • One Command
1212

1313
[Installation](#-installation)[Quick Start](#-quick-start)[Project Types](#-project-types)[Commands](#-commands)
1414

@@ -18,7 +18,7 @@
1818

1919
## ✨ What quickforge Does
2020

21-
One command creates a complete, production-ready Python project with modern tooling:
21+
One command creates a complete Python project with modern tooling:
2222

2323
```bash
2424
quickforge new myproject

0 commit comments

Comments
 (0)