Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.sh text eol=lf
*.cast text eol=lf
*.svg text eol=lf
125 changes: 78 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,42 @@
# microcodegen.py

**PRD text → production FastAPI app → ZIP bytes. One Python file, zero dependencies.**
**PRD text → a running Flask app → ZIP bytes. One Python file, zero dependencies.**

Inspired by Andrej Karpathy's [micrograd](https://github.com/karpathy/micrograd) — this is the core Archiet algorithm in its simplest form.

[![microcodegen demo — PRD to a running Flask app](demo.svg)](https://archiet.com)

> Every line of output above is from a real run. Reproduce it yourself in one command: [`./demo.sh`](demo.sh).

```bash
python microcodegen.py your-prd.md --out ./myapp
cd myapp && pip install -r requirements.txt
alembic upgrade head
uvicorn main:app --reload
python microcodegen.py examples/task_manager.md --out ./my-task-app
cd my-task-app && cp .env.example .env
docker compose up # Flask + Postgres, healthcheck-gated
curl localhost:5000/api/health
```

→ A **working, bootable FastAPI app** at `http://localhost:8000/docs`.
→ A **working, bootable Flask app** with JWT-cookie auth and per-tenant CRUD at `http://localhost:5000`.

---

## What it generates from your PRD

Given a plain-English Product Requirements Document, `microcodegen.py` outputs a complete FastAPI application:
Given a plain-English Product Requirements Document, `microcodegen.py` outputs a complete Flask application (25 files for the example PRD):

- **FastAPI** with `/docs` interactive OpenAPI explorer — free, auto-generated by FastAPI
- **SQLAlchemy 2.0 models** — one per entity extracted from your PRD (`DeclarativeBase`)
- **Pydantic v2 schemas** — `Base` / `Create` / `Update` / `Response` classes per entity
- **JWT auth** — `/api/auth/register`, `/api/auth/login`, `/api/auth/me` with httpOnly cookies; never localStorage
- **Full CRUD APIRouters** — list, create, get, update, delete per entity; all `Depends(get_current_user)`
- **Per-tenant data isolation** — every row has a `user_id` FK; every query filters by it; no cross-user leaks
- **Alembic migrations** — `alembic.ini` + `alembic/env.py` pre-configured; run `alembic upgrade head`
- **pytest test suite** — `TestClient` with `dependency_overrides`, auto-skips if Postgres unreachable
- **docker-compose.yml** — Postgres 16 with healthcheck-gated app startup
- **ARCHITECTURE.md** — ArchiMate 3.2 element map typed from the genome IR
- **openapi.yaml** — machine-readable API contract; import into Postman or Swagger UI
- **Flask app factory** (`app/__init__.py` → `create_app`) with a `wsgi.py`/gunicorn entrypoint — boots as-is
- **Flask-SQLAlchemy models** — one per entity extracted from your PRD, each with a `user_id` FK and `to_dict()`
- **JWT-cookie auth** — `/api/auth/register`, `/login`, `/logout`, `/me` via flask-jwt-extended; tokens live in **httpOnly cookies**, never localStorage
- **Full CRUD blueprints** — list, create, get, update, delete per entity; every route is `@jwt_required()`
- **Per-tenant data isolation** — every row has a `user_id`; every query is `filter_by(user_id=get_jwt_identity())`; no cross-user leaks. Writes go through a writable-field allowlist so a client can't spoof `user_id`
- **JSON error handlers** (400/401/404/405/500) so the API never returns HTML
- **CORS scoped to `FRONTEND_URL`** (not wildcard), with credentials support
- **A boot-time secret check** — `config.py` refuses to start if `SECRET_KEY`/`JWT_SECRET_KEY` are missing or still a `change-me` placeholder
- **docker-compose.yml** — Postgres 16 with a healthcheck-gated app start
- **A click-through demo page** (`app/static/index.html`) served at `/` — register/login/CRUD in the browser, no frontend to write
- **pytest suite** — Flask test client smoke tests
- **GENOME.json** — the architectural IR the app was rendered from

Zero LLM calls. Zero API keys. Pure Python stdlib.
Schema is created with `db.create_all()` on first boot — this minimal file ships no migrations (the full platform adds Alembic). Zero LLM calls. Zero API keys. Pure Python stdlib.

---

Expand All @@ -44,11 +49,32 @@ cd microcodegen

# Generate from an example PRD
python microcodegen.py examples/task_manager.md --out ./my-task-app

# Boot it (needs Docker for the bundled Postgres)
cd my-task-app
pip install -r requirements.txt
alembic upgrade head
uvicorn main:app --reload
# → http://localhost:8000/docs
cp .env.example .env
docker compose up
# → http://localhost:5000 (and the API at /api/health)
```

End-to-end in three curls (register → create → list):

```bash
curl -c cookies.txt -X POST localhost:5000/api/auth/register \
-H 'Content-Type: application/json' \
-d '{"email":"you@example.com","password":"hunter22hunter"}'

curl -b cookies.txt -X POST localhost:5000/api/projects/ \
-H 'Content-Type: application/json' \
-d '{"name":"My first project"}'

curl -b cookies.txt localhost:5000/api/projects/
```

Or just run the whole thing — generate, boot, and walk the auth+CRUD flow:

```bash
./demo.sh

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Make demo.sh executable before telling users to run it

The README now advertises ./demo.sh as the one-command reproduction path, but git ls-tree cfc121ac390669395a9cddd62c39be48af6ab6e7 demo.sh shows the script is committed with mode 100644, so a fresh clone will fail with Permission denied when users run this exact command. Either commit the executable bit (100755) or document bash demo.sh instead.

Useful? React with 👍 / 👎.

```

Or pipe the ZIP:
Expand Down Expand Up @@ -99,14 +125,14 @@ PRD text (your requirements document)
│ No LLM. Misses subtle PRDs; that's acceptable for a spec reference.
▼ Stage 2: manifest_to_genome(manifest) → genome
│ Converts the manifest into a stack-neutral architectural genome dict.
Adds ArchiMate 3.2 element typing (ApplicationComponent, DataObject,
BusinessProcess, ApplicationService) for each extracted element.
│ Converts the manifest into a stack-neutral architectural genome dict
the intermediate representation that drives rendering. One module per
entity, plus inferred integrations.
▼ Stage 3: render_genome(genome) → {path: content}
│ string.Template substitution over embedded FastAPI templates.
│ Outputs SQLAlchemy 2.0 models, Pydantic v2 schemas, APIRouters,
Alembic env, pytest suite, ARCHITECTURE.md, openapi.yaml.
│ string.Template substitution over embedded Flask templates.
│ Outputs the app factory, Flask-SQLAlchemy models, JWT-cookie auth,
CRUD blueprints, config, docker-compose, tests, and a demo page.
▼ Stage 4: pack(files) → ZIP bytes
stdlib zipfile.ZipFile. Download it, push it to GitHub, deploy it.
Expand All @@ -129,14 +155,16 @@ The same philosophy as [micrograd](https://github.com/karpathy/micrograd) and [m

## What this file does NOT include

This is the minimum viable PRD→code pipeline. Production use cases need more:
This is the minimum viable PRD→code pipeline: one stack (Flask), regex extraction, no quality gate. Production use cases need more:

| Feature | Where it lives |
|---|---|
| LLM-powered PRD extraction (handles natural language) | [archiet.com](https://archiet.com) |
| **9 backend stacks**: NestJS, Django, Flask, Go (chi), Java Spring Boot, .NET, Laravel, Rails | [archiet.com](https://archiet.com) |
| **9 backend stacks**: FastAPI, NestJS, Django, Go (chi), Java Spring Boot, .NET, Laravel, Rails | [archiet.com](https://archiet.com) |
| React/Next.js frontend (shadcn/ui, auth pages, onboarding) | [archiet.com](https://archiet.com) |
| Expo mobile app (iOS + Android, push notifications) | [archiet.com](https://archiet.com) |
| Alembic migrations instead of `db.create_all` | [archiet.com](https://archiet.com) |
| ArchiMate 3.2 element map + ADR / TOGAF architecture docs | [archiet.com](https://archiet.com) |
| Compliance artifact packs — SOC 2, HIPAA, GDPR, PCI-DSS control matrices | [archiet.com](https://archiet.com) |
| 13-gate shippability audit (security scan, import coherence, boot test) | [archiet.com](https://archiet.com) |
| GitHub push + drift detection + architecture scoring | [archiet.com](https://archiet.com) |
Expand All @@ -161,32 +189,35 @@ The full Archiet pipeline replaces this with a chunked LLM extractor (overlap +

### Stage 2 — `manifest_to_genome(manifest) → genome`

Converts the manifest into a formal **architectural genome** — the stack-neutral intermediate representation that drives all downstream rendering.
Converts the manifest into a **genome** — the stack-neutral intermediate representation that drives all downstream rendering.

The genome encodes:
- `language` — `fastapi` (this file's scope; the full system supports 12+ stacks)
- `modules[]` — one module per entity, with entities, user_stories, acceptance_criteria
- `archimate_elements[]` — every extracted element typed to ArchiMate 3.2 (ApplicationComponent for the app itself, DataObject per entity, BusinessProcess for workflow user stories, ApplicationService per integration)
- `language` — `flask` (this file's scope; the full system supports 9+ stacks)
- `modules[]` — one module per entity, with its fields and user stories
- `integrations[]` — inferred from vendor mentions (Stripe, Auth0, SendGrid, etc.)

The full platform additionally types every element to ArchiMate 3.2 and threads it through governance and compliance — out of scope for this single file.

### Stage 3 — `render_genome(genome) → {path: content}`

`string.Template` substitution across templates embedded directly in the file. Each template is a complete source file with `$variable` placeholders.

Templates emitted for every generated app:
Files emitted for every generated app:

- `main.py` — FastAPI entry point with `include_router` wiring (no `create_all` — Alembic owns the schema)
- `app/database.py` — SQLAlchemy 2.0 `DeclarativeBase` + `get_db` dependency
- `app/auth.py` — JWT via PyJWT + passlib/bcrypt, httpOnly cookie, `get_current_user` dependency
- `app/models/user.py` — User model
- `alembic.ini` + `alembic/env.py` — migration environment with model auto-discovery
- `ARCHITECTURE.md` — ArchiMate 3.2 element table
- `openapi.yaml` — full OpenAPI 3.1 spec
- `wsgi.py` — gunicorn entrypoint (`from app import create_app`)
- `app/__init__.py` — the Flask app factory: blueprint wiring, JWTManager, CORS, JSON error handlers, `db.create_all()` on boot
- `app/database.py` — the Flask-SQLAlchemy `db` instance
- `app/blueprints/auth_bp.py` — register / login / logout / me, JWT in httpOnly cookies
- `app/models/user.py` — User model with password hashing
- `config.py` — env-driven config that refuses to boot on placeholder secrets
- `docker-compose.yml` + `Dockerfile` — Postgres 16 + gunicorn, healthcheck-gated
- `app/static/index.html` — a single-page register/login/CRUD demo
- `tests/` — pytest + Flask test client
- `.env.example`, `requirements.txt`, `README.md`, `GENOME.json`

Per entity:
- `app/models/<entity>.py` — SQLAlchemy 2.0 model with `user_id` FK
- `app/schemas/<entity>.py` — Pydantic v2 `Base` / `Create` / `Update` / `Response`
- `app/routers/<entity>.py` — FastAPI `APIRouter` with full CRUD
- `app/models/<entity>.py` — Flask-SQLAlchemy model with a `user_id` FK and `to_dict()`
- `app/blueprints/<entity>_bp.py` — full CRUD blueprint, all routes `@jwt_required()`, per-tenant scoped

### Stage 4 — `pack(files) → bytes`

Expand Down Expand Up @@ -218,4 +249,4 @@ If the former, open a PR. If the latter, it belongs in the full Archiet pipeline

MIT. Use it, fork it, learn from it.

The production platform (12+ stacks, compliance packs, quality gates, GitHub push) is commercial: **[archiet.com](https://archiet.com)**
The production platform (9+ stacks, compliance packs, quality gates, GitHub push) is commercial: **[archiet.com](https://archiet.com)**
Loading
Loading