A simplified movie seat booking platform built with Express.js, PostgreSQL, and JWT authentication. Built as part of the ChaiCode Web Dev Cohort 2026 Hackathon.
- User Registration & Login β Secure auth with bcrypt password hashing & JWT tokens
- Protected Endpoints β Auth middleware guards booking routes; only logged-in users can book
- Movie Listing β Browse available movies with seat availability counts
- Seat Booking β Interactive seat map with real-time visual feedback
- Duplicate Prevention β Database-level constraints + transactional locking (
SELECT ... FOR UPDATE) prevent double-booking - User-Associated Bookings β Every booking is tied to the authenticated user
- Booking Management β View and cancel your bookings
- Backward Compatible β All original starter code endpoints are preserved and functional
| Layer | Technology |
|---|---|
| Runtime | Node.js |
| Framework | Express.js 5 |
| Database | PostgreSQL 17 |
| Auth | JWT + bcrypt |
| Frontend | HTML + Tailwind CSS |
book-my-ticket/
βββ db/
β βββ init.sql # Database schema & seed data
βββ src/
β βββ config/
β β βββ db.mjs # PostgreSQL connection pool
β βββ middleware/
β β βββ auth.mjs # JWT authentication middleware
β βββ routes/
β βββ auth.mjs # Register, Login, Profile routes
β βββ booking.mjs # Protected booking CRUD routes
β βββ movies.mjs # Movie listing routes
βββ index.mjs # Main Express server (original + new routes)
βββ index.html # Frontend UI
βββ package.json
βββ .env # Environment variables (Add yours)
βββ README.md
- Node.js v18+
git clone https://github.com/your-username/book-my-ticket.git
cd book-my-ticketnpm installCreate a .env file in the root (or use the provided one):
# Port
PORT=8080
# DB
DATABASE_URL=your_postgresql_connection_string
# JWT Config
JWT_SECRET=replace-with-a-strong-secretRecommended production setup:
- App: Versel (Node web service)
- Database: Managed PostgreSQL (Neon DB, Aiven, Supabase, etc.)
- Build command:
npm install - Start command:
npm start - Runtime: Node.js 18+
[Register] POST /api/auth/register β Returns JWT token
β
[Login] POST /api/auth/login β Returns JWT token
β
[Use Token] Authorization: Bearer <token>
β
[Access] Protected routes (bookings) now accessible
- Register with username, email, and password. Password is hashed with bcrypt (10 salt rounds).
- Login with email + password. Server verifies the hash and returns a JWT (24h expiry).
- Protected routes require the
Authorization: Bearer <token>header. The auth middleware verifies the JWT and attaches user info to the request.
| Method | Endpoint | Description |
|---|---|---|
| GET | / |
Serve frontend HTML |
| GET | /seats |
List all seats (original) |
| PUT | /:id/:name |
Book a seat by name (original) |
| POST | /api/auth/register |
Register a new user |
| POST | /api/auth/login |
Login and get JWT token |
| GET | /api/movies |
List all movies with availability |
| GET | /api/movies/:id |
Get movie details with seat map |
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/auth/profile |
Get current user's profile |
| POST | /api/bookings |
Book a seat for a movie |
| GET | /api/bookings |
List current user's bookings |
| DELETE | /api/bookings/:id |
Cancel a booking |
curl -X POST http://localhost:8080/api/auth/register \
-H "Content-Type: application/json" \
-d '{"username": "john", "email": "john@example.com", "password": "pass123"}'curl -X POST http://localhost:8080/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email": "john@example.com", "password": "pass123"}'curl -X POST http://localhost:8080/api/bookings \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-d '{"movieId": 1, "seatNumber": 5}'Duplicate bookings are prevented at two levels:
- Database Level β
UNIQUE(seat_number, movie_id)constraint onmovie_seats - Application Level β Transactional
SELECT ... FOR UPDATElocks the row during booking, preventing race conditions from concurrent requests
Possible causes:
- Wrong DB password copied from provider
- Password parsing issue in
.env(wrap value in quotes) - Wrong
DB_HOST/DB_PORT/DB_NAMEcombination - App not restarted after
.envchange
Cause:
- Schema not initialized in managed database.
Fix:
- Run
db/init.sqlagainst the target database. - Verify with
SELECT to_regclass('public.users');.
- Current DB client config supports SSL.
- For strict certificate validation in production, configure CA certificate usage in DB client configuration and set
rejectUnauthorizedappropriately.
ISC License Β© 2026 ChaiCode Web Dev Cohort 2026