Live market simulation for classrooms — digitises role cards, tracks transactions in real time, and calculates economic surplus automatically.
| Layer | Tech |
|---|---|
| Frontend | Next.js 14 (App Router) |
| Backend | Next.js API Routes |
| Database | NeonDB (Serverless Postgres) |
| Hosting | Vercel |
| Styling | Tailwind CSS + CSS variables |
- Create a free project at neon.tech
- Open the SQL Editor in the Neon dashboard
- Paste and run the contents of
db/schema.sql - Copy your Connection String from
Connection Details
npm install
cp .env.example .env.local
# Paste your Neon connection string into .env.local
npm run devnpx vercel
# Add DATABASE_URL as an environment variable in the Vercel dashboardOr connect your GitHub repo to Vercel for automatic deploys.
- Go to the app URL → Create Game
- Set a passphrase (remember it — you'll need it to control the session)
- Share the 6-digit PIN with students (display on projector)
- Wait for everyone to join → click Start Round
- Monitor live trades on the dashboard
- Click End Round when time is up → penalties applied automatically
- Optionally queue a Market Shock before the next round
- Repeat from step 4
- Go to the app URL on their phone → Join Game
- Enter the PIN + their name
- Wait in lobby until the teacher starts
- Receive a secret role (BUYER or SELLER) with a secret value
- Negotiate verbally with classmates, then log the trade in the app
- Partner confirms → surplus calculated automatically
| Rule | Detail |
|---|---|
| Buyers | Max willingness to pay: $95–$140 |
| Sellers | Min willingness to accept: $50–$95 |
| Consumer Surplus | Max Price − Transaction Price |
| Producer Surplus | Transaction Price − Min Price |
| No-trade penalty | Entire secret value deducted from total surplus |
| Partner restriction | Cannot trade with the same person across consecutive rounds |
Shocks are queued between rounds and applied when the next round starts.
- Supply Shock — shifts all seller minimum prices upward (models scarcity)
- Demand Shock — shifts all buyer maximum prices upward (models increased desire)
Example shock descriptions:
"A mysterious virus is killing the oysters!"→ supply shock, +$20"Face masks are suddenly in high demand!"→ demand shock, +$25
pearl-exchange/
├── db/
│ └── schema.sql # Run once in Neon SQL Editor
├── lib/
│ ├── db.ts # NeonDB connection
│ └── game.ts # PIN gen, role distribution, surplus calc
└── app/
├── page.tsx # Home: Create / Join
├── teacher/[sessionId]/ # Teacher dashboard
├── play/[sessionId]/ # Student view
└── api/sessions/ # All API routes
├── route.ts # POST /api/sessions
└── [id]/
├── route.ts # GET session status
├── players/ # GET players / POST join
├── rounds/ # POST start round / POST end round
├── transactions/ # GET feed / POST propose / PUT confirm
└── shocks/ # GET / POST market shocks
| Variable | Description |
|---|---|
DATABASE_URL |
NeonDB connection string (required) |