How it works

A menu-bar app and a web page.

No App Store, no jailbreak, nothing to install on the iPad. A small Swift app on the Mac serves the interface to Safari over your local network.

iPad

Safari, iOS 12 and later

  • Home-screen web app, full screen
  • TypeScript + Preact, bundled by esbuild
  • Widget grid engine and editor
  • Keeps itself awake, recovers from crashes
HTTPInterface, pairing, app icons, website icons, artwork
WebSocketMetrics every second, actions, trackpad, Pomodoro, layout
Mac

Menu-bar app, Swift

  • Hand-written HTTP + WebSocket server, port 8765
  • Collectors: IOKit, CoreAudio, libproc, EventKit
  • Actions: CGEvent, Accessibility, AppleScript, Shortcuts
  • No third-party dependencies

Built for old iPads

An iPad Air from 2013 tops out at iOS 12.5 and 1 GB of RAM. The interface is written for exactly that:

  • The build refuses anything iOS 12 can't run. Every bundle is checked as ES2017 JavaScript, for post-Safari-12 APIs, and for CSS that iOS 12 doesn't support. A self-test makes sure the checker itself catches the classic traps.
  • Small and steady: about 190 KB of JavaScript (64 KB gzipped), no framework beyond Preact, no heavy effects like backdrop blur.
  • Made to run all day: it keeps the screen awake, reconnects on its own, and if something crashes it shows a short notice and reloads itself.
  • One grid engine places, moves and resizes widgets, with tests for every edge case.

The Mac side

The menu-bar app is a Swift package with no dependencies. It serves the interface, keeps the paired devices, sends the Mac's state once a second, and runs the actions the iPad asks for.

AreaHow
CPU, memory, disk, networkMach host statistics, libproc, IOKit
Temperatures, fans, powerThe SMC, read without root
BatteriesIOKit for the Mac and accessories, Bluetooth for AirPods, libimobiledevice for iPhone and iPad
AudioCoreAudio for outputs and volume; a system audio tap and an AirPlay 1 sender for speakers
Calendar, remindersEventKit
Music, Spotify, dark modeAppleScript
Keys, typing, trackpadCGEvent and Accessibility

What stays on the Mac

Your layout, paired devices (names, dates and only a hash of each token) and Pomodoro stats, in ~/Library/Application Support/MacDeck/. There's no account, no analytics and no cloud service.

The only requests that leave your network:

  • the weather and city search, from Open-Meteo, for the city you set;
  • track artwork for what's playing;
  • the icons of the websites your link keys open.

Security model

Home network only. The iPad and the Mac talk over plain HTTP and WebSocket, without TLS. On a café, hotel or office network, someone could capture a paired device's token. Quit the app on networks you don't trust.
  • Pairing needs the 6-digit PIN shown on the Mac, accepted only while the Pair window is open. It works once and expires after 3 minutes or 5 wrong tries.
  • Tokens are random, sent as HttpOnly cookies, and stored on the Mac only as SHA-256 hashes.
  • Local only: the server answers only clients on the Mac's own subnets, and WebSocket connections must come from the app's own origin.
  • Revoke any time: Paired Devices in the menu bar. A revoked token stops working at once.
  • A paired iPad is trusted: it can press keys, type, move the pointer and quit apps. Treat it like an unlocked keyboard.

Found a problem? Please report it privately, as described in the security policy.

Credits

  • OldPhoneDeck by GLAUCOMA82, for the idea of turning an old iPhone into a deck. OldPadDeck is a separate implementation, written from scratch for the iPad.
  • Preact (MIT), bundled in the iPad interface.
  • Weather data by Open-Meteo.com, under CC BY 4.0.