skeleton-project
v1.1.1
Published
Scaffold an Express + Prisma + Vite/React + Docker project
Readme
fullstack-starter
A batteries-included starter for full-stack apps. Clone it, strip the example items
module, and ship your own — the wiring, structure, and Docker setup are already done.
Stack: Express + Prisma + PostgreSQL · Vite + React + TanStack Query + Tailwind v4 · Docker Compose
What's inside
Backend (backend/)
- Express app with a sane middleware chain:
helmet,cors, rate-limiting, body parsing, request logging - Prisma ORM with a singleton client (no connection-pool exhaustion on hot reload)
- Env validation — boots fail fast with a clear message if required vars are missing
- DB-aware
/api/health— returns503when Postgres is unreachable, so orchestrators know - Central error handler (maps common Prisma errors to clean HTTP codes)
- Standard response envelope (
{ success, message, data }) + request validation helper - JWT auth middleware ready to guard any route
- Feature-module pattern:
routes → controller → service, one folder each
Frontend (frontend/)
- Vite + React SPA, served by nginx in production (with
/apiproxy) - TanStack Query wired up (sensible retry/stale defaults, never retries auth errors)
- Tailwind v4 (zero-config, via the Vite plugin)
- Axios client + a matching feature-module pattern
Infra
docker-compose.yml— Postgres + backend + frontend, one command to run it all- Multi-stage Dockerfiles (non-root backend, nginx frontend)
scaffold.mjs— spin up a renamed copy for a new project
Quick start
cp .env.example .env # set POSTGRES_PASSWORD, SESSION_SECRET, etc.
docker compose up --build| Service | URL | |----------|--------------------------------| | Frontend | http://localhost:8080 | | Backend | http://localhost:3001/api | | Health | http://localhost:3001/api/health | | Postgres | localhost:5400 |
Local dev (without Docker) — needs a running Postgres:
cd backend && cp .env.example .env && npm i && npm run dev # :3001, --watch reload
cd frontend && cp .env.example .env && npm i && npm run dev # :5173, proxies /api → :3001Project layout
.
├── docker-compose.yml # postgres + backend + frontend
├── scaffold.mjs # create a new project from this template
├── .env.example # copy → .env (used by compose)
│
├── backend/ # Express API
│ ├── server.js # entry: connect db, listen, graceful shutdown
│ ├── prisma/schema.prisma # data model
│ └── src/
│ ├── app.js # middleware chain + routes + /api/health
│ ├── config/ # all env vars read here, nowhere else
│ ├── database/ # prisma client (singleton)
│ ├── middleware/ # errorHandler · validateRequest · auth
│ ├── utils/ # apiResponse · logger · asyncHandler
│ └── modules/
│ └── items/ # example CRUD — copy this shape
│ ├── items.routes.js
│ ├── items.controller.js
│ └── items.service.js
│
└── frontend/ # Vite + React SPA
└── src/
├── api/ # axios client
├── lib/ # queryClient, shared providers
├── modules/items/ # example feature: api calls + React Query hooks
└── utils/ # pure helpersAdding a feature
The whole pattern, end to end:
- Model — add it to
backend/prisma/schema.prisma, thennpm run dev(auto-runsdb push). - Backend — copy
backend/src/modules/items/→modules/<name>/, rename, mount it insrc/app.js. - Frontend — copy
frontend/src/modules/items/, point the API calls at your new routes.
items is intentionally trivial so you can see the shape — delete it once you've copied it.
Reusing this template
This is a template, not a dependency — don't npm install it into a project. Pick one
of these to start a fresh project from it:
1. Scaffold locally (no setup)
Copies the tree into a new folder, writes the name into both package.json files and the
frontend <title>, asks for the backend / frontend / database ports (Enter = default)
and wires them through .env + vite.config.js, creates .env from each .env.example,
and runs npm install in backend/ and frontend/ — ready to run immediately:
node scaffold.mjs my-new-project # prompts for ports, full setup
node scaffold.mjs my-new-project --yes # accept default ports, no prompt
node scaffold.mjs my-new-project --no-install # skip npm installThen start it:
cd my-new-project
docker compose up -d postgres # Postgres on :5400
cd backend && npm run dev # cd frontend && npm run dev in another terminal2. npx (after publishing once)
Published to npm as skeleton-project. From anywhere, no install needed:
npx skeleton-project my-new-project3. GitHub template
Push this repo to GitHub and tick Settings → Template repository. Others then get a "Use this template" button, or can pull it without git history via:
npx degit your-user/your-repo my-new-projectNotes
.envfiles are git-ignored at every level — only the.env.examplefiles are committed. Set real secrets before deploying.- Postgres runs on host port 5400 (configurable via
POSTGRES_PORT) to avoid clashing with a default5432install. - Stays on Prisma 6 for the simple
url = env(...)schema; Prisma 7 needsprisma.config.ts+ a driver adapter.
