create-rexp
v1.0.11
Published
Scaffold a React + Express + Prisma full-stack monorepo
Maintainers
Readme
create-rexp
Scaffold a React + Express + Prisma v7 full-stack monorepo in seconds.
npx create-rexp # npm
bun create rexp # bun
yarn create rexp # yarn
pnpm create rexp # pnpmFeatures
- TypeScript or JavaScript — choose your language at scaffold time
- Node.js or Bun — pick the runtime for the server
- PostgreSQL, MySQL, or SQLite — Prisma v7 with driver adapters, auto-detected at runtime
- npm, yarn, pnpm, or bun — bring your preferred package manager
- Vite + React 19 + Tailwind CSS v4 — modern client with proxy to the API server
- Express 5 + layered architecture — Routes → Controllers → Services → Prisma
- Custom error classes — throw
NotFoundError,BadRequestError, etc.; the error handler catches them - Prisma v7 multi-file schema — models in
prisma/models/, generator output redirected togenerated/ - Generator scripts —
make:controller,make:model,make:service,make:viewscaffold new files instantly - Path aliases —
@/*→./src/*,@db/*→./generated/*(Prisma client)
Quick start
bun create rexpOr with npm:
npx create-rexp@latestOr with yarn / pnpm:
yarn create rexp
pnpm create rexpRun locally after cloning this repo:
bun install
bun run src/index.tsInteractive prompts
| Prompt | Options | | ----------------- | ---------------------------------------------------- | | Project name | any valid npm package name | | Language | TypeScript · JavaScript | | Runtime | Node.js · Bun | | Database | PostgreSQL · MySQL · SQLite | | Package manager | npm · yarn · pnpm · bun | | Init git? | Yes / No | | Install deps? | Yes / No |
Generated project structure
my-app/
├── package.json # workspaces: [client, server]
├── README.md
├── scripts/
│ ├── _utils.mjs # shared helpers (pascalCase, camelCase, ext detection)
│ ├── make-controller.mjs
│ ├── make-model.mjs # generates Prisma model + service file
│ ├── make-service.mjs
│ └── make-view.mjs
├── client/
│ ├── index.html
│ ├── package.json
│ ├── tsconfig.json # or jsconfig.json for JS
│ ├── vite.config.ts # React + Tailwind v4 plugin, @/* alias, /api proxy
│ └── src/
│ ├── main.tsx
│ ├── App.tsx # fetches /api/users and renders a list
│ ├── index.css # @import "tailwindcss"
│ └── components/ # scaffolded by make:view
└── server/
├── .env.example
├── package.json
├── prisma.config.ts # Prisma v7 config (schema dir, migrations, datasource)
├── tsconfig.json # paths: @/* → ./src/*, @db/* → ./generated/*
├── prisma/
│ ├── schema.prisma # datasource + generator (output = ../generated)
│ └── models/
│ ├── user.prisma # example model
│ └── post.prisma # example model with relation
├── generated/ # prisma client output (gitignored, generated by postinstall)
└── src/
├── index.ts # entry point, imports app + env, starts listening
├── app.ts # Express app with middleware chain
├── config/
│ └── env.ts # typed env var accessor
├── controllers/
│ └── user.controller.ts
├── errors/
│ └── index.ts # AppError, BadRequestError, NotFoundError, etc.
├── lib/
│ └── prisma.ts # singleton PrismaClient with driver adapter
├── middlewares/
│ ├── errorHandler.ts
│ ├── logger.ts
│ └── notFound.ts
├── routes/
│ └── index.ts # mounts controllers on /api
└── services/
└── user.service.tsServer architecture
Request → Routes → Controllers → Services → Prisma
↓
AppError subclasses
↓
errorHandler middleware- Controllers parse the request, call a service method, and respond. They never import from
@prisma/client. - Services contain business logic and database queries via Prisma. They throw typed errors like
NotFoundError. - Error classes extend
AppErrorwhich carries astatusCode. TheerrorHandlermiddleware catches them and returns{ message }with the correct status. - Path aliases are configured in
tsconfig.json(@/*,@db/*). For Bun,jsconfig.jsonhandles them. For Node.js (JS template),module-aliasis used with_moduleAliasesinpackage.json.
Middleware chain (in app.ts)
helmet()— security headerscors()— cross-origin requestsmorgan("dev")— request loggingexpress.json()— body parsing/api— routesnotFoundHandler— throwsNotFoundErrorfor unmatched routeserrorHandler— catches all errors and returns JSON
Prisma v7 specifics
- Uses
prisma.config.ts(or.js) withdefineConfig— no moregeneratorblock for the datasource URL - Multi-file schema:
schema.prismadeclares datasource + generator; models live inprisma/models/*.prisma - Generator output:
output = "../generated"so the client is atgenerated/client - Driver adapters are mandatory in v7. The scaffold includes all three (
@prisma/adapter-pg,@prisma/adapter-mariadb,@prisma/adapter-libsql) and detects the correct one at runtime viaDATABASE_URLprefix. postinstallscript runsprisma generateautomatically
Client architecture
- Vite with
@vitejs/plugin-reactand@tailwindcss/vite - Tailwind CSS v4 — no
tailwind.config.js, no PostCSS config. Just@import "tailwindcss"inindex.css. - Path aliases —
@/*→./src/*configured in bothvite.config.tsandtsconfig.json - API proxy —
/apirequests are proxied tohttp://localhost:3000during development - The example
App.tsxfetches from/api/usersand renders a user list
Generator scripts
Run from the monorepo root:
| Command | What it creates |
| -------------------------- | ---------------------------------------------------- |
| bun run make:controller | server/src/controllers/<name>.controller.ts |
| bun run make:service | server/src/services/<name>.service.ts |
| bun run make:model <Name> | server/prisma/models/<name>.prisma + service file |
| bun run make:view <Name> | client/src/components/<name>.tsx |
Scripts auto-detect TypeScript vs JavaScript by checking for server/tsconfig.json. Names are converted automatically (kebab-case files, PascalCase classes, camelCase instances).
Database
The scaffold includes all three Prisma v7 driver adapters in server/package.json:
| Provider | Adapter package | Driver package |
| ------------ | ---------------------- | ----------------- |
| PostgreSQL | @prisma/adapter-pg | pg |
| MySQL | @prisma/adapter-mariadb | mysql2 |
| SQLite | @prisma/adapter-libsql | @libsql/client |
At runtime, lib/prisma.ts imports the correct adapter based on the DATABASE_URL prefix, so you only need one adapter installed and it works for any provider you choose.
Development workflow
After scaffolding:
cd my-app
bun run dev # starts client (Vite) + server (Express) concurrently
bun run build # builds both client and server
bun run start # starts the built server
bun run db:migrate # run Prisma migrations
bun run db:studio # open Prisma Studio
bun run db:generate # regenerate Prisma clientContributing
Contributions are welcome. Before starting work, open an issue to discuss the change or comment on an existing one. Create a branch from main using a feat/* prefix for feature requests or fix/* for bug fixes, then open a pull request once ready. This project uses Bun for development and builds.
Setup
git clone https://github.com/MowlandCodes/rexp-bootstrap.git
cd rexp-bootstrap
bun installCommands
bun run build # build src/index.ts → dist/index.js
bun run src/index.ts # run the CLI interactively during development
bunx tsc --noEmit # type-check (templates excluded from tsconfig)Token system
Templates in templates/ts/ and templates/js/ use __TOKEN__ placeholders replaced by buildTokens() in src/index.ts at scaffold time. Each token maps to a user's prompt choice (e.g. __DATABASE_PROVIDER__, __SERVER_DEV__).
What gets published
Only dist/ and templates/ are published to npm (see files in package.json). Source files in src/ are excluded.
Publishing
Push to main triggers .github/workflows/publish.yml:
oven-sh/setup-bun— installs Bun for the build stepbun install && bun run build— producesdist/index.jsactions/setup-nodewithnode-version: 24— fornpm publishnpm publish --provenance— publishes with OIDC trusted signing
Requires the npm package to be configured for trusted publishing on the main branch.
Code of Conduct
Our pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in this project and its community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
Our standards
Examples of behavior that contributes to creating a positive environment include:
- Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism
- Focusing on what is best for the community
- Showing empathy towards other community members
Examples of unacceptable behavior include:
- The use of sexualized language or imagery and unwelcome sexual attention or advances
- Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment
- Publishing others' private information without explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting
Enforcement
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting the project maintainer. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances.
