create-projx
v1.7.3
Published
Scaffold production-grade fullstack projects in seconds. FastAPI, Fastify, Express, React, Flutter, Terraform — with auth, database, CI/CD, E2E tests, and Docker. One command, ready to deploy.
Maintainers
Readme
Projx
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-appNo SDK lock-in. No runtime dependency on Projx. Just clean code in your repo that you own forever.
You've done this a hundred times
Every new project starts with the same week of plumbing:
- Wire up auth (again).
- Configure the database and migrations (again).
- Write the Dockerfile and
docker-compose.yml(again). - Set up CI, linting, formatting, pre-commit hooks (again).
- Build the same login + CRUD scaffolding (again).
- Realize at 11pm that something's broken and you don't remember why (again).
You ship features two weeks late because the first two weeks were boilerplate.
Or your AI does it badly
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.
What if you just… didn't?
npx create-projx my-app # interactive — pick exactly what you need
cd my-app
./scripts/setup.sh # installs everything you pickedPick 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,frontend -y
# Minimal Express API + React frontend
npx create-projx api-app --components express,frontend -y
# Drizzle-backed Node API + React frontend
npx create-projx ledger --components express,frontend --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,frontend,e2e,infra -y
# Just the infra
npx create-projx platform --components infra -y30 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.)
Why teams pick Projx and stay
- It actually runs. Every template is tested in CI before release. No "looks right" surprises.
- Tests ship with the code.
gen entitywrites integration tests alongside every model — 11 tests per entity, against a real database. You start green, not scrambling. - Auto-entity pattern. Define a data model, get CRUD routes, validation, OpenAPI docs, and a typed UI for free. Backend, frontend, and mobile all stay in sync.
- Updates don't nuke your code.
projx updatedoes a 3-tier merge — your custom controllers, pages, and config survive template upgrades. No rewrites. - No lock-in. Projx generates files and walks away. Delete the
.projxconfig and it's just a normal repo. - Adopt incrementally. Already have a project?
projx initadds CI, hooks, and Docker without touching your code. - Pick your package manager. npm, pnpm, yarn, or bun. The choice propagates everywhere — scripts, Docker, CI, docs.
- Pick your Node ORM. Prisma is the auto-CRUD default. Drizzle, Sequelize, and TypeORM ship as first-class addons with identical runtime surface (auto-routes, pagination, filtering, search, lifecycle hooks).
- AI-agent friendly. Ships with SKILL.md so Claude, Cursor, and other agents call Projx instead of hand-writing broken scaffolds.
What you get
| 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 |
| frontend | React 19, TypeScript, Vite | Auth, theming, design tokens, light/dark mode |
| 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 |
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.
Built for humans and AI agents
Projx is a shared operating system for teams that ship with both:
- Developers get a readable layout, stable conventions, and safe updates.
- AI agents get a deterministic CLI to call instead of guessing folder structures.
- Teams get consistency across repos, less drift, and fewer surprise refactors.
If you're an AI agent reading this, see SKILL.md for trigger conditions, decision rules, and the canonical invocation.
Quick Start
# Interactive — pick your stack
npx create-projx my-app
# Non-interactive — specify components
npx create-projx my-app --components fastify,frontend,e2e
# Use Drizzle for Node backends instead of Prisma
npx create-projx my-app --components express,frontend --orm drizzle
# Accept defaults (Fastify + Frontend + E2E)
npx create-projx my-app -yPackage Manager Support
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.
Commands
Create a Project
npx create-projx my-appInteractive prompt lets you pick components. Or specify them directly:
npx create-projx my-app --components fastapi,fastify,frontend,mobile,e2e,infraAdopt an Existing Project
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 initAuto-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.
Add Components Later
cd my-app
npx create-projx add frontend mobileCopies the new component directories, regenerates shared files (docker-compose, CI, pre-commit hooks) to include them, and installs dependencies.
Multiple instances of the same type
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-ingestorCreates 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.
Update Scaffolding
When templates improve, update your project:
cd my-app
npx create-projx@latest updateUpdates use a 3-tier merge strategy:
- Git merge — if the template merges cleanly with your code, it's auto-committed. Done.
- 3-way merge — if git merge fails, each file is merged individually using
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. - Direct copy — if no merge baseline exists, template files are written directly. You pick which changes to keep via an interactive prompt, and discarded files are automatically added to your skip list.
Your custom files (controllers, pages, middleware) are never deleted. Files you created that don't exist in the template are always preserved.
Skip Files
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 / frontend / 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>.
Options
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,frontend,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 + frontend + e2e)
-h, --help Show helpPreview Changes
See what update would change before applying:
cd my-app
npx create-projx diffShows file-by-file analysis: clean updates, files needing merge, user-only changes, and skipped files.
Pin / Unpin 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 filesFiles inside a component directory are added to that component's .projx-component skip list. Root-level files are added to .projx skip.
Health Check
Diagnose issues with your projx setup:
npx create-projx doctor # check everything
npx create-projx doctor --fix # auto-fix what's possibleChecks: config validity, component markers, baseline ref, stale worktrees, skip pattern coverage.
Generate Entities
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 |
| frontend | 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.
ORM choice (Node backends)
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 Component Directories
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": ["frontend"] }CI, scripts/setup.sh, pre-commit hooks, and docker-compose are all regenerated with your custom directory names.
What a Scaffolded Project Looks Like
my-app/
├── fastapi/ # Auto-entity CRUD backend
│ └── .projx-component # Identifies this as the fastapi component
├── frontend/ # 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 + versionOnly the components you selected appear. Shared files (docker-compose, CI, hooks) are generated to match your selection.
Auto-Entity Pattern
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.
Encrypted Service Config
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.
Rate Limiting
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 frontend/nginx.conf) — no application-level limiter is wired by default since the service is internal.
Development
Contributing to Projx itself:
git clone https://github.com/ukanhaupa/projx.git
cd projx
./scripts/setup.shThe CLI lives in cli/. Templates are the root-level component directories (fastapi/, frontend/, etc.).
cd cli
pnpm test # run tests
pnpm build # build CLITry it now
You're still reading. Stop reading. Run this:
npx create-projx my-appPick 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.
Badge
Add this to your project's README:
[](https://github.com/ukanhaupa/projx)License
MIT
