Multi-tenant SaaS for team and project management
Getting Started • API • Deploy Checklist
TeamFlow is a multi-tenant app: organizations manage teams, projects, and tasks with row-scoped isolation, roles (Owner / Admin / Member), JWT auth with refresh cookies, and Socket.io updates.
| Layer | Technology |
|---|---|
| Frontend | React 18, TypeScript, Vite, TailwindCSS, shadcn/ui |
| Backend | Node.js 20+, Express 5, TypeScript |
| Database | PostgreSQL 16, Drizzle ORM |
| Real-time | Socket.io |
| Testing | Vitest |
┌─────────────────────────────────────────────────────────────┐
│ Client (React + Vite) │
└────────────────────────┬────────────────────────────────────┘
│ REST + WebSocket (same origin in prod)
┌────────────────────────┴────────────────────────────────────┐
│ Express 5 + Socket.io │
└────────────────────────┬────────────────────────────────────┘
│ Drizzle
┌────────────────────────┴────────────────────────────────────┐
│ PostgreSQL │
└─────────────────────────────────────────────────────────────┘
Prerequisites: Node.js 20+ and PostgreSQL 16 (Docker recommended via docker-compose.yml).
git clone https://github.com/S37F/TeamFlow.git
cd TeamFlow
npm install
cp .env.example .envOne command (Postgres via Docker, schema push, dev server):
npm run localOpen http://localhost:5000. If docker compose up --wait is not available, run:
npm run db:up
npm run db:push
npm run devWithout Docker: install Postgres, set DATABASE_URL in .env, then npm run db:push and npm run dev.
| Command | Description |
|---|---|
npm run local |
Docker Postgres → db:push → dev server |
npm run db:up / npm run db:down |
Start/stop Postgres container |
npm run dev |
Dev server with Vite HMR |
npm run build |
Production build (client + server) |
npm start |
Run production server (dist/) |
npm test |
All tests |
npm run db:push |
Push schema to database |
npm run db:studio |
Drizzle Studio |
Auth uses Bearer access tokens and an httpOnly refresh cookie.
| Method | Endpoint | Description |
|---|---|---|
POST |
/api/auth/register |
Register user + organization |
POST |
/api/auth/login |
Login |
POST |
/api/auth/refresh |
Refresh access token |
POST |
/api/auth/logout |
Logout |
GET |
/api/user |
Current user |
| Method | Endpoint | Description |
|---|---|---|
GET / POST |
/api/projects |
List / create projects |
PATCH / DELETE |
/api/projects/:id |
Update / delete project |
GET / POST |
/api/projects/:projectId/tasks |
List / create tasks |
PATCH / DELETE |
/api/tasks/:id |
Update / delete task |
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/organization |
Organization |
GET |
/api/organization/members |
Members |
POST |
/api/organization/invite |
Invite member |
PATCH / DELETE |
/api/organization/members/:id |
Role / remove |
| Method | Endpoint | Description |
|---|---|---|
GET |
/health |
Liveness |
GET |
/ready |
Readiness (includes DB) |
TeamFlow/
├── client/ # React app
├── config/ # Build/test/db config files
├── server/ # Express + Socket.io
├── shared/ # Drizzle schema + Zod + route types
├── tests/ # Vitest setup
├── script/build.ts # Production bundle script
├── docker-compose.yml
└── .env.example
Set NODE_ENV=production, DATABASE_URL, and strong JWT_* secrets. Build and run:
npm run build
npm startThe server serves the Vite-built client from dist/public and the API on PORT (default 5000). Set ALLOWED_ORIGINS to your public origin(s) if it differs from the defaults.
This project is already structured for this stack (single Node service + PostgreSQL).
- Create a free Neon project and copy the pooled
DATABASE_URL. - Push this repository to GitHub.
- In Render, create a Web Service from the repo.
- Render should auto-detect
render.yaml; otherwise set:- Build command:
npm ci && npm run build - Start command:
npm start
- Build command:
- Add environment variables in Render:
NODE_ENV=productionDATABASE_URL=<your_neon_database_url>JWT_ACCESS_SECRET=<32+ chars>JWT_REFRESH_SECRET=<32+ chars>ALLOWED_ORIGINS=https://<your-service>.onrender.com
- Deploy.
- Run schema sync once against Neon from your machine:
npm run db:push
After deployment:
https://<your-service>.onrender.com/healthhttps://<your-service>.onrender.com/ready
Notes:
- Keep frontend and backend on the same Render service for this codebase.
- Free tier services may sleep and have cold starts.
JWT access + refresh tokens, scrypt passwords, rate limits on auth routes, Helmet, CORS, compression, structured logging, Zod validation, soft deletes.
MIT