Contributing
How the repository is laid out and how to send a change.
Repository layout
src/
app/ routes
(marketing)/ public site and docs
(app)/ signed-in surfaces
prompter/[roomId]/ the display
remote/[roomId]/ the remote
components/
brand/ ui/ marketing/ docs/ app/ pwa/
prompter/ engine, canvas, session hooks
lib/
markdown/blocks.ts deterministic script splitter
prompter/state.ts state shape, limits, themes
realtime/ protocol, link, WebRTC mesh
server/
api/routers/ tRPC: script, room
auth/ Auth.js config and guards
db/ Drizzle schema and client
scripts/
generate-brand-assets.mjs renders the app iconsGetting set up
Follow Running your own; a contributor setup and a self-hosted setup are the same thing. You need your own Supabase project and at least one OAuth client of your own; there is no shared development backend.
Conventions
- TypeScript is strict, including
noUncheckedIndexedAccess.npm run typecheckhas to pass. - Prettier decides formatting.
npm run formatbefore you commit. - Anything off the network is validated with Zod before it is used, on both the tRPC boundary and the realtime one.
- The frame loop does not touch React. If you are adding something that runs per frame, it belongs in the engine, not in state.
- Comments explain decisions, not mechanics. Say why the anchor is not a scroll offset; do not narrate what the next line does.
- No emoji in the interface, and no placeholder copy. Every string is real.
Testing a change by hand
There is no substitute for two real devices. The sync path in particular cannot be exercised in one browser window, because the WebRTC tie-break and the presence ordering both depend on there being two device keys.
- Run
npm run devand open the display on your computer. - Reach the dev server from your phone on the same network, or use a tunnel. Remember that WebRTC and the wake lock need a secure context, so a tunnel with HTTPS is more representative than a LAN IP.
- Check the badge on both devices. If it says Direct, the peer path is live; if it says Relay, you are exercising the fallback.
- Test a reload mid-session. Persistence is easy to break and easy to miss.
Worth knowing
Force the relay path by disabling WebRTC in the browser, or by putting one device on a network that blocks UDP. Both paths need to work, and the relay one is the one users on venue Wi-Fi will actually get.
Wanted
- TURN support. An optional, configurable TURN server so direct routes are possible on hostile networks.
- Import. Google Docs, plain text, and a paste handler that converts formatting to Markdown.
- Timed segments. A per-section target duration with a countdown on the remote.
- Foot pedals. Gamepad API mapping, so a pedal can drive play and step.
- Accessibility. Screen-reader behaviour on the prompter surface deserves a proper look.
Sending a change
- Open an issue first for anything that changes the sync protocol or the data model.
- Branch, make the change, run typecheck and format.
- Describe what you tested and on which devices. “Two devices, same Wi-Fi, direct” is useful; “works for me” is not.
- Open a pull request against the repository.
Teleprompt is MIT licensed and maintained by Biios. Contributions are accepted under the same licence: a merged patch carries your name in the history and nothing else changes hands.