UltimateDarkTowerDigital · Player Guide

Connecting the
Official App to your digital tower

You know the board game. You have never touched this software. This guide takes you from nothing to a working setup where Restoration Games' companion app drives the tower on your screen. There is one program to install and one command to run.

~5 min first time ~1 min every time after 1 terminal window macOS needs a real tower

Section OneWhat you are setting up

In a normal game of Return to Dark Tower, your phone app talks to the plastic tower over Bluetooth. The app is the brain: it decides what happens, then tells the tower to spin its drums, light up, and make noise.

UTDD replaces the plastic tower with a picture of one on your screen. To make that work, three programs have to talk to each other.

📱 Official app the brain — owns all the rules
🗼 The relay pretends to be a real tower
🖥️ UTDD shows the tower and board
  • The relay is a small program that runs on your computer. To your phone, it looks and behaves exactly like a real Dark Tower. It has no window — it just prints text in a terminal.
  • UTDD is the web page with the 3D tower and the game board. It is already online — there is nothing to install for it, you just open a link.
  • So there is exactly one thing to run (the relay) and one link to open (UTDD).
Why so convoluted?

A web browser is not allowed to pretend to be a Bluetooth device — the standard only lets a browser connect to one. That single restriction is the entire reason the relay exists as a separate program instead of living inside the web page.

Section TwoBefore you start

The macOS problem — read this even if you don't use a Mac

Before the official app will talk to any tower, it checks the tower's firmware version. It asks over Bluetooth: "what firmware are you running?"

⚠ Hard limitation

On macOS, the relay is not allowed to answer that question. Apple's Bluetooth stack blocks it. This is a limitation of macOS itself — nothing in this software can fix it. The result is that the app gets stuck forever on the "checking firmware" screen.

You have three ways around it:

Option What you need Verdict
A. Real-tower handoff (Mac) Your actual physical Dark Tower Easy — but repeat it every session
B. Run the relay on Windows Any Windows PC with Bluetooth Easy, works permanently
C. Run the relay on Linux / Pi A Raspberry Pi (even a Zero W) More setup, works permanently

Option A is covered in full below (Section 4b), since it needs no hardware beyond the tower you already own. Options B and C follow this guide exactly, except you skip 4b entirely — the app clears the firmware screen by itself. The gory technical detail is in the macOS BLE limitation note.

If the relay is on a different computer

Options B and C put the relay on a second machine, and that changes one thing: open UTDD in a browser on that same machine. For security reasons a web page may only reach a relay running on the computer it is displayed on — so a Pi in the cupboard works fine if you view UTDD on the Pi, but not if you view it on your laptop.

If you would rather keep the relay headless and watch on your laptop, forward the port first and everything behaves as if it were local:

on your laptop, in its own terminal
$ ssh -L 8765:localhost:8765 pi@raspberrypi.local

Comfortable with Tailscale? tailscale serve in front of the relay gives it a real certificate and works too. The Tailscale 100.x address on its own does not — it has to be the https name.

What you need to hand

Ticks are saved in this browser, so the list survives a reload.

Software to install, once

Node.js — version 22.13 or newer. Download it from nodejs.org and run the installer. To check what you already have, open a terminal and type:

check your version
$ node --version

If it prints v22.13.0 or higher, you're set. If it says "command not found", Node isn't installed yet.

Opening a terminal

Mac: press Cmd + Space, type "Terminal", press Enter.
Windows: press Start and type "PowerShell".
Linux: you already know.

That is the only thing you install. The relay itself is fetched by the command in the next section, and UTDD runs in your browser from a web address. There is nothing to download from GitHub and nothing to build.

One exception

On a Windows PC with an ARM processor (a Snapdragon-based Surface, for example) the relay has no ready-made Bluetooth component and will try to build one, which usually fails without developer tools installed. Intel and AMD Windows PCs, Macs, and Raspberry Pis are all fine.

Section ThreeStart the relay

Open a terminal and run this. It works from any folder:

start the relay
$ npx ultimatedarktowerrelay-cli

The first time, this downloads the relay — that takes a minute or so, and you may be asked to confirm the install by typing y. Every time after that it starts immediately.

⚠ On a Mac: allow Bluetooth

The first run pops up "Terminal would like to use Bluetooth" (or the name of whichever terminal app you opened). Click OK. The relay pretends to be a Bluetooth tower, so if you refuse this it can never advertise and the official app will never find it.

Said no by accident? System Settings → Privacy & Security → Bluetooth, and switch your terminal app on.

You may also be asked about the firewall

Some machines also ask "do you want to allow incoming network connections?" — click Allow. The relay has to listen for a connection from the web page. If you never see this, nothing is wrong; macOS ships with its firewall switched off.

What you should see

The relay opens on a live status board instead of a wall of scrolling text. It looks roughly like this:

 Ultimate Dark Tower Relay — v0.2.0 · emulator · up 00:03

 RELAY
  ws://localhost:8765
  ws://192.168.1.42:8765 (LAN)
  Open  https://chessmess.github.io/UltimateDarkTower/digital/

 TOWER
  ● advertising    app: disconnected    BLE: poweredOn

 STATE
  top north  mid north  bot north   cal · · ·
  led seq 0 · audio #0 vol 0 · beam 0

 CLIENTS (0)
  none connected

 COUNTERS  commands 0   skulls 0   last never

 q quit   r resend   l logging (on)

The line that matters is TOWER: ● advertising. Your computer is now broadcasting itself as a Dark Tower named ReturnToDarkTower. The RELAY panel is your next step — Sections 4 and 5 below just walk through it slowly. That panel also prints a ws://192.168.x.x:8765 address when it can detect your LAN IP — that's the one to use if you're connecting from a phone instead of the same machine.

On a Mac you will also see a line like this in the activity feed near the bottom of the board, which is expected — it's the problem from Section 2:

12:03:50 event [TowerEmulator] macOS detected — skipping Device Information Service (0x180A).
Leave it running

Keep this window open for the whole game session. Closing it, or pressing Ctrl + C in it, shuts the fake tower down.

Section FourConnect the official app

4a · On Windows or Linux / Raspberry Pi

Open the official app and connect to the tower exactly as you always do. It finds ReturnToDarkTower, clears the firmware check on its own, and calibrates. Skip to Section 5.

4b · On a Mac — the real-tower handoff

The app refuses to move past "checking firmware" when talking to the relay, but it will happily accept a real tower. So we let it check a real tower first, then swap.

  1. Turn on your physical Dark Tower and put it within reach.

  2. Stop the relay — press Ctrl + C in its terminal. Two Bluetooth towers with the same name at once will only confuse the app.

  3. Connect the app to your real tower, the ordinary way you always do.

  4. Wait until the app is fully past the firmware check — you should be at the app's normal game screen, and the real tower should have calibrated (you'll hear the drums spin).

  5. Turn the physical tower off. The app notices the tower vanish and offers to reconnect.

  6. Restart the relay and wait for tower ready again.

    start the relay again
    $ npx ultimatedarktowerrelay-cli
  7. Tell the app to reconnect. It finds ReturnToDarkTower — the relay — and connects. Having already satisfied itself about the firmware, it goes straight through.

How you know it worked

The TOWER panel switches to ● connected, and lines like these start appearing in the activity feed near the bottom of the board:

12:04:09 event [TowerEmulator] companion subscribed to state notifications
12:04:11 event [TowerEmulator] command received: 000000000000…

Every command received: line is the app telling the tower to do something. They should appear as you tap around in the app.

Tired of this already?

You have to repeat 4b every session on a Mac. A cheap Raspberry Pi running the relay removes the problem permanently — see the relay setup guide.

Section FiveOpen UTDD and connect it

Leave the relay running in its terminal. Everything from here happens in your browser — there is nothing else to start.

  1. Open UTDD in Chrome or Edge — it is a normal web page, already online:

    https://chessmess.github.io/UltimateDarkTower/digital/

    Bookmark it — this is the same link every session.

  2. Find the "Official app" panel in the left-hand column of the page, just under the Tower panel.

  3. The box should already say ws://localhost:8765 — the address of the relay from Section 3. Leave it alone.

  4. Click "Connect".

  5. Chrome will ask permission — click "Allow". The dialog looks like this:

    chessmess.github.io wants to:
    Access other apps and services on this device
    
                                  [ Block ]   [ Allow ]

    The "other app" is the relay on your own computer. Chrome asks once and then remembers your answer.

    ⚠ It may still go red — that's expected

    Chrome cancels the attempt that made it ask, so the panel can flash "Could not connect" even though you clicked Allow. UTDD notices the permission and retries on its own, so just wait a moment — and if it doesn't go green, click Connect once more. Nothing is broken.

    If you clicked Block, Chrome remembers that too and will not ask again — Section 8 has how to undo it.

Why a web page can talk to your computer at all

localhost means "this machine". Browsers allow a secure web page to talk to a program on your own computer — but, since Chrome 142, only after you say yes. Nothing about your game leaves your machine: the relay and the web page talk directly to each other, and the connection never goes near the internet.

✓ Success looks like

The status line under the button turns green and reads "Connected — the official app is driving the tower."

That green line is your confirmation. You can also check the relay's CLIENTS panel — your browser should now show up there as one connected client.

Now try it. Tap something in the official app that makes the tower do something — a drum rotation, a seal reveal. The 3D tower in your browser should move and light up to match.

Section SixPlaying a game

This is the important part, and the part that surprises people.

The tower is automatic

Everything the app tells the tower to do now happens on your screen: drum rotations, the glowing seal lights, the light patterns. You don't touch the tower controls in UTDD.

Dropping a skull — you press the button

In a real game you physically drop a skull into the tower and its sensor tells the app. There is no sensor here, so the "Drop skull" button in UTDD is your skull drop.

When you press it, UTDD tells the relay, and the relay tells the app "a skull just fell" in exactly the way a real tower would. Press it once per skull, at the point in your turn where you'd normally drop one.

Don't double up

Do not also do something in the app to register the skull. The button is the whole action.

Seals — usually automatic, always correctable

When the app reveals a seal, UTDD works out which seal from the lights and marks it broken for you.

This is the least-proven part of the bridge. If UTDD marks the wrong seal, or misses one, just tap the seal squares in the Tower panel — tap once to break, tap again to undo. Your taps always win.

The board is not automatic

⚠ The big one

When the app says "place a foe at the Ruined Village", that instruction does not travel over Bluetooth. The tower connection only ever carried tower state; it never carried board instructions, not even with a real tower.

So, exactly as in a normal game:

  • Read the placement instructions off the app
  • Move your figures, foes, and skulls yourself
  • Do it on the digital board in UTDD, on your physical board, or both

The same goes for cards, items, corruption, and everything else on your player board.

In short

UTDD replaces your tower. It does not replace your board, your cards, or your table.

Section SevenFinishing up, and next time

To stop: press q or Ctrl + C in the relay's terminal, and close the browser tab.

Next session, the whole routine is:

  1. Start the relay:

    one terminal, any folder
    $ npx ultimatedarktowerrelay-cli
  2. Mac only: the real-tower handoff (Section 4b).

  3. Connect the official app to ReturnToDarkTower.

  4. Open your UTDD bookmark and click Connect.

That's it — one command and a bookmark. Nothing to update, nothing to rebuild; the relay and the web page both keep themselves current.

Section EightWhen something goes wrong

Click any symptom to expand it.

The app sits on "checking firmware" and never moves

This is the macOS limitation from Section 2. Do the real-tower handoff (4b), or run the relay on Windows or a Raspberry Pi. There is no other fix on a Mac.

If the app instead complains the tower is out of date, the firmware value can be overridden — see the limitation note.

The app can't find any tower
  • Is the relay still running, and does its TOWER panel show ● advertising or ● connected? If the terminal closed or the process died, restart it.
  • Is Bluetooth switched on, on both the computer and the phone?
  • On a Mac, did you allow the Bluetooth prompt? If you dismissed "Terminal would like to use Bluetooth", the relay starts up and looks healthy but never actually advertises. System Settings → Privacy & Security → Bluetooth, switch your terminal app on, then restart the relay.
  • Is the phone close to the computer? Stay within ~10 metres.
  • Is your physical tower switched on nearby? Turn it off — two devices with the same name confuse the app.
  • On Linux / Raspberry Pi, the relay needs permission for Bluetooth:
    linux only
    $ sudo setcap cap_net_raw,cap_net_admin+eip $(which node)
UTDD says "Could not connect"
  • First, just click Connect again. Chrome cancels the attempt that raises its permission dialog, so the very first click can fail even when you allowed it.
  • Then: the local-network permission. Chrome has to be allowed to "access other apps and services on this device". If you clicked Block — or dismissed the dialog — it remembers, and will never ask again on its own. Click the icon at the left of the address bar → Site settings → set Local network access to Allow, then reload the page and click Connect again.
  • The relay must be running before you click Connect.
  • Confirm the address is exactly ws://localhost:8765ws://, not http://.
  • If you were asked about the firewall and dismissed it, the relay can't be reached. On a Mac, System Settings → Network → Firewall → Options; on Windows, Windows Defender Firewall → Allow an app.
  • Is the relay on a different computer? Then this is expected — see the note in Section 2. Open UTDD on the machine running the relay, or forward the port with ssh -L.
  • If you changed the relay's port, use the port from its listening on line.
UTDD says "Paused — the app disconnected from the tower emulator"

The phone lost its Bluetooth link. Reconnect in the official app; UTDD picks up again on its own and goes back to green. Nothing is lost.

UTDD says "Host speaks a different relay protocol"

Your copy of the relay is older than the web page. Stop the relay with Ctrl + C and start it again with @latest on the end — that forces a fresh download instead of reusing the one already on your machine. Then reload the browser tab.

force the newest relay
$ npx ultimatedarktowerrelay-cli@latest
The tower on screen doesn't move when the app does something
  • Is the status line green? If not, work through the cases above.
  • Look at the relay's activity feed. If no command received: lines appear when you tap in the app, the app isn't really connected to the relay — it may have silently reconnected to your physical tower. Turn the physical tower off and reconnect.
The 3D tower never appears in the browser

The 3D view loads lazily and the board image is large. Give it a moment on first load, and use Chrome or Edge.

Something else entirely

The relay writes detailed logs to a logs/ folder in whatever folder you ran the command from — it also prints the exact path on startup, on the Event log: line. Those files are what to look at, or attach to a bug report, when nothing here fits. They're also how the seal-detection guesswork gets confirmed, so they're genuinely worth keeping from a real session.

The full operator runbook is the relay troubleshooting guide, and bugs go to GitHub issues.

Section NineGlossary

Term What it means here
Official app Restoration Games' Return to Dark Tower companion app, on your phone or tablet
Relay / host The program from Section 3 that pretends to be a Dark Tower over Bluetooth
Tower emulator The Bluetooth part of the relay — the bit the app actually talks to
UTDD The web page: 3D tower, digital board, player boards
Bridge The connection between UTDD and the relay — the "Official app" panel
Terminal The window where you type commands
Ctrl + C Keyboard shortcut that stops a running program in a terminal