Roll real physical dice remotely and see the result on camera.
A web application that controls a physical dice-rolling mechanism via a Raspberry Pi. Users can roll dice from the website or by mentioning @dice4me on X.com.
User (Web/X.com) → VPS (Next.js) → Raspberry Pi → Servo rolls dice → Camera captures result → Photo displayed
- User clicks "Roll Dice" on dice4.me or tweets
@dice4me roll - VPS sends a trigger to the Raspberry Pi
- Pi moves an RC servo to physically shake and roll two dice
- Pi captures a photo from a USB camera
- Photo is sent back to VPS, watermarked with roll number, and displayed
- For X.com rolls: bot replies with the roll number and result photo
- Next.js 15 (App Router) - Web frontend and API
- PostgreSQL + Prisma - Roll history and settings
- Twitter API v2 - Filtered stream for real-time mention detection
- Cloudflare Turnstile - Bot protection
- Sharp - Photo watermarking (roll number, X.com username)
- Fastify - HTTP server for trigger and camera stream endpoints
- gpiozero (Python) - Servo motor control via GPIO
- ffmpeg - USB camera MJPEG stream and photo capture
/home/dice4me/
├── app/
│ ├── page.tsx # Landing page
│ ├── components/ # React components
│ └── api/
│ ├── roll/route.ts # POST: trigger roll, GET: history
│ ├── roll/[id]/route.ts # GET: poll roll status
│ ├── roll/callback/route.ts # POST: Pi sends result here
│ ├── rolls/[filename]/ # GET: serve roll photos
│ └── stream/route.ts # GET: proxy camera snapshot
├── lib/
│ ├── db.ts # Prisma client
│ ├── pi.ts # Pi trigger helper
│ ├── twitter.ts # Twitter API (reply, retweet, post)
│ └── twitter-stream.ts # Filtered stream listener
├── prisma/schema.prisma # Database schema
├── pi/ # Raspberry Pi codebase
│ └── src/
│ ├── index.ts # Fastify server
│ ├── servo.ts # Servo control (gpiozero/lgpio)
│ ├── camera.ts # Photo capture from stream
│ └── stream.ts # MJPEG stream from USB camera
└── data/rolls/ # Saved roll photos
- Raspberry Pi 5
- SG90 or MG996R servo motor (GPIO 18)
- USB webcam (1280x720)
- Dice tray attached to servo arm
- 2x standard 6-sided dice
npm install
npx prisma db push
npm run build
npm startcd pi
npm install
sudo apt install ffmpeg
sudo tsx src/index.tsSee .env.local for required variables:
PI_TRIGGER_URL- Pi trigger endpointDICE4ME_API_KEY- Shared API keyTWITTER_*- Twitter API credentialsTURNSTILE_*- Cloudflare Turnstile keysDATABASE_URL- PostgreSQL connection string
- Mention
@dice4me rollto trigger a dice roll - Must be following @dice4me to use
- Bot replies with roll number, then result photo
- Result photo is retweeted to main timeline
- Web rolls are also posted as tweets
| Service | Description |
|---|---|
dice4me-web |
Next.js production server (VPS) |
dice4me-twitter |
Twitter filtered stream listener (VPS) |
dice4me-pi |
Pi server with servo + camera (Raspberry Pi) |