diff --git a/docs/UIUX_BRANDING_HANDOFF.md b/docs/UIUX_BRANDING_HANDOFF.md index 5b75cf3..9047d1a 100644 --- a/docs/UIUX_BRANDING_HANDOFF.md +++ b/docs/UIUX_BRANDING_HANDOFF.md @@ -1,3 +1,438 @@ -# UI/UX branding handoff +# UI/UX And Branding Handoff -Placeholder for website/marketing assets once the docs site exists. +Use this document as the opening context for a new chat focused on improving the Create Python App (CPA) ecosystem branding, UI/UX, website, landing pages, template presentation, and developer-facing engagement. + +## Goal + +Run a complete UI/UX and branding review across the Create Python App ecosystem and then implement improvements that make the project feel more polished, trustworthy, memorable, cozy, modern, and attractive to developers. + +The target outcome is not just "better looking". The goal is better engagement, higher adoption, clearer positioning, stronger brand identity, and a more delightful first impression across GitHub, PyPI, the website (when it exists), and generated/template-facing experiences. + +## Repositories And Areas To Review + +Primary repositories: + +- `Create-Python-App/create-python-app` (this monorepo) +- `Create-Python-App/cpa-templates` (template and extension catalog) +- `Create-Python-App/homebrew-tap` and `Create-Python-App/aur-package` (distribution) +- Website repository (optional, not yet created; see `docs/CPA_TEMPLATES_TRACKING.md`) + +Primary surfaces: + +- Root repository README in `create-python-app` +- Package README in `packages/create-awesome-python-app/README.md` +- SVG hero banner at `packages/create-awesome-python-app/assets/hero.svg` +- CLI terminal experience (`create-awesome-python-app`) +- Template catalog (`templates.json` in `cpa-templates`) +- Extension/addon catalog pages (future website) +- Template landing pages or docs pages +- Generated project starter UIs, especially FastAPI and full-stack templates +- Any demo screenshots, cards, badges, icons, diagrams, and onboarding copy +- Docker image, Homebrew formula, and AUR package presentation + +## CPA Brand Foundation + +Working identity from `docs/BRAND.md` (to be refined): + +- **Tagline:** One command. Any Python stack. +- **Story:** choose template -> add addons -> ship with uv +- **Positioning:** Composable scaffolding CLI for production-ready Python apps. +- **Tooling anchor:** uv-first workflow (PyPI via `uvx`, workspace dev via `uv sync`). + +Designers should treat this as a starting point, not a final brand system. The next pass should evaluate whether the tagline, story arc, and visual identity fully support adoption and trust. + +## CLI Terminal Experience (Current Implementation) + +The CLI is the primary interactive surface today. Designers and implementers must understand how it behaves before proposing changes. + +### Output channel: Rich on stderr + +All user-facing CLI output uses Rich `Console(stderr=True)` in: + +- `packages/create-awesome-python-app/src/create_awesome_python_app/cli.py` +- `packages/create-awesome-python-app/src/create_awesome_python_app/catalog.py` + +Stdout stays clean for piping and scripting. Status, tables, prompts metadata, and colored messages go to stderr. + +### Version and banner + +- `--version` prints the package version string only (no banner, no extra copy). +- `--info` / `-i` prints environment diagnostics via `print_env_info()` (OS, Python, uv tooling). +- There is no animated or ASCII-art startup banner today. +- The package README references `packages/create-awesome-python-app/assets/hero.svg` as a static banner image (dark slate background `#0f172a`, teal headline `#14b8a6`). This is minimal and not yet aligned with a full brand system. + +### Interactive vs non-interactive (CI) + +Default behavior: + +```text +want_interactive = interactive if interactive is not None else (not _in_ci()) +``` + +- When `CI` is `1`, `true`, or `yes`, interactive prompts are skipped unless `--interactive` is passed explicitly. +- In non-interactive mode without `--template`, the CLI exits with: `--template is required in non-interactive mode`. +- CI pipelines and Docker runs should use explicit flags: `--template`, `--addons`, `--no-interactive`, `--set key=value`. + +Flags: + +- `--interactive` / `--no-interactive` override the CI default. +- `--set key=value` supplies custom option answers without prompts. + +### Questionary prompt flows + +Interactive mode uses `questionary` with consistent markers: `qmark="?"`, `pointer=">"`. + +#### 1. Template selection (autocomplete) + +When no `--template` is provided and interactive mode is on: + +- Prompt: `Pick a template (type to search)` +- Control: `questionary.autocomplete` with `match_middle=True` +- Choices: built from `build_template_choices()` in `catalog.py` +- Each choice shows a category badge, template name, slug, optional labels, and description +- Final choice: `Use my own template URL` -> `questionary.text` for a custom URL + +#### 2. Extension selection (checkbox, two-step) + +When no `--addons` are provided and interactive mode is on: + +- Step A: `Which kinds of extensions do you need?` -- category-level checkbox +- Step B: per selected category, `{CategoryName} extensions` -- item-level checkbox +- Choices are filtered by template type compatibility + +#### 3. Custom options (text / confirm) + +From `cpa.config.json` or catalog `customOptions`: + +- `confirm` for boolean options +- `text` for string options +- Password/invisible types are skipped with a yellow warning + +### Category badge colors + +Template list badges use deterministic ANSI colors from `_CATEGORY_PALETTE` in `catalog.py`: + +| Index | ANSI color | Typical use | +|-------|------------|-------------| +| 0 | yellow (`\033[33m`) | category badge | +| 1 | green (`\033[32m`) | category badge | +| 2 | cyan (`\033[36m`) | category badge | +| 3 | magenta (`\033[35m`) | category badge | +| 4 | blue (`\033[34m`) | category badge | + +Color selection: `sum(ord(char) for char in category_slug) % 5`. Respects `NO_COLOR` (plain text, no ANSI). + +Badge label: compact form from `short_category_label()` (strips "Applications", "Application", "Boilerplate"; abbreviates long names to initials). + +Design implication: terminal category colors are slug-hash-driven, not semantically mapped (e.g. "backend" is not always blue). A future brand system may want stable category-to-color mapping for docs and website cards. + +### Rich semantic color usage + +| Style | Meaning | Examples | +|-------|---------|----------| +| `[red]` | Blocking error, exit code 1-2 | Invalid `--set`, invalid `--refresh`, missing template, catalog slug errors, strict version mismatch, cache verify failure | +| `[yellow]` | Warning, recoverable | Catalog fetch fallback, config parse warning, skipped custom option, version behind latest (non-strict), cache outdated | +| `[green]` | Success | `Created {project}`, cache clean/remove success, cache verify pass | +| `[cyan]` | Primary identifier | Cache entry IDs | +| `[dim]` | Secondary/metadata | URLs, refs, ages, empty-state hints | + +### Error and warning message tone + +Current copy is direct, actionable, and developer-oriented: + +- States what failed and what to do next. +- Catalog errors: `Invalid catalog slug: '{spec}'. Run --list-templates / --list-addons or pass a full URL.` +- Validation errors name the flag and expected format: `Invalid --set {item} (expected key=value)` +- Refresh errors enumerate valid values: `always, stale, manual` +- Missing dependency: `questionary not available` (exit 1) +- Catalog resilience: `[cpa] Could not refresh catalog ({err}); using disk cache.` or `using fixture.` +- Version notice: `You are running create-awesome-python-app {current}, latest is {latest}.` + +Tone guidelines for future copy: + +- Prefer imperative next steps over apology. +- Keep messages one or two lines; use `[dim]` for supplementary detail. +- Prefix recoverable catalog issues with `[cpa]` for grep-friendly logs. +- Avoid jargon; assume the reader is a Python developer familiar with uv and git URLs. + +### Cache subcommand UI + +`create-awesome-python-app cache` provides `dir`, `list`, `clean`, `verify`, `outdated`, `update`, `doctor`. + +Visual patterns: + +- Column-aligned tables for `list` and `outdated` +- `[OK]` / `[FAIL]` style marks via green check / red cross in terminal (Unicode today; consider ASCII `[ok]` / `[fail]` if brand requires strict ASCII everywhere) +- Empty states use `[dim]` with a hint to populate the cache + +## What Was Already Done + +CPA is earlier in its branding maturity than Create Node App (CNA). Documented baseline: + +Completed in `create-python-app`: + +- Root `README.md` with ecosystem table, install paths (uvx, Homebrew, AUR, Docker), and monorepo layout. +- Package README at `packages/create-awesome-python-app/README.md` with minimal hero SVG reference. +- Placeholder hero SVG at `packages/create-awesome-python-app/assets/hero.svg` (dark background, teal text). +- Working brand notes in `docs/BRAND.md` (tagline and story). +- Full interactive CLI with CNA-parity flows (autocomplete templates, checkbox extensions, custom options). +- Rich stderr output and semantic coloring across scaffold and cache commands. +- Catalog integration with `cpa-templates` default URL and `CPA_CATALOG_URL` override. + +Not yet done (gaps vs CNA handoff completeness): + +- No website repository or deployed landing pages. +- No polished npm/PyPI README engagement copy (PyPI README is minimal). +- Hero SVG and root README lack a cohesive visual identity system. +- No screenshots, template cards, or curated "build paths" for marketing. +- Generated template starter UIs not yet reviewed for premium first-run experience. +- `docs/UIUX_BRANDING_HANDOFF.md` was a placeholder until this document. + +## Known Current State + +The CLI experience is functional and CNA-aligned for catalog flows, but the broader UI/UX and branding system still needs a full pass. + +Current CLI aesthetic: + +- Rich semantic colors (red/yellow/green/cyan/dim). +- Hash-based category badge colors in terminal. +- Minimal hero SVG (slate + teal). +- No startup banner or branded prompt chrome beyond questionary defaults. + +Current brand direction (from `docs/BRAND.md`): + +- uv-first Python scaffolding. +- Composable templates + extensions. +- Production-ready positioning. + +Do not assume the current teal-on-slate hero or hash-colored badges are final. Treat them as implementation defaults to review and potentially evolve toward a cohesive design system. + +## User Intent For The New Chat + +The user wants a complete review and improvement cycle for: + +- UI/UX of landing pages (when website exists). +- Branding across the whole CPA project. +- Website repo quality and visual design (greenfield). +- Template previews and starter UX in `cpa-templates`. +- Visual consistency between GitHub, PyPI, docs, CLI, and templates. +- Engagement and adoption. +- A more cozy, attractive, polished, memorable brand. +- CLI prompt flow polish (autocomplete, checkbox, error tone, banner). + +The user explicitly wants the new chat to review everything, not only CLI internals or README tweaks. + +## Desired Review Mindset + +Start with discovery and audit before implementing. + +Review the ecosystem like a product designer, brand strategist, frontend engineer, and developer advocate. + +Assess: + +- First impression (GitHub README, PyPI page, first `uvx` run). +- CLI prompt clarity and perceived quality. +- Visual hierarchy in terminal lists and cache tables. +- Messaging clarity (tagline, story, uv positioning). +- Brand memorability. +- Emotional tone (cozy vs cold infrastructure). +- Developer trust. +- Copy quality across errors, warnings, and success states. +- Accessibility (contrast, `NO_COLOR` respect, screen reader limits of terminal UIs). +- Responsiveness (N/A for CLI; required for website and template UIs). +- Consistency across surfaces. +- Conversion path from visitor to first scaffold. +- Conversion path from user to contributor. +- Whether generated templates feel premium or generic. +- Parity and differentiation vs Create Node App. + +Avoid generic "AI slop". The design should not feel like a generic SaaS landing page or generic neon devtool. It should feel intentional, distinctive, and warm. + +## Branding Direction To Explore + +Explore a brand that balances: + +- Cozy developer workspace. +- Polished open-source infrastructure. +- Productive scaffolding/composition. +- Friendly automation. +- Craft, clarity, and reliability. +- Modern but not cold. +- Technical but approachable. +- uv-native Python identity (distinct from Node/npm CNA). + +Potential themes to evaluate: + +- Cozy command center. +- Developer greenhouse/nursery for growing Python apps. +- Modular workbench. +- Creative coding studio. +- Friendly infrastructure toolkit. +- Warm terminal / soft cyberpunk. +- Bento-grid developer dashboard. +- Calm productive OS. +- "Ship with uv" velocity story. + +Potential visual vocabulary: + +- Soft gradients. +- Warm dark mode. +- Cream/off-white surfaces. +- Muted greens, amber, violet, cyan (align with hero teal `#14b8a6` or evolve it). +- Friendly geometric icons. +- Cards with depth but not heavy glassmorphism. +- Clear screenshots and product diagrams. +- Human-readable CLI examples in docs. +- Template cards that feel curated, not dumped from JSON. +- Stable category colors shared between terminal badges, website, and docs. + +## Questions The New Chat Should Answer + +Before implementation, produce a complete audit answering: + +- What is the current brand personality? +- What should the brand personality become? +- Does the CLI first run explain the product clearly in the first 5 seconds? +- Do autocomplete and checkbox flows feel premium and discoverable? +- Should category badge colors become semantic instead of hash-based? +- Does the PyPI package README convert visitors into users? +- Does the root GitHub README convert visitors into contributors? +- Are templates presented in a way that feels premium and trustworthy? +- Are template/generated UIs visually appealing enough? +- Are screenshots, demos, and visual assets consistent? +- Are colors, fonts, spacing, and iconography coherent across CLI, README, and templates? +- Is `NO_COLOR` / non-interactive / CI behavior documented and visually acceptable? +- Are CTAs clear (uvx install, template pick, addon select)? +- Is AI-ready positioning clear but not gimmicky? +- What is missing for adoption and trust? +- What should be redesigned first for highest impact? +- How does CPA differentiate from CNA while maintaining parity? + +## Suggested Work Plan For New Chat + +1. Discover repositories and docs (`README.md`, `docs/`, `AGENTS.md`, `CONTRIBUTING.md`, `docs/BRAND.md`, CI config). +2. Run the CLI interactively and in CI mode; capture stderr output samples. +3. Read `catalog.py` and `cli.py` for prompt and color behavior. +4. Inspect `cpa-templates` catalog and starter template UIs. +5. Inspect the website repo if/when created. +6. Audit current UI/UX and branding across all surfaces. +7. Produce a prioritized design strategy. +8. Define a cohesive brand direction (extend `docs/BRAND.md`). +9. Propose CLI banner, hero SVG, and category color system updates. +10. Implement improvements incrementally. +11. Validate with lint/build/tests and manual CLI screenshots where applicable. +12. Open PRs only after review and green checks. + +## High-Impact Improvements To Consider + +CLI and terminal: + +- Optional branded banner on first interactive run (respect `--no-interactive` and CI). +- Refined questionary styling or custom prompt prefix aligned with brand. +- Semantic category color map shared with docs/website. +- Improved empty states and catalog fallback messaging. +- ASCII-safe success/error marks if Unicode checkmarks are undesirable in some terminals. +- Consistent `[cpa]` prefix for all recoverable warnings. + +Website (future): + +- Rework homepage hero and above-the-fold messaging. +- Product story: choose template, add addons, ship with uv. +- Visual template/extension catalog cards using stable category colors. +- Popular recipes or build paths (e.g. FastAPI + GitHub setup). +- Contributor-oriented section. +- Screenshots or diagrams consistent with the brand. +- Mobile layout and spacing. +- CTA hierarchy toward `uvx create-awesome-python-app@latest`. + +Templates (`cpa-templates`): + +- Review generated landing pages and starter homepages. +- Replace generic starter screens with polished, branded examples. +- Premium first-run experience after scaffold completes. +- Ensure accessibility and responsive behavior in web templates. + +Docs and READMEs: + +- Engaging PyPI README with raw GitHub hero URL for reliable rendering. +- Contributor-focused root README. +- Align messaging across README, `docs/BRAND.md`, and future website. +- Consistent terms: templates, extensions/addons, uv, CI-friendly, `cpa.config.json`. +- Document interactive vs `--no-interactive` UX for CI authors. + +Visual identity: + +- Define palette and typography recommendations (extend hero SVG direction). +- Define card/icon/badge style for catalog and docs. +- Define illustration/hero style. +- Define voice and tone (match CLI error copy guidelines). +- Define how "cozy" and "developer infrastructure" coexist. +- Map `_CATEGORY_PALETTE` colors to branded hex values for non-terminal surfaces. + +## Constraints And Standards + +- Documentation, PR descriptions, and commit messages should be in English. +- Respect repo-specific instructions and existing conventions. +- Do not commit without review. +- Prefer small, correct changes over large unfocused rewrites. +- Validate commands with evidence (`uv run pytest`, `make lint`, etc.). +- Preserve PyPI/GitHub rendering compatibility. +- For SVGs, avoid invalid XML, external fonts, scripts, and unsupported constructs. +- For PyPI README images, prefer absolute raw GitHub URLs if PyPI rendering is required. +- Use accessible contrast and readable text sizes. +- Respect `NO_COLOR` and CI non-interactive defaults in any new CLI styling. +- Keep Rich output on stderr; do not break stdout piping. +- Prefer ASCII in new user-facing docs unless terminal fidelity requires otherwise. + +## CLI Behavior Reference (Quick) + +```text +# Interactive (default when not in CI) +uvx create-awesome-python-app@latest my-app + +# Non-interactive (CI / scripting) +uvx create-awesome-python-app@latest my-app \ + --template fastapi-starter \ + --addons github-setup \ + --no-interactive \ + --no-install + +# Version (stderr, plain version string) +create-awesome-python-app --version + +# List catalog (Rich tables on stderr) +create-awesome-python-app --list-templates +create-awesome-python-app --list-addons --template fastapi-starter +``` + +Environment variables affecting UX: + +| Variable | Effect | +|----------|--------| +| `CI` | Disables interactive prompts unless `--interactive` | +| `NO_COLOR` | Disables category badge ANSI colors | +| `CPA_CATALOG_URL` | Override catalog source | +| `CPA_NO_CATALOG_CACHE` | Force catalog refresh | +| `CPA_STRICT_VERSION` | Treat version mismatch as error | + +## Suggested Opening Prompt For New Chat + +Use this as the first message in the new chat: + +```text +We need to do a full UI/UX and branding review of the Create Python App ecosystem. + +Please start with discovery and audit before implementing. Review the root create-python-app repo, the package README, cpa-templates, and docs/BRAND.md. The goal is to improve engagement, attraction, branding, cozy developer experience, visual consistency, and conversion across GitHub, PyPI, docs, CLI, and generated starter UIs. + +The CLI already uses Rich on stderr, questionary autocomplete/checkbox flows, and hash-based category badge colors from catalog.py. Evaluate whether those defaults should evolve into a cohesive brand system. Pay attention to error message tone, interactive vs CI non-interactive behavior, and the minimal hero SVG. + +Previous work established basic READMEs and BRAND.md notes, but now I want a broader review and a stronger cohesive brand direction. Do not assume the current teal-on-slate hero or terminal colors are final. + +Focus on: CLI prompt UX, landing pages (when website exists), template catalog presentation, generated starter pages, README visual presentation, copy, CTAs, accessibility, cozy/premium branding, and developer trust. + +First, inspect the repos and produce a prioritized audit + implementation plan. Then implement the highest-impact improvements, validate, self-review, and prepare PRs when ready. +``` + +## Final Note + +The next chat should not simply tweak the hero SVG or badge colors in isolation. It should treat the whole Create Python App ecosystem as a product and brand that needs a cohesive design system, stronger storytelling, and better visual polish across every developer touchpoint -- from the first `uvx` run through the generated template's first page. diff --git a/packages/create-python-app-core/README.md b/packages/create-python-app-core/README.md index 291ea16..9ea59e6 100644 --- a/packages/create-python-app-core/README.md +++ b/packages/create-python-app-core/README.md @@ -1,15 +1,269 @@ # create-python-app-core Programmatic scaffolding engine behind Create Awesome Python App. +Import the scaffolding pipeline -- composable, headless, and CI-ready. + +Requires **Python >= 3.12**. + +> This is the _engine_ package. For the interactive CLI, use +> [`create-awesome-python-app`](https://pypi.org/project/create-awesome-python-app/) +> instead. + +--- + +## Installation + +```bash +pip install create-python-app-core +``` + +Or with uv: + +```bash +uv add create-python-app-core +``` + +--- + +## Usage + +### Scaffold a project programmatically + +```python +import asyncio +from create_python_app_core import create_python_app + + +async def main() -> None: + await create_python_app( + "my-app", + { + "projectName": "my-app", + "template": "file:///path/to/template", + "install": True, + }, + transform_options=lambda opts: asyncio.sleep(0, result=opts), + ) + + +asyncio.run(main()) +``` + +### Scaffold with the installer API ```python -from create_python_app_core import ( - create_python_app, - check_python_version, - check_for_latest_version, - print_env_info, - CPA_USER_AGENT, +from create_python_app_core import scaffold_project + +scaffold_project( + "my-app", + template="file:///path/to/template", + addons=[], + extend=[], + install=True, + force=False, + offline=False, ) ``` -Requires **Python >= 3.12**. +### Resolve a template source + +```python +from create_python_app_core import resolve_source, get_template_dir_path + +source = resolve_source( + "https://github.com/Create-Python-App/cpa-templates?ref=main&subdir=fastapi" +) +print(source.kind) # github +print(source.ref) # main +print(source.subdir) # fastapi +``` + +### Download a repository into the cache + +```python +from create_python_app_core import resolve_source, download_repository + +source = resolve_source("https://github.com/org/my-template") +root = download_repository(source, refresh="stale", offline=False) +template_dir = get_template_dir_path(source, root) +``` + +### Load template configuration + +```python +from pathlib import Path + +from create_python_app_core import load_cpa_config + +cfg = load_cpa_config(Path("/path/to/template/cpa.config.json")) +for opt in cfg.custom_options: + print(opt.key, opt.default) +``` + +### Check environment info + +```python +from create_python_app_core import print_env_info + +print_env_info() +# Prints Python, platform, uv, and git info. Then exits. +``` + +### Validate the Python version + +```python +from create_python_app_core import check_python_version + +check_python_version(">=3.12", "my-tool") +# Exits with code 1 if the interpreter does not match. +``` + +--- + +## API Reference + +All public exports from `create_python_app_core`: + +### Functions + +| Signature | Description | +| --------- | ----------- | +| `create_python_app(project_directory, options, transform_options=None)` | Async orchestrator. Applies `transform_options`, then delegates to `scaffold_project`. | +| `scaffold_project(project_directory, *, template, addons=None, extend=None, force=False, install=True, offline=False, refresh=None, keep_on_failure=False, cache_dir=None, options=None)` | Main scaffolding pipeline. Resolves sources, downloads layers, merges files, runs `uv sync`, and initializes git. | +| `resolve_source(spec, *, cache_dir=None)` | Parses a template/extension specifier (GitHub URL, `file://`, slug) into a `ResolvedSource`. | +| `get_template_dir_path(source, root)` | Returns the `template/` subdirectory when present, otherwise the resolved root. | +| `default_cache_dir()` | Returns `CPA_CACHE_DIR` or `~/.cache/cpa`. | +| `download_repository(source, *, offline=False, refresh=None, cache_root=None)` | Clones or refreshes a Git repo into the cache. Returns the entry directory. | +| `read_cache_meta(entry)` | Reads `.cpa-cache.json` metadata from a cache entry. | +| `write_cache_meta(entry, meta)` | Writes `.cpa-cache.json` metadata for a cache entry. | +| `load_cpa_config(path)` | Loads optional `cpa.config.json` (custom CLI prompts). Returns empty `CpaConfig` when missing. | +| `assert_directory_is_empty(path, *, force=False)` | Raises `NonEmptyTargetDirectoryError` when the target exists and is non-empty. | +| `load_layer(source, root, dest, *, overwrite=True, context=None)` | Copies one template/extension layer into `dest`. | +| `merge_layers(layers, dest, *, context=None)` | Applies layers in order (template, addons, extend). Later layers win. | +| `merge_pyproject_text(base_text, overlay_text)` | Deep-merges two `pyproject.toml` documents as TOML. | +| `check_python_version(required, package_name)` | Compares `sys.version_info` against a PEP 440 specifier. Exits with code 1 if too old. | +| `check_for_latest_version(package_name)` | Async. Fetches the latest version from PyPI. Returns `None` on failure. | +| `print_env_info()` | Prints OS, Python, uv, and git info to stdout, then exits. | + +### Constants + +| Name | Description | +| ---- | ----------- | +| `__version__` | Installed package version string. | +| `CPA_USER_AGENT` | HTTP User-Agent sent to PyPI (`create-python-app-core/`). | +| `NON_EMPTY_DIR_ERROR_CODE` | Stable code for `NonEmptyTargetDirectoryError` (`CPA_NON_EMPTY_TARGET_DIR`). | + +### Types + +| Type | Shape | +| ---- | ----- | +| `ResolvedSource` | `kind` (github \| file \| slug \| git), `url`, `ref`, `subdir`, `local_path` | +| `CacheMeta` | `url`, `ref`, `fetched_at`, `commit` | +| `CpaConfig` | `name`, `custom_options`, `raw` | +| `CpaCustomOption` | `key`, `type`, `message`, `default` | +| `CpaError` | Base exception with `.code` attribute | +| `ConfigParseError` | Invalid `cpa.config.json` (code: `CPA_CONFIG_PARSE`) | +| `ManifestLoadError` | Missing template directory (code: `CPA_MANIFEST_LOAD`) | +| `PackageManagerFallbackError` | Package manager fallback failure (code: `CPA_PM_FALLBACK`) | +| `ScaffoldAbortedError` | Scaffold failed mid-run (code: `CPA_ABORTED`) | +| `NonEmptyTargetDirectoryError` | Target directory not empty (code: `CPA_NON_EMPTY_TARGET_DIR`) | + +### `create_python_app` options dict + +| Key | Type | Default | Description | +| --- | ---- | ------- | ----------- | +| `template` | `str` | `""` | Primary template specifier (URL, `file://`, or slug). | +| `addons` | `list[str]` | `[]` | Additional template layers applied after the base template. | +| `extend` | `list[str]` | `[]` | Extension layers applied last (later wins on conflicts). | +| `force` | `bool` | `False` | Allow scaffolding into a non-empty directory. | +| `install` | `bool` | `True` | Run `uv sync` when `pyproject.toml` is present. | +| `offline` | `bool` | `False` | Use cached repos only; raise on cache miss. | +| `refresh` | `str` | env / `"stale"` | Cache refresh mode: `always`, `stale`, or `manual`. | +| `keep_on_failure` | `bool` | `False` | Keep the partial project directory when scaffolding fails. | +| `cache_dir` | `str \| Path` | `None` | Override the default cache root. | +| `set` | `dict` | `{}` | Jinja context overrides (merged into `projectName` and custom option defaults). | + +--- + +## Environment Variables + +All `CPA_*` variables read by the core engine: + +| Variable | Default | Description | +| -------- | ------- | ----------- | +| `CPA_CACHE_DIR` | `~/.cache/cpa` | Root directory for cloned repository cache entries. | +| `CPA_REFRESH` | `stale` | Default cache refresh mode: `always`, `stale`, or `manual`. | +| `CPA_REFRESH_AFTER_HOURS` | `24` | Hours before a `stale` cache entry is refreshed. | +| `CPA_SKIP_GIT` | unset | Set to `1` to skip `git init` and block all git subprocess calls. | +| `CPA_STRICT_REPRO` | unset | Set to `1` to require a full 40-character commit SHA in `?ref=` query params. | + +--- + +## Error Codes + +Stable machine-readable codes on `CpaError.code`: + +| Code | Exception class | When raised | +| ---- | --------------- | ----------- | +| `CPA_ERROR` | `CpaError` | Generic base error (default). | +| `CPA_CONFIG_PARSE` | `ConfigParseError` | Malformed or invalid `cpa.config.json`. | +| `CPA_MANIFEST_LOAD` | `ManifestLoadError` | Template directory not found on disk. | +| `CPA_PM_FALLBACK` | `PackageManagerFallbackError` | Package manager fallback failure. | +| `CPA_ABORTED` | `ScaffoldAbortedError` | Scaffold failed (template render, unexpected error, etc.). | +| `CPA_NON_EMPTY_TARGET_DIR` | `NonEmptyTargetDirectoryError` | Target directory exists and is not empty. | +| `CPA_GIT` | `CpaError` | Git subprocess failed or `git` not found. | +| `CPA_SKIP_GIT` | `CpaError` | Git operation attempted while `CPA_SKIP_GIT=1`. | +| `CPA_FILE` | `CpaError` | `file://` source path does not exist. | +| `CPA_OFFLINE` | `CpaError` | Offline mode with no cached copy of the repository. | +| `CPA_STRICT_REPRO` | `CpaError` | `?ref=` is not a full SHA while `CPA_STRICT_REPRO=1`. | + +--- + +## How It Works + +```text +create_python_app() + |-- transform_options() (optional) + |-- scaffold_project() + |-- assert_directory_is_empty() + |-- resolve_source() for each template / addon / extend + |-- download_repository() (git clone or file://) + |-- load_cpa_config() from cpa.config.json + |-- build_scaffold_context() (projectName + custom options + --set) + |-- merge_layers() (Jinja .template, .append, pyproject merge) + |-- uv sync (when install=True and pyproject.toml exists) + |-- git init (unless CPA_SKIP_GIT=1) + +-- cleanup partial directory on failure (unless keep_on_failure) +``` + +--- + +## Architecture + +The package is organized into these modules: + +| Module | Responsibility | +| ------ | -------------- | +| `__init__.py` | Barrel export and public API surface | +| `api.py` | `create_python_app`, version checks, env info, PyPI lookup | +| `installer.py` | `scaffold_project` orchestration, `uv sync`, git init | +| `loaders.py` | File discovery, `.template` / `.append` processing, layer merge | +| `pyproject_merge.py` | Deep-merge `pyproject.toml` across template layers | +| `paths.py` | URL resolution (GitHub, `file://`, slugs, `?ref=`, `?subdir=`) | +| `git_cache.py` | Clone/pull with cache, refresh modes, offline support | +| `config.py` | Reads optional `cpa.config.json` for custom CLI prompts | +| `errors.py` | Typed `CpaError` hierarchy with stable codes | + +--- + +## Related + +- [`create-awesome-python-app`](https://pypi.org/project/create-awesome-python-app/) -- Interactive CLI built on this core +- [Create Python App](https://github.com/Create-Python-App/create-python-app) -- Monorepo +- [Templates catalog](https://github.com/Create-Python-App/cpa-templates) + +--- + +## License + +MIT (c) [Create Python App Contributors](https://github.com/Create-Python-App/create-python-app/graphs/contributors)