Go from blank folder to production-ready project in 30 seconds. Backend-only API, AI/ML app, mobile, full-stack, infra setup — pick what you need and get it wired with auth, database, Docker, CI/CD, hooks, and tests. All optional. All yours.

npx create-projx my-app
No SDK lock-in. No runtime dependency on Projx. Just clean code in your repo that you own forever.
Every new project starts with the same week of plumbing:
docker-compose.yml (again).You ship features two weeks late because the first two weeks were boilerplate.
Ask an LLM to “scaffold a full-stack app” and you get 50 files of plausible-looking code that breaks on first run. Wrong import paths. Outdated package versions. Auth that doesn’t actually authenticate. You end up debugging machine-generated boilerplate, which is worse than writing it yourself.
npx create-projx my-app # interactive — pick exactly what you need
cd my-app
./scripts/setup.sh # installs everything you picked
Pick any combination of components — they’re all optional:
# AI/ML backend only
npx create-projx vision-api --components fastapi -y
# Node API + React frontend
npx create-projx saas --components fastify,vitejs -y
# Minimal Express API + React frontend
npx create-projx api-app --components express,vitejs -y
# Go API + React frontend
npx create-projx my-app --components go,frontend -y
# Drizzle-backed Node API + React frontend
npx create-projx ledger --components express,vitejs --orm drizzle -y
# Mobile app with backend
npx create-projx field-app --components fastapi,mobile -y
# Full-stack with infra and E2E
npx create-projx prod-app --components fastify,vitejs,e2e,infra -y
# Just the infra
npx create-projx platform --components infra -y
30 seconds. No matter what you pick, you get auth, Docker, CI/CD, hooks, and tests wired up for it.
If this saves you even one hour, it’s already paid for itself. (It’s free.)
gen entity writes integration tests alongside every model — 11 tests per entity, against a real database. You start green, not scrambling.projx update does a 3-tier merge — your custom controllers, pages, and config survive template upgrades. No rewrites..projx config and it’s just a normal repo.projx init adds CI, hooks, and Docker without touching your code.| Component | Stack | What it gives you |
|---|---|---|
fastapi |
Python, SQLAlchemy, Alembic | Auto-entity CRUD, JWT auth, migrations, OpenAPI docs |
fastify |
Node.js, Prisma / Drizzle / Sequelize / TypeORM, TypeBox | Auto-entity CRUD, JWT auth, typed schemas, OpenAPI docs |
express |
Express 5, TypeScript, Prisma / Drizzle / Sequelize / TypeORM | Auto-entity CRUD, JWT auth, validation, security middleware, health checks |
go |
Go, Chi, GORM / sqlc / ent | Auto-entity CRUD, request_id error envelope, soft-delete, lifecycle hooks |
rust |
Rust, Axum, SeaORM | Auto-entity CRUD, request_id task-local, tower middleware, panic-recoverer, distroless build |
laravel |
Laravel 11, PHP 8.3+, Eloquent, Sanctum | Auto-entity CRUD, request_id envelope, Pest + larastan gates, FrankenPHP runtime |
vitejs |
React 19, TypeScript, Vite | Auth, theming, design tokens, light/dark mode |
nextjs |
React 19, TypeScript, Next.js App Router | Auth, theming, design tokens, light/dark mode, output: 'standalone' node server |
mobile |
Flutter, Riverpod, GoRouter | Auth, biometric, theming, GoRouter shell |
e2e |
Playwright | Page object model, auth fixtures, accessibility scans |
infra |
Terraform, AWS | EKS, RDS, VPC, ALB, CodePipeline, multi-environment |
admin-panel |
Go, HTMX (Docker), Postgres | Auth-gated table browser over any Postgres, read-only by default, internal-only behind nginx |
Plus, in every project: Docker Compose for dev + prod, GitHub Actions CI per component (path-filtered), pre-commit hooks, secret detection, VS Code settings, and 80% test coverage enforced.
All optional. Pick any combination. frontend is accepted as a deprecated alias for vitejs.
Components are the floor. Features are the opt-in modules that ride on top — same standard, same CI, same skip-list discipline. Today there’s one, and it’s the one everyone rewrites: auth.
# Fastify + Prisma (default ORM)
npx create-projx my-app --components fastify --auth fastify
# Express + Drizzle
npx create-projx my-app --components express --orm drizzle --auth express
# FastAPI + SQLAlchemy
npx create-projx my-app --components fastapi --auth fastapi
# Multiple backends, one flag — comma-separable targets
npx create-projx my-app --components fastify,express --auth fastify,express
# Add auth to an existing project
npx create-projx add vitejs --auth fastify
update re-applies any feature recorded on a component, so template upgrades never strip your auth wiring.
--auth ships/meAUTH_BACKGROUND_JOBS)request_id propagationSixteen endpoints across signup, login, MFA challenge/enroll/disable, recovery-code regen, refresh, logout, change-password, sessions, forgot/reset password, verify/resend email, me. Same surface on every backend — mounted at /auth/* on fastify and express, /api/v1/auth/* on fastapi.
| Backend | Prisma | Drizzle | Sequelize | TypeORM | SQLAlchemy | GORM |
|---|---|---|---|---|---|---|
fastify |
yes | yes | yes | yes | — | — |
express |
yes | yes | yes | yes | — | — |
fastapi |
— | — | — | — | yes | — |
go |
— | — | — | — | — | yes* |
*Go ships only base CRUD/runtime today; --auth=go lands in M3 (issue #50). sqlc / ent / sea-orm are alternate ORMs deferred to M2.
Nine auth combinations today, one external contract — Go joins in M3. ORM-specific bits live under features/auth/ (per-stack, per-ORM subdirectories); the shared surface per stack lives under each stack’s common/ subdirectory. Env vars the feature reads: JWT_SECRET, FRONTEND_URL, AUTH_BACKGROUND_JOBS (all backends); JWT_ALGORITHMS, MFA_ISSUER, AUTH_CLEANUP_INTERVAL_SECONDS (fastapi).
Full feature-template spec — manifests, patches, anchors, idempotency — in docs/feature-templates.md.
Projx is a shared operating system for teams that ship with both:
If you’re an AI agent reading this, see SKILL.md for trigger conditions, decision rules, and the canonical invocation.
# Interactive — pick your stack
npx create-projx my-app
# Non-interactive — specify components
npx create-projx my-app --components fastify,vitejs,e2e
# Go backend + React frontend
npx create-projx my-app --components go,frontend
# Use Drizzle for Node backends instead of Prisma
npx create-projx my-app --components express,vitejs --orm drizzle
# Accept defaults (Fastify + Frontend + E2E)
npx create-projx my-app -y
Projx supports npm, pnpm, yarn, and bun. During create, you’re prompted to pick one. The choice is stored in .projx and used everywhere — scripts/setup.sh, Docker, CI, pre-commit hooks, and README.
{ "packageManager": "pnpm" }
For init, the package manager is auto-detected from lockfiles (pnpm-lock.yaml → pnpm, yarn.lock → yarn, bun.lockb → bun). Falls back to a prompt if no lockfile is found.
npx create-projx my-app
Interactive prompt lets you pick components. Or specify them directly:
npx create-projx my-app --components fastapi,fastify,go,vitejs,mobile,e2e,infra
Already have a project? Initialize projx to get the scaffolding (CI, hooks, docker-compose) without overwriting your code:
cd my-existing-app
npx create-projx init
Auto-detects components by scanning for fastapi in pyproject.toml, react/fastify in package.json, flutter in pubspec.yaml, and .tf files. Confirms each mapping, creates a projx/baseline branch with the template, and merges it — preserving all your existing code while establishing the ancestry link that makes future updates work.
cd my-app
npx create-projx add vitejs mobile
Copies the new component directories, regenerates shared files (docker-compose, CI, pre-commit hooks) to include them, and installs dependencies.
Need a second backend service alongside an existing one (e.g. an SMTP listener next to your CRUD API)? Use --name <dir>:
npx create-projx add fastify --name email-ingestor
Creates email-ingestor/ with the fastify scaffold and a .projx-component marker. Each instance gets its own job in .github/workflows/ci.yml, its own section in .githooks/pre-commit, and its own install step in scripts/setup.sh. update keeps every instance refreshed on every run.
When templates improve, update your project:
cd my-app
npx create-projx@latest update
Updates use a 3-tier merge strategy:
git merge-file. Your additions (extra deps, env vars, custom config) are preserved alongside template updates. Clean merges are auto-staged; only true conflicts need review.Your custom files (controllers, pages, middleware) are never deleted. Files you created that don’t exist in the template are always preserved.
Common user-owned files are default-skipped automatically — template updates won’t touch them:
| Scope | Default skips |
|---|---|
Root (.projx) |
docker-compose.yml, README.md, .githooks/pre-commit, .github/workflows/ci.yml, scripts/setup.sh, scripts/setup-docker.sh, scripts/setup-ssl.sh |
| fastapi | pyproject.toml |
| fastify / vitejs / nextjs / e2e | package.json |
| mobile | pubspec.yaml |
Defaults are applied once on first update and saved to the skip array. To skip additional files, add them to skip in .projx (root-level) or .projx-component (per-component):
// .projx — root skip
{
"version": "x.y.z",
"skip": ["docker-compose.yml", "README.md", "my-custom-config.yml"]
}
// fastapi/.projx-component — component skip
{
"component": "fastapi",
"origin": "init",
"skip": ["pyproject.toml", "src/custom_middleware.py"]
}
To opt back in to updates for a skipped file, use npx create-projx unpin <file>.
npx create-projx <name> [options]
npx create-projx init
npx create-projx add <components...>
npx create-projx add <type> --name <dir>
npx create-projx update
npx create-projx diff
npx create-projx pin <patterns...>
npx create-projx unpin <patterns...>
npx create-projx pin --list
npx create-projx doctor [--fix]
npx create-projx gen entity <name> [--ai | --backend]
--components <list> Comma-separated: fastapi,fastify,express,go,rust,laravel,vitejs,nextjs,mobile,e2e,infra
--name <dir> Custom directory for `add <type>` (multi-instance)
--ai Target fastapi (AI/ML) for gen entity
--backend Target fastify (API backend) for gen entity
--no-git Skip git init
--no-install Skip dependency installation
-y, --yes Accept defaults (fastify + vitejs + e2e)
-h, --help Show help
See what update would change before applying:
cd my-app
npx create-projx diff
Shows file-by-file analysis: clean updates, files needing merge, user-only changes, and skipped files.
Skip files from future template updates without editing JSON:
npx create-projx pin backend/pyproject.toml # skip this file
npx create-projx pin "backend/src/**" # skip with glob
npx create-projx unpin backend/pyproject.toml # allow updates again
npx create-projx pin --list # show all pinned files
Files inside a component directory are added to that component’s .projx-component skip list. Root-level files are added to .projx skip.
Diagnose issues with your projx setup:
npx create-projx doctor # check everything
npx create-projx doctor --fix # auto-fix what's possible
Checks: config validity, component markers, baseline ref, stale worktrees, skip pattern coverage.
Scaffold a new entity in your primary backend + typed models for frontend/mobile:
npx create-projx gen entity invoice # interactive
npx create-projx gen entity invoice --fields "name:string,amount:number" # non-interactive
npx create-projx gen entity embedding --ai --fields "name:string,vector:json" # target AI backend
npx create-projx gen entity invite --fields "email:string,code:string:unique:generated" # server-fills `code`
Field modifiers (Fastify/Express only, after the type): unique adds a Prisma @unique constraint; generated (alias: server, server-generated) marks the field as server-populated — it’s omitted from the create-schema and a beforeCreate hook stub is emitted that fills it before persist (override the body of generateXxx() with your slug/code/UUID logic). Use both together for server-issued unique identifiers (invite codes, slugs, short URLs).
When both fastapi and fastify exist, the entity generates in the primary backend only (not both). First run prompts you to choose and saves to .projx:
{ "primaryBackend": "fastify" }
Override with --ai (fastapi) or --backend (fastify).
| Component | Generated |
|---|---|
| Primary backend (fastapi) | src/entities/<name>/_model.py + tests/test_<name>_entity.py — model + 11 CRUD/auth tests |
| Primary backend (fastify) | src/modules/<name>/schemas.ts + index.ts + Prisma model + tests/modules/<name>.test.ts |
vitejs |
src/types/<name>.ts — TypeScript interface + Create/Update variants |
nextjs |
src/types/<name>.ts — TypeScript interface + Create/Update variants |
Tests included: every gen entity writes a working integration test file alongside the model — 11 tests for FastAPI (extending BaseEntityApiTest), 11 tests for Fastify (via describeCrudEntity). Both run against a real database (Postgres). New entities ship green from day one — no scrambling to bolt on tests at go-live.
No migrations — run alembic revision --autogenerate or prisma migrate dev (via your package manager) when ready.
Pick an ORM at create-time with --orm <provider>. Default: prisma. Supported: prisma, drizzle, sequelize, typeorm.
| ORM | Schema home | gen entity produces |
Sync schema to DB |
|---|---|---|---|
prisma |
prisma/schema.prisma |
Prisma model + Fastify/Express module (schemas.ts, index.ts) + integration test |
prisma migrate dev |
drizzle |
src/db/schema.ts |
Typed pgTable + Fastify/Express router wired via _base/ + CRUD test |
drizzle-kit push --force |
sequelize |
src/models/<name>.ts |
Sequelize Model class + aggregator entry + Fastify/Express router + CRUD test |
pnpm db:sync (uses sequelize.sync) |
typeorm |
src/entities/<name>.ts |
Decorated @Entity class + aggregator entry + Fastify/Express router + CRUD test |
pnpm db:sync (uses dataSource.synchronize) |
All four ORMs scaffold equivalent runtime behavior: _base/auto-routes.ts wires POST/GET/PATCH/DELETE/bulk routes with pagination, equality filters, ILIKE search, and the lifecycle hook contract (beforeCreate, afterCreate, beforeUpdate, afterUpdate, beforeDelete).
ORM-specific scaffolding lives in cli/src/addons/orms/ — each ORM is a self-contained folder with a manifest.json (deps, file removals, scripts), shared/ files, per-framework overlays, and gen-entity/ templates. Adding a new ORM means adding a new folder there; no CLI core changes.
Rename fastapi/ to backend/? Just rename the folder — the .projx-component marker file moves with it. The update command auto-discovers where each component lives by scanning for these markers. No config changes needed.
backend/.projx-component → { "components": ["fastapi"] }
web/.projx-component → { "components": ["vitejs"] }
CI, scripts/setup.sh, pre-commit hooks, and docker-compose are all regenerated with your custom directory names.
my-app/
├── fastapi/ # Auto-entity CRUD backend
│ └── .projx-component # Identifies this as the fastapi component
├── vitejs/ # React + Vite shell
│ └── .projx-component
├── e2e/ # Playwright E2E tests
│ └── .projx-component
├── docker-compose.yml # Production (backend + frontend + SSL)
├── .github/workflows/ # CI per component (runs only on changes)
├── .githooks/pre-commit # Format + lint on commit
├── .vscode/ # Editor settings + recommended extensions
├── scripts/ # setup.sh, setup-docker.sh, setup-ssl.sh
└── .projx # Components list + version
Only the components you selected appear. Shared files (docker-compose, CI, hooks) are generated to match your selection.
The core idea: define a data model, get everything else for free.
Backend — Drop a model file. The registry auto-discovers it and generates CRUD routes, schemas, pagination, filtering, sorting, search, FK expansion, and OpenAPI docs.
Field privacy — Sensitive columns (password_hash, secret, api_key, mfa_secret, etc.) are automatically stripped from API responses via a built-in baseline. Add project-specific hidden fields per entity (__hidden_fields__ in FastAPI, hiddenFields in Fastify). Mark entire entities as __private__ / private: true to hide them from the API entirely — no routes registered.
Frontend — Ships a React shell with auth, theming, and design tokens. Build your own pages using the generated types from gen entity.
Mobile — Ships a Flutter shell with auth, biometric, and GoRouter scaffolding. Build screens using the generated Dart models from gen entity.
Both backends ship with a service_configs table for storing third-party credentials (SMTP, OAuth, S3, etc.) encrypted at rest with AES-256-GCM. The purpose column is a free-form string — pick whatever taxonomy fits your project.
// Fastify
import { setServiceConfig, getServiceConfig } from "./lib/service-config.js";
await setServiceConfig(prisma, "smtp", { host, port, user, password });
const cfg = await getServiceConfig<{ host: string }>(prisma, "smtp");
# FastAPI
from src.entities.service_config._repository import ServiceConfigRepository
repo = ServiceConfigRepository(session)
await repo.set_config('smtp', {'host': ..., 'port': 587})
cfg = await repo.get_config('smtp')
Encryption key resolves from CRED_ENCRYPTION_KEY (32-byte base64). If absent, derived from JWT_SECRET for development. Set an explicit key in production. Reads are cached in-memory for 10 minutes; invalidate(purpose) clears.
The Fastify backend ships with @fastify/rate-limit registered globally. Defaults: 200 requests per minute per user (or per IP for unauthenticated requests). Tune via RATE_LIMIT_MAX and RATE_LIMIT_WINDOW in .env.
Override per route for sensitive endpoints:
fastify.post(
"/auth/resend-verification",
{
config: {
rateLimit: {
max: 5,
timeWindow: "1 hour",
keyGenerator: (req) => (req.body?.email ?? req.ip).toLowerCase(),
},
},
},
handler,
);
For the FastAPI service, edge rate limits are enforced by the frontend nginx (auth_limit and api_limit zones in vitejs/nginx.conf) — no application-level limiter is wired by default since the service is internal.
Contributing to Projx itself:
git clone https://github.com/ukanhaupa/projx.git
cd projx
./scripts/setup.sh
The CLI lives in cli/. Templates are the root-level component directories (fastapi/, vitejs/, etc.).
cd cli
pnpm test # run tests
pnpm build # build CLI
You’re still reading. Stop reading. Run this:
npx create-projx my-app
Pick whatever you need from the menu — backend-only, AI app, mobile, full-stack, just infra. 30 seconds. Free. No signup. If you don’t like it, rm -rf my-app and we never speak of this again.
Add this to your project’s README:
[](https://github.com/ukanhaupa/projx)
Projx is free and MIT-licensed. If it saves you time, consider sponsoring its development — it keeps the templates current and the roadmap moving.
MIT