- demonstration url link:- https://www.youtube.com/watch?v=Q2RRNLVUzio&feature=youtu.be
- live site url frontend:- https://sneaker-drop-system.vercel.app/
- live site backend url :- https://sneaker-drop-system.onrender.com/api/health
sneaker drop system
Real-time inventory system for high-demand merch drops with atomic reservations, 60-second expiry, and live stock updates via WebSockets.
Documentation:
- docs/DOCUMENTATION.md — API reference, setup, credentials
- docs/ARCHITECTURE.md — System design, data flows, diagrams
- docs/HOW_IT_WORKS.md — User journey and flow guide
- Frontend: React + Vite + Tailwind CSS
- Backend: Node.js + Express
- Database: PostgreSQL (Prisma ORM)
- Real-time: Socket.io
Create a PostgreSQL database (e.g. via Neon). Set DATABASE_URL (pooled for app) and DIRECT_URL (direct for migrations) in .env.
Copy .env.example to .env in the project root:
cp .env.example .envSet DATABASE_URL and DIRECT_URL (see .env.example). For local Postgres, use the same URL for both.
cd server
npm install
npm run migrateIf you have an existing database from Sequelize, either run npx prisma migrate reset (drops all data) or npx prisma migrate resolve --applied 20250226080000_init to mark the migration as applied.
curl -X POST http://localhost:3001/api/drops \
-H "Content-Type: application/json" \
-d '{"name":"Air Jordan 1","price":199.99,"totalStock":100}'Optional: startsAt and endsAt (ISO 8601) control when the drop is active.
cd server
npm run devcd client
npm install
npm run devOpen http://localhost:5173. Enter a username and reserve items.
An in-process setInterval runs every 5 seconds. It finds Reservation rows where status = 'active' and expiresAt < NOW(), marks them expired, then broadcasts stockUpdated via Socket.io. All connected clients update the displayed stock.
Production alternative: Run the same expiry logic in a cron job or queue worker; the DB + broadcast logic stays the same.
PostgreSQL SELECT FOR UPDATE inside a Prisma transaction:
reserve(dropId, username)usesprisma.$transactionand$queryRawto lock theDroprow withFOR UPDATE.- It counts active reservations and purchases for that drop.
available = totalStock - reserved - purchased. Ifavailable < 1, rollback and returnOUT_OF_STOCK.- Otherwise, create the reservation and commit.
Only one transaction can hold the lock at a time, so concurrent requests are serialized. If 100 users click Reserve for the last item, only one succeeds.
Neon: Prisma uses DATABASE_URL (pooled) for app and DIRECT_URL (direct) for migrations.
| Method | Path | Description |
|---|---|---|
| GET | /api/drops?username=xyz |
List active drops with stock and top 3 purchasers; optionally include current user's reservations |
| POST | /api/drops |
Create drop: { name, price, totalStock, startsAt?, endsAt? } |
| POST | /api/reservations |
Reserve: { dropId, username } |
| POST | /api/purchases |
Purchase: { reservationId, username } |
| GET | /api/reservations/:id |
Validate reservation (for client refresh) |
📖 Full step-by-step guide: DEPLOYMENT.md
Important: Vercel serverless does not support WebSockets. Deploy frontend and backend separately:
- Frontend: Vercel (static SPA)
- Backend: Railway, Render, or Fly.io (supports Socket.io)
- Database: Neon PostgreSQL
- Create a new Vercel project and connect your repo.
- Set Root Directory to
client. - Add environment variables for the production build:
VITE_API_URL– Your backend URL (e.g.https://sneaker-drop-api.onrender.com)VITE_SOCKET_URL– Same asVITE_API_URL(API and WebSocket share the origin)
- Deploy. Vercel will use
client/vercel.jsonand runnpm run build.
Railway
- Create a new project and add a service from your repo.
- Set Root Directory to
server. - Add environment variables in the dashboard:
DATABASE_URL– Neon pooled connectionDIRECT_URL– Neon direct connection (for migrations)CORS_ORIGIN– Your Vercel frontend URL (e.g.https://your-app.vercel.app)
- Run migrations once:
cd server && npm run migrate(or via Railway CLI). - Deploy. The
Procfilerunsnode src/index.js.
Render
- Connect your repo; Render will detect
render.yamlin the root. - Add environment variables in the Render dashboard:
DATABASE_URL,DIRECT_URL,CORS_ORIGIN
- Deploy. The blueprint runs migrations on start and starts the server.
| Variable | Where | Description |
|---|---|---|
DATABASE_URL |
Backend | Neon pooled connection |
DIRECT_URL |
Backend | Neon direct (migrations) |
CORS_ORIGIN |
Backend | Frontend URL (e.g. https://your-app.vercel.app) |
PORT |
Backend | Provided by host (Railway, Render) |
VITE_API_URL |
Frontend (Vercel) | Backend URL for API calls |
VITE_SOCKET_URL |
Frontend (Vercel) | Backend URL for Socket.io |
See PITFALLS_AND_FIXES.md for details on:
- Neon PgBouncer and
SELECT FOR UPDATE - Race between purchase and expiry worker
- Double reservation prevention
- Cross-origin Socket.io
- Input validation and rate limiting