Build guide

Build a $40 WiFi e-reader that fetches its own news brief

An ESP32-S3, an e-paper panel, five buttons, and a scheduled agent that writes the morning brief. Roughly $40 in parts and a weekend.

The batch 01 kit is closed. If another batch opens, the email list above hears first. Everything you need to build one yourself is below, free.

Handheld e-paper reader in a black taped cardboard case showing page 35 of 36 of a news brief.
Page 35 of a generated brief. Text is pre-wrapped on the host, so the device only draws characters.
Inside the case: an ESP32-S3 dev board with soldered wires running to a blue Good Display adapter board taped to cardboard.
Inside. ESP32-S3 on the left, panel adapter at the bottom, every joint soldered.
Back of the reader showing the dev board's two USB-C ports and the five-way button poking through black tape and cardboard.
The back. Two USB-C ports, the reset and boot buttons, and the five-way switch top right.

Part 1: The hardware

Four parts, $35 to $60 in total. The full parts list with links.

You need four things: an ESP32-S3 dev board, an e-paper panel with its adapter board, a five-way button module, and a way to power it. Total cost lands between $35 and $60 depending on the panel you pick. The ESP32-S3 is the right microcontroller for this because it has WiFi built in, enough flash to store a few books, and a hardware SPI bus that drives the panel at full speed. Buy a board with 8 MB or 16 MB of flash if you can; the 4 MB boards work but leave little room for text. For the buttons, any five-way navigation module (up, down, left, right, center click) from the usual hobby suppliers will do, wired with one common leg to ground and five signal legs to free GPIO pins. Add a BME280 breakout if you want temperature and humidity on the status line; it is optional and costs a couple of dollars.

PartWhat to buyPriceNotes
MicrocontrollerESP32-S3 dev board, 8 or 16 MB flash$6 to $12Any generic S3 board with USB-C. Dual USB-C boards make flashing and monitoring easier.
Display5.76" E Ink Carta Display Module (GDEH0576T81) (use the promo code "stition3" at checkout), or the Waveshare 7.5" e-Paper (V2, 800x480, black and white) with its e-Paper driver HAT$25 to $45 with adapterBuy the panel and its adapter board as a kit. The ready-made firmware supports exactly these two panels. See the panel section below.
ButtonsFive-way navigation switch module$1Five signals plus one common ground.
Capacitors470 uF electrolytic + 100 nF ceramicunder $1Across the adapter's VCC and GND. Not optional.
PowerUSB only, 3x AA + Schottky diode, or a small lithium cell with charger board$0 to $8Pick one. Details below.
OptionalBME280 breakout$2 to $4Temperature and humidity on the status line.
CaseTwo pieces of cardboard and tape, a 3D print, or a cheap CNC order$0 to $15Cardboard is what you see in the photos.

Choosing the e-ink panel

Two panels work out of the box. What to check if you buy a different one.

The ready-made firmware supports exactly two panels: the 5.76 inch Good Display GDEH0576T81 and the Waveshare 7.5 inch V2 (800x480). If you buy one of those, skip the filtering below. Ordering any other display is where people get lost, and it needs a code change (a new entry in the panel table in the repo), so here are the variables that matter. Go to waveshare.com (or good-display.com, whose panels Waveshare resells; use the promo code "stition3" at checkout) and filter on these:

  • Size. 5.7 to 7.5 inches reads like a paperback. 4.2 inches is pocketable but cramped for a full page of text.
  • Resolution. Aim for 800x480 or better. Below that, small text looks jagged and you lose a column of characters per line.
  • Color. Plain black and white refreshes fastest. The three and four color panels take 10 to 20 seconds per page and are a poor fit for reading.
  • Interface. You want SPI, which every hobby panel uses. Skip parallel panels; they need a dedicated controller board.
  • Partial refresh. The one that decides whether page turns flash white for two seconds or update quietly in a few hundred milliseconds. Look for "partial refresh" or "fast refresh" on the product page.

The panel ships as bare glass with a flat ribbon cable, so you also need the matching adapter board (Waveshare calls it a driver HAT, Good Display calls it DESPI). Buy the panel and adapter together as a kit and confirm the adapter runs at 3.3 V. The panel in the photos is a Good Display GDEH0576T81, 5.76 inch, 920x680, black and white, on a DESPI-C02 adapter, and it supports fast partial refresh.

Using the 7.5 inch panel

The Waveshare 7.5 inch V2 uses the same pins as the DESPI adapter in the wiring table below, so the wiring does not change. On a driver HAT revision 2.3 or later there is also a PWR pin; tie it to 3.3 V. The firmware assumes the 5.76 inch panel, so a fresh install of the 7.5 inch build starts with a blank screen. To fix that, hold the center button while you press reset (or while you plug in the USB cable). The reader cycles through the supported panels and draws "Press center if you can read this" on each for about 8 seconds; let go of center, then press it when the text is readable and it saves that panel. After that, the menu item "Screen" switches between panels at any time. The 7.5 inch panel has larger, lower-resolution text, so fewer characters fit on a line, and books you already loaded are reformatted on the reader the first time you open them. Speed read works on the 5.76 inch panel only for now.

Power, with or without a battery

USB only, AA cells, or lithium. Solder the power wires and add both capacitors.

Power is flexible because e-paper holds its image with no power at all, and the position in the book gets saved to flash on every page turn. That means the simplest build has no battery: plug a USB cable in, read, unplug, and the last page stays on the glass. If you want it portable, three AA cells in series (4.5 V) fed through a Schottky diode into the board's 5 V pin works well; the diode drops about 0.3 V and stops the board's USB supply from pushing current back into the cells when you plug in to reflash. A small lithium cell (500 to 1000 mAh) with a $2 charger and protection board is the tidier option and gives weeks of use per charge.

Whatever you pick, solder the panel adapter's power wires directly instead of using Dupont jumper crimps, and put a 470 uF capacitor plus a 100 nF capacitor across the adapter's VCC and GND. E-paper pulls short bursts of current during a refresh, resistive jumpers let the rail sag, and a sagging rail will eventually corrupt or kill the panel controller. That lesson cost me a panel.

Firmware: flash mine, no code needed

Wiring table, then a one-click install in Chrome or Edge. Needs 8 MB of flash or more.

You do not have to write any software. The firmware running on the reader in the photos is open source at github.com/AllanBinder/ereader, and you can install it straight from this page. Wire your parts to the pins below, plug the board into a computer over USB, open this page in Chrome or Edge, and click Install. It takes about two minutes, and it comes with Alice's Adventures in Wonderland loaded so you can check that everything works before you add your own books.

Adapter or partESP32-S3 pinNotes
Panel adapter SDIGPIO 17SPI data
Panel adapter SCKGPIO 18SPI clock
Panel adapter CSGPIO 8
Panel adapter D/CGPIO 9
Panel adapter RESGPIO 10
Panel adapter BUSYGPIO 46
Panel adapter VCC, GND3V3, GND3.3 V, not 5 V. Set the adapter's RESE switch to 0.47.
Button upGPIO 40Directions as you hold the reader in portrait. Each button connects its pin to ground; no resistors needed.
Button downGPIO 41
Button leftGPIO 1
Button rightGPIO 2
Button centerGPIO 42
Button commonGND
BME280 SDA, SCLGPIO 12, 13Optional. The reader shows "n/a" without it.
This browser cannot talk to USB serial ports. Open this page in Chrome or Edge on a desktop or laptop. Serial access needs a secure (https) page. Pick the board's serial port when asked. Installing erases the whole board. It needs an ESP32-S3 with 8 MB of flash or more; 4 MB boards are not supported. If the board does not show up, hold its BOOT button while you plug it in, then try again. On a board with two USB-C ports, use the one labelled USB (not UART or COM). Still stuck? Post in #ereader on the Discord.
Connect it to WiFiPress center to open the menu and pick WiFi setup. The reader puts up a network called ereader-setup. Join it from your phone, pick your home network, type the password. Up to eight networks are remembered.
Add booksPick Books and games (WiFi) in the menu. Join ereader-games from your phone (password ereader1), or open http://ereader.local/ on your home WiFi. Upload any plain text book (Project Gutenberg has 70,000 free ones as .txt) and the reader lays out the pages itself.
ReadDown or left turns the page, up or right goes back, center opens the menu. The page you are on is saved on every turn, so you can unplug it any time. If the picture is upside down in your case, pick Flip screen in the menu.

Make it yours

Change the firmware in plain English with Claude Code. Case options from cardboard to a print.

You can use the firmware exactly as it is; it is a complete reader. If you want something different, it is trivial to change with Claude Code. Clone the repo, open the folder, and describe the change in plain English: "I wired the buttons to different pins," "I have a different e-paper panel instead," "add a menu item that shows tomorrow's weather," "download a text file from my server every morning." The code is small, every pin lives in include/pins.h, every setting lives in include/config.h, and the README explains how the pieces fit, so a change like that is usually one conversation. Ask for soldering instructions in the same conversation and it will walk you through your own pin map one wire at a time. PDF books go through the Python converter in the repo, which keeps figures and page layout better than plain text does.

The case can be as simple as two pieces of cardboard with a window cut for the panel and a hole for the buttons, which is what mine is. For a proper case, the case files come by email: leave your address at the top of this page and I will send them. A printed shell is an evening of work if you have a printer, and if you do not, ordering it from a cheap online CNC or print service runs about $15.

Speed read mode

One to three words per flash, up to about 290 wpm on the 5.76 inch panel.

The reader can also flash a book at you one, two or three words at a time, in one fixed spot on the screen, so your eyes never move. This is called RSVP (rapid serial visual presentation), and it is a strange thing to see on e-paper, which is supposed to be slow. Open the menu, pick Speed read, and pick a book. It starts from the page you are on and keeps your place in step with the normal page view, so you can switch between the two whenever you like.

SettingsThe Speed read book picker ends with two tiles. Words switches between 1, 2 and 3 words per flash. Speed goes up 25 words a minute per press and wraps back to 100. Both are remembered. It starts at two words and 250 wpm; I read at two words and 425.
While it playsLeft or right is 25 wpm faster, up or down is 25 slower, center pauses. Sentence ends hold a little longer than other words, and commas a little longer again, which makes it read like speech instead of a metronome.
While pausedLeft or right plays again, up or down steps back a sentence or two, and center returns to the normal page at the spot you reached.

Getting e-paper this fast took three tricks, and the numbers are specific to the 5.76 inch GDEH0576T81 in the photos. First, the SPI bus runs at 40 MHz while speed read is on, which gets a whole frame to the panel in 54 ms. Second, the panel stores several refresh waveforms (the timed voltage sequence that moves the ink) and picks one by temperature, colder meaning slower. Telling it the room is 40 C selects the shortest one it has, 367 ms. Third, and this is the one that made single words possible: the words are already solid black about 60 ms into that 367 ms waveform, and the rest is margin. So when a flash has to come faster than the full waveform allows, the firmware resets the panel's controller 60 ms in, which stops the drive, and sets it back up again.

Where the time goesStock partial refreshWith the cut
Send the frame over SPI54 ms54 ms
Drive the ink367 ms60 ms
Set the controller up againnoneabout 90 ms, mostly restarting its power supply
Per flashabout 420 msabout 205 ms
Top speed at one word per flashabout 140 wpmabout 290 wpm

The cut is automatic. Any flash that stays on screen for 450 ms or more gets the full waveform, so slow settings and the longer holds at sentence ends never use it; at two words and 250 wpm nothing is cut at all. Every 30 flashes or so, at the next sentence end, the reader does one full refresh (the black and white flash) to wipe the ghosts, and it never waits past 40.

Treat the cut as an experiment on your own panel. Cut flashes leave a little more ghosting, a faint trace of the previous words, which the periodic full refresh clears. The bigger unknown is wear. Refresh waveforms are designed so the voltage across each pixel averages out to zero, and stopping one early probably breaks that balance. Every word pixel that turns black turns white again for the next word, so much of it should cancel, but I cannot promise it all does, and the panel maker does not publish its waveforms. The warning sign is ghosting in the word band that is still there after a full refresh. If you see that, slow down until the cut switches off, or ask Claude Code to make the full refresh more frequent (RSVP_FULL_AFTER in include/config.h).

Speed read is 5.76 inch only for now, and it is hidden on the 7.5 inch panel until I have tested it on glass. On a different panel, the idea carries over but the numbers do not. Most SPI e-paper modules have a controller on the glass that plays back a stored waveform, and resetting it mid refresh should stop the drive on those too. What changes is where the waveform does its work: some start with a shake or a flash to black before they drive the new image, and cutting those early leaves gray or wrong pixels. To find your panel's cut, set speed read to one word, start with a long cut (the RSVP_CUT_MS setting, try 150) and step it down until the words stop reaching solid black, then back off. Ghosting at the end of each 30 flash cycle is the other limit; I stopped at 60 ms because below that the ghosting got distracting. Some controllers also let you load your own short waveform instead, which is cleaner than a cut. Color panels, grayscale, and boards built on the IT8951 controller are a poor fit: the first two have long waveforms, and the IT8951 has its own fast mode (A2) and is slow to reset.

Part 2: The automated news brief

A scheduled Claude Code routine, a small server, and the reader pulling the brief.

The reader gets interesting once it fetches content on its own. The setup has three pieces: a scheduled agent that writes the brief, a small server that stores the latest copy, and the device pulling it over WiFi.

Scheduled agentA Claude Code routine runs on a cron schedule in the cloud, researches the topics you listed, writes plain text, and POSTs it to your endpoint.
Small serverA Cloudflare Worker or a Raspberry Pi. One route accepts the upload behind a token, one route serves the latest file.
DeviceOn boot or button press: join WiFi, GET the file, write it to flash, paginate, show page one.

Claude Code routines handle the first piece. A routine is a Claude Code session that runs on a schedule in the cloud; you give it a prompt such as "research these six topics, write a 1500 word brief in plain text with short paragraphs, no markdown, and upload it to this endpoint," pick a cron schedule (mine runs three mornings a week), and give it network access plus an upload token stored as an environment variable. It runs unattended and posts the finished text.

The server can be almost anything that accepts an HTTP POST and serves a GET. I used a Cloudflare Worker, which is free at this volume and has no machine to maintain: one route accepts the upload behind a bearer token and writes the text to KV storage, the other serves the latest file behind a read token. A Raspberry Pi running a twenty-line Flask app on your home network does the same job if you would rather keep everything local. The device side is a single function: on boot or on a button press, join WiFi, GET the URL, write the text to flash, paginate, and show page one. Ask Claude to write both halves and to keep the brief format fixed at plain text with a known column width so the device never has to do layout work.

The firmware from the Install button leaves the Sync feeds item out of the menu, because it has nowhere to sync from until you have a server. Once you do, ask Claude Code to point NEWS_URL in include/config.h at it, put your read token in include/secrets.h, and flash from source. Sync feeds and Auto sync then show up in the menu.

Other things to put on it Once the pipeline exists, the same routine can produce a daily weather and tide sheet for your area, a summary of a subreddit or a set of RSS feeds, a digest of your own project notes, a language lesson, or a chapter a day of a public domain book. Each is a prompt change and nothing more. The device does not care what the text is about.

Part 3: The Game Boy server and the Pokemon companion screen

The reader serves NES and Game Boy games to your phone and shows a live Pokemon screen.

This is the part the video is about. The reader hosts NES and Game Boy ROMs and serves a browser emulator to your phone over its own WiFi, keeps the saves so a laptop and a phone can share one game, and while Pokemon Red or Blue runs the e-ink turns into a live companion screen drawn with the game's own font, tiles and sprites: the Kanto map with your position, the party with HP bars, badges, money, the bag with Mart prices, the route you are on with its wild encounters and hidden items, and a battle view that scores your moves against the enemy's types. The firmware, the browser page and the design docs are all in the public repo at github.com/AllanBinder/ereader (Apache 2.0). It ships no ROMs and no game assets; you bring your own dump and build the asset pack yourself from the game's disassembly.

Flash the firmwareIf you used the Install button above, you already have it: the emulator page is built into the same firmware. To build from source instead, clone the repo, open it with PlatformIO and run pio run -e esp32s3 -t upload. That updates the firmware without touching your books or saves.
Build the asset packClone pret/pokered into third_party/pokered and run python3 tools/pokered_pack.py. It reads the font, town map, tilesets, sprites, wild tables and item lists straight out of the disassembly and writes build_pack/pokered.pack, about 240 KB. Pillow makes it faster; it works without it.
PlayPick Books and games (WiFi) on the reader. Join its network from your phone (ereader-games, password ereader1) or, if the reader knows your home WiFi from Part 2, open http://ereader.local/ on the same network. Upload the pack and your ROM through the page's file picker, tap the ROM, play.

The reader never emulates anything. An e-paper panel cannot draw sixty frames a second and the ESP32 has no memory to spare, so the emulator (jsnes for NES, WasmBoy for Game Boy and Game Boy Color) runs in the phone's browser and the reader only stores and serves files. What makes the companion screen possible is that the page can read the emulator's memory. Once a second it takes the Game Boy's 8 KB of work RAM and posts it to the reader, and the firmware decodes it with addresses taken from the pokered disassembly: the party lives at one address, money at another, the current map and your step coordinates at two more. Pokemon Red never wrote any of this for a second screen; it just keeps its whole world in 8 KB, and the disassembly community mapped every byte of it. The panel redraws only when something you can see has changed, a partial refresh in about half a second, with a full refresh once a minute to keep the image clean.

On the reader the silkscreen right button pages from Home to Inventory and back, the left one goes the other way, up toggles the terrain view of the map you are standing on, and center leaves the games server. A battle takes the screen on its own and hands it back when the fight ends. On the phone the pad works on touch, and on a laptop the arrows or WASD move, X or E is A, Z or R is B, Enter is Start, Shift is Select. The speed button runs the game at 2x or 4x for grinding. The page saves the cartridge RAM to the reader whenever it changes, writes an autosave every minute, and offers Continue the next time any device opens that ROM.

Make it for another game Everything game specific is in three firmware files plus the generator script, and the repo carries a ranked survey of other games with documented memory maps and full disassemblies: Pokemon Gold, Silver and Crystal (WasmBoy already exposes the full Game Boy Color RAM, so those are nearly free), Yellow, Link's Awakening, FireRed, Harvest Moon, Dragon Warrior IV and Final Fantasy, with the addresses, the repos and the effort each one takes. Start from docs/companion-dashboard-game-candidates-2026-09-13.md, hand the Pokemon files to a coding agent as the worked example, and ship a generator, never the assets or a ROM. I would love to see a Crystal or a Link's Awakening screen; open an issue or send a pull request.

Part 4: Where this could go

Multiplayer ideas and an invitation to help turn this into an open platform.

The part I keep thinking about is multiplayer. The games server already proves the shape: an ESP32 can run as a WiFi access point, so the reader broadcasts its own network and serves a web page to anyone who joins. Nobody installs an app: players scan a QR code on the e-paper, their phone opens a page served by the device, and the panel becomes a shared board on the table that everyone can see while phones hold the private hands. That covers a whole class of tabletop games (trivia, drafting, hidden role, bidding, word games) and the panel is a perfect scoreboard because it stays readable in daylight and holds the last state if someone knocks the power out. The same hardware could host a shared reading group where the device shows one page and each phone gets a vote on what happens next, or a quiz night where the question is on the glass and answers arrive over the local network.

I would like this to be an open source platform rather than one person's project. If you build a reader from this guide, or if you want to help define a small game API (device serves the board, phones post moves over HTTP, everything stays on the local network), come say hi in the _stition Discord, email me, or reply wherever you found the video. Ideas for games, case designs, panel choices, and power setups are all welcome. Pictures of your build are the best contribution of all.