Funded Crossword
March 20, 2026 · View on GitHub
Real-time multiplayer crossword-style game with:
- Node.js + Express backend (
backend/) - PostgreSQL persistence
- SSE realtime updates
- React + Vite frontend (
frontend/)
Tempo Mainnet: Defaults target Tempo Mainnet (chain 4217): MPP_TESTNET=false, TEMPO_RPC_URL=https://rpc.presto.tempo.xyz. The frontend uses viem’s tempo chain with the same RPC.
Tempo Moderato testnet (matches mppx testnet: true, chain 42431): set MPP_TESTNET=true, TEMPO_RPC_URL=https://rpc.moderato.tempo.xyz, and in frontend/src/wagmiConfig.ts use tempoModerato instead of tempo.
On-chain checks (TIP-20)
Payments use TEMPO_CURRENCY; winner payouts use the same token from WINNER_PAYOUT_PRIVATE_KEY. Verify RPC chain id and balances:
cd backend
npm run tempo:check
Project Structure
backend/- API server, game logic, DB schema/initfrontend/- web app UI (mobile-first responsive)
Prerequisites
- Node.js 18+ (recommended)
- PostgreSQL running locally or remotely
Backend Setup
- Copy env template and fill values:
cd backend
cp .env.example .env
- Set at least:
DATABASE_URL
- Install and run:
npm install
npm run dev
Backend default URL: http://localhost:3001
Health check:
GET /healthz
Frontend Setup
- Install and run:
cd frontend
npm install
npm run dev
Frontend default URL: http://localhost:5173
If needed, set API base URL in frontend env:
VITE_API_BASE=http://localhost:3001
Core API Endpoints
GET /puzzles- list puzzles (?status=all|active|completed)POST /puzzles/create- create puzzleGET /puzzles/:id- fetch one puzzlePOST /puzzles/:id/reveal- reveal a random unrevealed letterPOST /puzzles/:id/guess- guess full answer or char+indexGET /events/puzzles/:id- SSE realtime stream
Demo User Identity
For mutating actions, backend uses:
x-user-addressheader (preferred), oruser_addressin request body, or- fallback:
demo-user
Frontend includes a user-id input to simulate multiplayer users.
Notes
- Inputs are normalized/validated to uppercase alphanumeric (with spaces where allowed).
- Completed puzzles display full answer for all users.
- Char guesses on already revealed positions are rejected.