create-frenzy-backend
v0.1.1
Published
A production-ready, reusable hackathon backend template built with modern TypeScript and best practices. Perfect for student projects, MVPs, and rapid prototyping.
Downloads
225
Readme
Frenzy Backend
A production-ready, reusable hackathon backend template built with modern TypeScript and best practices. Perfect for student projects, MVPs, and rapid prototyping.
Tech Stack
- Runtime: Node.js (>=20)
- Language: TypeScript
- Framework: Express.js
- Database: PostgreSQL
- ORM: Prisma v7
- Validation: Zod
- Authentication: JWT + bcrypt
- Environment: dotenv
- Rate Limiting: express-rate-limit
Features
- Complete authentication system (register/login)
- JWT-based authorization
- Password hashing with bcrypt (10 rounds)
- Request validation using Zod
- Global error handling
- Rate limiting on auth routes
- Graceful shutdown handling
- Prisma singleton pattern with connection pooling
- Health check endpoints
- TypeScript strict mode
- Modular architecture
Quick Start
Prerequisites
- Node.js 20 or higher
- PostgreSQL database
- npm or yarn
Installation
Clone and install dependencies
npm installSet up environment variables
cp .env.example .envEdit
.envwith your configuration:DATABASE_URL: Your PostgreSQL connection stringJWT_SECRET: A secure random string for JWT signingPORT: Server port (default: 3000)NODE_ENV: development or production
Run database migrations
npm run prisma:migrateGenerate Prisma client
npm run prisma:generateStart the development server
npm run dev
Your server should now be running at http://localhost:3000!
Project Structure
frenzy-backend/
├── src/
│ ├── app.ts # Express app configuration
│ ├── server.ts # Server entry point
│ ├── db/
│ │ └── prisma.ts # Prisma client singleton
│ ├── middleware/
│ │ ├── auth.middleware.ts # JWT authentication
│ │ ├── error.middleware.ts # Global error handler
│ │ └── validate.middleware.ts # Zod validation
│ └── modules/
│ ├── auth/
│ │ ├── auth.types.ts # Zod schemas
│ │ ├── auth.controller.ts # Auth logic
│ │ └── auth.routes.ts # Auth endpoints
│ └── health/
│ └── health.routes.ts # Health checks
├── prisma/
│ ├── schema.prisma # Database schema
│ └── migrations/ # Migration history
├── prisma.config.ts # Prisma v7 configuration
├── .env.example # Environment template
└── package.jsonAvailable Endpoints
Health Check
GET /health- Public health check{ "status": "ok", "uptime": 123.456 }GET /health/protected- Protected endpoint (requires JWT){ "status": "ok", "message": "You are authenticated!", "userId": "user-uuid" }
Authentication
POST /auth/register- Register a new user{ "email": "[email protected]", "password": "securePassword123" }POST /auth/login- Login and receive JWT{ "email": "[email protected]", "password": "securePassword123" }
Both return:
{
"message": "...",
"token": "jwt-token-here",
"user": {
"id": "uuid",
"email": "[email protected]"
}
}Adding New Modules
Follow the modular pattern to add new features:
Create module directory
mkdir -p src/modules/yourModuleAdd types (Zod schemas)
// src/modules/yourModule/yourModule.types.ts import { z } from "zod"; export const yourSchema = z.object({ field: z.string(), }); export type YourType = z.infer<typeof yourSchema>;Create controller
// src/modules/yourModule/yourModule.controller.ts import { Request, Response, NextFunction } from "express"; export const yourHandler = async (req: Request, res: Response, next: NextFunction) => { try { // Your logic here res.json({ success: true }); } catch (error) { next(error); } };Define routes
// src/modules/yourModule/yourModule.routes.ts import { Router } from "express"; import { validate } from "../../middleware/validate.middleware"; import { authenticateToken } from "../../middleware/auth.middleware"; import { yourSchema } from "./yourModule.types"; import { yourHandler } from "./yourModule.controller"; const router = Router(); router.post("/", authenticateToken, validate(yourSchema), yourHandler); export default router;Register in app.ts
import yourModuleRoutes from "./modules/yourModule/yourModule.routes"; app.use("/your-endpoint", yourModuleRoutes);
Protecting Routes
Use the authenticateToken middleware to protect routes:
import { authenticateToken } from "../../middleware/auth.middleware";
router.get("/protected", authenticateToken, (req, res) => {
// req.userId is available here
res.json({ userId: req.userId });
});Validation
Use the validate middleware with Zod schemas:
import { validate } from "../../middleware/validate.middleware";
import { yourSchema } from "./yourModule.types";
router.post("/endpoint", validate(yourSchema), controller);NPM Scripts
npm run dev- Start development server with auto-reloadnpm run build- Compile TypeScript to JavaScriptnpm run prisma:migrate- Run database migrationsnpm run prisma:generate- Generate Prisma client
Prisma Commands
# Create a new migration
npm run prisma:migrate
# Generate Prisma client after schema changes
npm run prisma:generate
# Open Prisma Studio (database GUI)
npx prisma studioEnvironment Variables
| Variable | Description | Example |
|----------|-------------|---------|
| DATABASE_URL | PostgreSQL connection string | postgresql://user:pass@localhost:5432/db |
| JWT_SECRET | Secret key for JWT signing | your-super-secret-key |
| PORT | Server port | 3000 |
| NODE_ENV | Environment mode | development or production |
Security Features
- Password Hashing: bcrypt with 10 salt rounds
- JWT Tokens: 7-day expiration
- Rate Limiting: 100 requests per 15 minutes on auth routes
- Input Validation: All requests validated with Zod
- Error Handling: No stack traces leaked in production
- CORS: Enabled for cross-origin requests
Error Handling
All errors are caught by the global error handler. Use the AppError class for custom errors:
import { AppError } from "../middleware/error.middleware";
throw new AppError("Resource not found", 404);Best Practices
- Always validate inputs with Zod schemas
- Use async/await with try-catch blocks
- Pass errors to next() in controllers
- Keep controllers thin - business logic in services
- One module = one feature (routes, types, controller)
- Update Prisma schema then run migrations
- Protect sensitive routes with
authenticateToken
