Phone remote
The phone remote turns a phone into a one-handed clicker for the presenter view. It shows a live copy of the current slide, drawn by the deck’s own components, so what you see is what the room sees. Everything it does runs as a command in the presenting window, the same commands the keyboard runs, so it can do exactly what the keys can and nothing more.
For a walkthrough, see Present from your phone, even on a static host.
What it does
Section titled “What it does”| Control | What happens |
|---|---|
| Next and back | step forward or back, as Space and K do; in Laser or Zoom mode, a swipe left on the slide is next and a swipe right is back |
| Laser | touch the slide to point at that spot on every screen; lift your finger and the dot goes |
| Pen | draw on the slide with your finger; the same shapes and eraser as the desk’s pen, with undo and clear |
| Zoom | tap a point to zoom into it; tap again to zoom out |
| Air pointer | hold the button and move the phone: the laser follows where you aim |
| Blackout | black out the audience’s screens, and bring them back |
| Focus | show the focus labels on links, terms and embedded pages, as F does |
| Slides | a list of every slide; tap one to jump there |
| Notes | the part of your notes for the current click step, with A− and A+ to resize them |
| Timer | the presenter’s stopwatch or countdown and how far ahead or behind you are; tap it to pause |
The settings button holds the rest:
- Pointer: a laser dot (a red point) or a spotlight (dims the rest of the slide).
- Air pointer reach: how far you turn the phone to reach the slide’s edge, from ±8° to ±45°.
- Buzz at: minutes into the talk when the phone vibrates, for a quiet “ten minutes left”.
- Tick on every press: a short vibration on each button.
The remote keeps the phone’s screen awake while it is paired, where the browser allows a wake lock. A paired phone cannot open windows on your computer, go full screen there, or pair other phones.
Pairing
Section titled “Pairing”- In the presenter view (press S on the deck), click Phone remote in the toolbar.
- Scan the QR code with the phone’s camera. The phone opens the deck’s
/remotepage and connects.
The QR code holds a one-time code, not a password or a ticket:
- A code works once, and for one minute. While the dialog is open it changes every 30 seconds, so a photo of your screen is soon useless.
- One phone at a time. The newest phone to scan becomes the remote; any other is disconnected and says “Another phone is the remote”.
- A paired phone keeps a lease for its browser tab. A reload or a dropped connection reconnects it without scanning again.
- Disconnect in the dialog drops the phone, even while it is offline, voids its lease and changes the code.
- Copy link copies the pairing address, for when the camera can’t read the screen.
The address in the QR is …/remote#pair=CODE on a deck with a live room (the fragment never
reaches a server) and …/remote?pair=CODE on kadal-deck dev or a relay.
How the phone reaches the deck
Section titled “How the phone reaches the deck”The phone and the presenting window need something in between to carry the remote’s messages. There are three, and the deck picks the right one by itself.
| Where the deck runs | What carries the remote | What you do |
|---|---|---|
| Published on deck.kadal.cc, or any host with a live room | the deck’s room | nothing: the QR pairs through the room |
kadal-deck dev on your computer |
the dev server | run kadal-deck dev --host so the phone can reach it |
| A static build (GitHub Pages, Netlify, S3, any file server) | a remote relay | run kadal-deck relay and point the deck at it |
A deck with a room always pairs through the room, and kadal-deck dev always pairs through the dev
server, whatever remote.relay says. A build pairs through a relay only when you name one; it
never reaches for one on its own.
On the dev server
Section titled “On the dev server”npx kadal-deck dev --host # on your network: the phone opens http://<your computer>:5173/npx kadal-deck dev --host --https # a self-signed certificate, for the air pointernpx kadal-deck dev --tunnel # on the internet through a Cloudflare Quick Tunnel (needs cloudflared)npx kadal-deck dev --remote <password> # on your network, with the presenter pages behind a passwordpnpm exec kadal-deck dev --host # on your network: the phone opens http://<your computer>:5173/pnpm exec kadal-deck dev --host --https # a self-signed certificate, for the air pointerpnpm exec kadal-deck dev --tunnel # on the internet through a Cloudflare Quick Tunnel (needs cloudflared)pnpm exec kadal-deck dev --remote <password> # on your network, with the presenter pages behind a passwordyarn kadal-deck dev --host # on your network: the phone opens http://<your computer>:5173/yarn kadal-deck dev --host --https # a self-signed certificate, for the air pointeryarn kadal-deck dev --tunnel # on the internet through a Cloudflare Quick Tunnel (needs cloudflared)yarn kadal-deck dev --remote <password> # on your network, with the presenter pages behind a passwordbunx kadal-deck dev --host # on your network: the phone opens http://<your computer>:5173/bunx kadal-deck dev --host --https # a self-signed certificate, for the air pointerbunx kadal-deck dev --tunnel # on the internet through a Cloudflare Quick Tunnel (needs cloudflared)bunx kadal-deck dev --remote <password> # on your network, with the presenter pages behind a passwordOpen the presenter view at the Network address Vite prints, not at localhost: the QR code
carries the address of the page it is shown on, and a phone can’t open your computer’s
localhost. The dialog says so when it sees one.
--tunnel always guards the presenter, notes, notes editor and overview pages with a password,
because a tunnel address is public and the dev server can write your files. Without
--remote <password>, one is made up and printed. The phone needs only the QR code.
On a static host
Section titled “On a static host”A build has no server of its own, so the presenter view and the phone meet at a small relay you run. Name it in the headmatter:
---title: My talkremote: relay: wss://relay.example.com/---or add ?relay=wss://relay.example.com/ to the presenter view’s address (kept for that tab, and
carried to the phone by the QR). The first time, the Phone remote dialog asks for the relay’s
password. See Remote relay.
The air pointer
Section titled “The air pointer”Hold Hold to point and move the phone: turning it left and right moves the point across the slide, tipping it up and down moves it up and down. Where you aim when you press is the middle of the slide. The movement is smoothed (a One Euro filter), so a steady hand gives a steady dot.
- It needs the phone’s motion sensors, and browsers give those only to a secure page (
https). On plainhttpthe button says “Air pointer needs HTTPS — touch the slide to point”, and the laser still works by touch. A published deck,dev --https,dev --tunneland anhttpsstatic host with awss://relay are all secure. - On an iPhone, iOS asks for permission to use motion. It only asks after a tap, so the first time the button says Tap to allow motion · then hold to point: tap it once, allow, then hold.
- With
dev --https, the phone warns about the self-signed certificate the first time. Accept it for that address to continue.
The remote page in your deck
Section titled “The remote page in your deck”The starter deck passes the engine’s remote page to <Deck>:
import { RemotePage } from "@kadal/deck/remote";
<Deck manifest={manifest} config={config} components={components} pages={{ presenter: PresenterPage, audience: AudiencePage, notes: NotesPage, stats: StatsPage, remote: RemotePage, }}/>;A deck made before the remote existed doesn’t list remote. Since 0.3.5 the engine serves its own
remote page anyway, loaded only when a phone opens /remote, so older decks work without a change.
Troubleshooting
Section titled “Troubleshooting”| What you see | Why, and what to do |
|---|---|
The dialog says the page is open on localhost |
Open the presenter view at your computer’s network address (dev --host prints it), or at the published address. |
| The phone says “Not paired” | The code was used or is more than a minute old. Scan the current QR. |
| The phone says “Another phone is the remote” | A newer phone scanned the QR. Scan again to take over. |
| The phone says “Waiting for the presenter view” | It is paired, but the presenting window is closed, reloading or asleep. Bring the presenter view back; the phone reconnects by itself. |
| Air pointer needs HTTPS | Use the published deck, dev --https or dev --tunnel, or point by touch. |
| The dialog asks for a password and refuses it | It is the relay’s password, printed where kadal-deck relay runs. Ten wrong tries a minute from one address are refused for a minute. |
| Nothing happens on a static build | The deck names no relay. Add remote: { relay } or ?relay= (see above). |