Sync a PDF presentation across every device in the room. The presenter controls the page; participants follow via link or QR code.
npm install
npm run dev- Web app: http://localhost:5173
- API + WebSocket: http://localhost:3001
- Start presenting → upload PDF (optional title + PIN).
- Share the QR code or join link (
/j/roomId) — no presenter secret in the QR. - Use Next / Previous or arrow keys when you have control.
- Participants can Take control if the presenter allows it.
npm run preview # build + start on port 3001
# open http://localhost:3001Or:
npm run build
NODE_ENV=production PORT=3001 npm run startThe API and the React app are served from the same port.
- Push the repo to GitHub.
- render.com → New Web Service → connect the repo.
- Use the
render.yamlin the repo (or set build:npm install && npm run build, start:npm run start). - Set
PUBLIC_URLto your Render URL (e.g.https://share-slides.onrender.com). - Deploy. Participants and presenter use the same URL.
Note: On the free tier, the service sleeps when idle; uploaded PDFs are lost on redeploy (ephemeral disk). Fine for demos.
| Variable | Default | Description |
|---|---|---|
PORT |
3001 |
Server port |
NODE_ENV |
— | Set to production when deployed |
WEB_ORIGIN |
http://localhost:5173 |
Extra CORS origin (dev) |
PUBLIC_URL |
auto from request | Public URL for join links & QR |
- Presenter token is only in the presenter URL (
?t=...), not in the QR. - Optional room PIN for participants.
- Rooms expire after 24 hours (in-memory; restarts clear rooms).
- PDF access requires PIN or presenter token.
apps/server Express + Socket.io + PDF upload
apps/web Vite + React + PDF.js viewer
packages/shared Shared message types