Skip to content
~/tosaki
Go back

AI Secondary Display (Part 1): Reviving a Forgotten Kindle, Crafting an Elegant E-Ink Desktop Dashboard

Edit page

As a devoted enthusiast of electronic paper (E-Ink/ink screen) technology, I firmly believe that E-Ink is the optimal solution for a desktop Always-On Display (AOD) showcasing low-frequency information. It maintains an image without power draw, resulting in extremely low total consumption; its non-emissive nature is neither distracting nor harsh on the eyes. Moreover, its paper-like texture makes it a perfectly elegant and minimalist desktop ornament.

Kindle-Dashboard-Demo

Video Demo

Tutorial

Hardware Options

Numerous DIY kits combining “E-Ink price tags + STM32” are available on platforms like Taobao or Xianyu. However, for most E-Ink enthusiasts, a forgotten Kindle gathering dust at home is often the most accessible larger screen.

I was no exception. With a recent Black Friday upgrade, my loyal companion from high school through my master’s degree—the Kindle Oasis 2—was honorably retired. Rather than consigning it to a drawer, repurposing it was the clear choice. This device, with its premium 7-inch screen and build quality, naturally became my primary target for transformation. Of course, the “server-side rendering” approach discussed here is generalizable. Even if you’re using a platform like STM32, I hope this provides some useful inspiration.

Software Options

1. Past Attempt: The Built-in Browser Method

Years ago, I tried converting a Paperwhite 3 into a secondary display using projects like kindle-weather-dashboard. This method leverages the Kindle’s “Experimental Browser” to display information. A specific command (e.g., ~ds) entered in the search box prevents the screen from sleeping. The main advantage is that it requires no jailbreaking.

However, this approach has significant drawbacks:

2. Current Choice: Jailbroken Client + Server-Side Rendering

To overcome these limitations, I adopted a new strategy: since the Kindle’s rendering capabilities are weak, shift the rendering burden to a server; since the browser can’t go full-screen, jailbreak the device and output images directly.


Technical Implementation Details

The Client: FBInk and Process Management

Kindle-Dashboard

The Kindle’s native system lacks a direct graphics display API. Fortunately, the legendary jailbreak developer NiLuJe created the FBInk tool. It conveniently enables full-screen display of images and text, with fine-grained control over partial or full refreshes—crucial for managing E-Ink ghosting.

The Basic Workflow: The Kindle periodically downloads a pre-rendered image from the server and displays it using FBInk. During implementation, I encountered two major hurdles:

  1. Screen Override and Signal Issues FBInk operates at a low level, forcefully outputting to the framebuffer rather than acting as an overlay. This means the Kindle’s native UI framework updates can overwrite our carefully drawn screen. The intuitive fix is to run stop framework to halt the system interface. This worked perfectly via SSH debugging but failed when the script was packaged as a KUAL extension—the script would mysteriously terminate. The root cause was a classic Unix signal cascade effect: KUAL is a child process of the UI Framework, and my script is a child of KUAL. When the script killed the Framework, its parent process (KUAL) also terminated, subsequently killing the script itself. The solution involved implementing more sophisticated logic for signal handling and process supervision.

  2. Real-time Clock Display The primary image is fetched from the server at intervals of several minutes. However, a secondary display requires minute-accurate clock updates. An elegant solution leverages FBInk’s localized text refresh capability. The main background image updates from the server, while the time in the corner is refreshed locally every minute using FBInk’s text rendering function.

The Server: Modern Development Powered by Vibe Coding

Kindle-Dashboard-Server

The server’s core responsibilities are: fetching data, rendering the dashboard, and generating a grayscale image optimized for E-Ink displays. The tech stack chosen was Flask + Tailwind CSS + Playwright. Thanks to the contemporary paradigm of Vibe Coding (AI-assisted programming), I could rapidly build an aesthetically pleasing interface despite my limited frontend expertise.

1. The Dashboard Page (/dashboard) This page is tailored to my personal information consumption habits and includes:

2. The Render Endpoint (/render) The Kindle does not access the dashboard page directly. Instead, it calls this endpoint. The server uses Playwright to load the dashboard in a headless browser, takes a screenshot, and applies image processing specifically for E-Ink (grayscale dithering, optional scaling for non-7-inch devices), finally returning a high-quality image perfectly suited for the Kindle screen.

3. Configuration and Optimization To facilitate community reuse and customization, I placed configurable parameters like language, location, and financial instruments in a .env file. Since Playwright rendering is resource-intensive and slow, it is advisable in a production deployment (e.g., behind a Caddy/Nginx reverse proxy) to expose only the /render endpoint. If using a CDN like Cloudflare, adding a caching rule for this endpoint is highly recommended. Setting the Time To Live (TTL) slightly lower than the Kindle’s refresh interval balances data freshness with significantly reduced server load.

Summary

We now have a complete hardware and software solution: a rendering service that produces E-Ink-optimized output and a Kindle client capable of perfect full-screen display. With simple configuration, you can create an elegant desktop information hub.

But you might ask: We have the secondary display, but where’s the “AI” from the title?

Patience. The real intrigue lies not just in fetching standard API data, but in leveraging AI to curate and rewrite high-value news content. In the next part, I will detail the implementation of my AI-powered news service.


Edit page
Share this post on:

Previous Post
AI Secondary Screen (Part 2): Building a Personalized Multi-Source News Recommendation Feed with LLMs
Next Post
OSS Migration Log: Moving Image Hosting to Cloudflare R2