Lessons
What didn't work, the traps that cost hours, and what two evenings taught me about building with an AI.
What didn't work, honestly
| Tried | Why not |
|---|---|
| Root or custom firmware | There's no public exploit for this model. Everything stays within what Samsung's Developer Mode allows. |
| Replacing Samsung's Home bar, starting at boot | Samsung doesn't allow either. Pin the launcher first instead. |
| The Jio set-top box | Developer options removed, ADB closed. Leased hardware, left alone. |
| Google sign-in in the TV's browser | Google refuses that engine. Faking another browser would get round it; I chose not to. |
| Real Chrome compiled to WebAssembly | A TV with 1 GB of RAM can't run it. |
| Phone control of YouTube and Netflix | That needs the TV's own remote channel, whose pairing prompt never appeared. Samsung's SmartThings app already does it. |
Traps on a Samsung TV
If you build anything for Tizen, these will save you hours. Each one cost us real time.
- Check what a device really is. "[TV] SONY" was a Samsung. Ask the TV's API on port 8001 before assuming.
- Unsigned packages hang silently at "Installing package". Sign everything.
- Copy a working
config.xmlinstead of writing one from memory. One navigation rule blanked the whole app. - Reinstalling isn't restarting. Kill the app before every install, or you'll test the old build.
- No console? Use a beacon. Image requests to a tiny logger on your laptop.
putImageDataon a large canvas draws nothing on this TV. Use WebGL textures.- Background services run Node 4.4.3. ES5,
new Buffer, no npm. Hand-roll small protocols. - Secure pages can't reach the TV's local
httpserver (mixed content). Local apps can; websites can't. - Exiting an app with
exit()also stops its background service. Killing it from the laptop didn't, which made our first test misleading. Test the way a user triggers it. - The TV drops off Wi-Fi after standby unless Auto Power Off is off and "Power on with mobile" is on.
- CDNs cache by file name. Tag every release and change the script's file name.
What I took away
1. Measure before you optimise
One function was 90% of Doom's frame time. Without a profile I'd have guessed something else, and fixed the wrong thing.
2. Measure on the real device
A change that looked 20× faster on my laptop did nothing on the TV. The laptop numbers were real; they just weren't the TV's problem.
3. Working with an AI is a skill
Claude was fast, tireless and very good at debugging blind. It scanned the network, reverse-engineered the install path, wrote a WebSocket server for a 2016 runtime and rebuilt Doom from C. But the decisions that made this good were mine: rejecting two launcher designs, insisting Doom be smooth rather than merely running, refusing to settle for laggy controls, and saying no to the shortcuts that weren't worth taking.
I brought the foundation and the direction. Claude did the reverse engineering and the code. That split is the honest version of this story, and I think it's the interesting one.
Credits
- doom.wasm by Jacob Enget, built on doomgeneric by ozkl. GPL-2.0. Our engine changes are in the repo's
doom-build/. - Doom shareware episode (v1.9, freely distributable), © id Software.
- TizenBrew by reisxd, which made TV Browser+ possible.
- qrcode-generator by Kazuhiko Arase (MIT), for the dot QR codes.
- Fonts: Doto and Space Mono (OFL).
- Design inspiration: Nothing OS.
The code: samsung-tv-dotos (MIT) and tv-browser-plus (MIT).