DO NOT FLASH THIS ON A LOCKED XTEINK VIA THE UNLOCKER YOU WILL LIKELY BRICK YOUR DEVICE! this is only for unlocked xteink’s only
A Lua-powered firmware runtime for the Xteink X4 e-paper reader.
A TeamIDE project.
Join the community on Discord · Follow on X · Subreddit: r/TeamIDELabs · YouTube: @TeamIDElabs.
CrossLua Reader is a C runtime that turns the Xteink X4 into an extensible e-reader platform. The firmware provides hardware drivers, a font renderer, and a Lua 5.4 interpreter. Everything else — readers, menus, network features — runs as Lua plugins loaded from the SD card.
Built on the hardware knowledge from CrossPoint Reader, rewritten from the ground up in pure C.
CrossPoint Reader is an excellent e-reader firmware, but it's a monolithic C++ application. Every feature is compiled into the firmware. Adding new functionality requires C++ embedded development, a PlatformIO toolchain, and a firmware flash.
CrossLua Reader takes a different approach: the firmware is a compact ~640KB runtime, and all application logic lives as Lua scripts on the SD card. No recompilation, no reflashing — just drop a .lua file on the SD card:
-
Want to browse Project Gutenberg? Drop
gutenberg.luaon the SD card. -
Want to read JSON files? Drop
json_viewer.luaon the SD card. -
Want an RSS feed reader? Drop
rss_reader.luaon the SD card. -
Want a dictionary lookup? Drop
dictionary.luaon the SD card. -
Want a note-taking tool? Drop
notes.luaon the SD card. -
Want a daily quote reader? Drop
daily_quotes.luaon the SD card. -
Want a Bible reader with chapter navigation? Drop
bible.luaon the SD card. -
Want a Pomodoro timer for reading sessions? Drop
pomodoro.luaon the SD card.
The goal is to let people customize and extend the firmware without ever touching a C++ compiler. If you build a plugin you think others would enjoy, send a PR — I'll audit it and ship it in the community plugins directory.
SD Card Flash (~640KB)
├── plugins/ ├── C HAL drivers
│ ├── epub_reader.lua ├── Font loader + renderer
│ ├── txt_reader.lua ├── Framebuffer renderer
│ ├── md_reader.lua ├── Lua 5.4 interpreter
│ ├── file_browser.lua ├── C → Lua API bindings
│ ├── settings.lua └── Plugin manager
│ ├── sefaria.lua
│ └── ...
├── fonts/
│ ├── NotoSans-14-Regular.cfont
│ └── ...
└── books/
-
Plugin system — extend the device by dropping
.luafiles on the SD card -
C runtime — minimal flash footprint, maximum headroom (C++ only in SDK bridge layer)
-
SD-loadable fonts — add fonts without reflashing (.cfont format)
-
Hebrew/RTL support — bidirectional text rendering built into the core
-
Full Lua 5.4 — tables, closures, coroutines, string manipulation
-
Native API — display, input, storage, WiFi, fonts, ZIP, XML, JSON exposed to Lua
-
MCU: ESP32-C3 (single-core RISC-V @ 160MHz)
-
RAM: ~380KB (no PSRAM)
-
Flash: 16MB
-
Display: 800x480 e-ink
-
Storage: SD card
-
Device: Xteink X4
Early development. See build_plan.md for the phased roadmap.
CrossLua Reader is designed so contributing is as simple as writing a Lua script.
-
Try an idea — write a
.luafile, drop it on your SD card, reload. No toolchain, no flash. -
Share it — open a PR with your plugin and a short description.
-
Get it shipped — accepted plugins land in the
community/directory of the next release.
Plugins must be MIT-licensed, free of network calls to non-public APIs, and pass a basic code audit (no os.execute shenanigans, no busy loops that wreck the battery).
Using AI to contribute is welcome — please mention AI use in your PR description. I've intentionally left my Claude Code setup (.claude/, .skills/, CLAUDE.md) in the repo so contributors using Claude Code (or any tool that reads CLAUDE.md) start with my conventions, style preferences, and project gotchas already loaded. That's especially aimed at folks who want to contribute but aren't deeply technical — open the repo in Claude Code, describe what you want to build, and the assistant should know enough to make something close to what I'd accept. Full AI policy and contribution details in CONTRIBUTING.md.
CrossLua Reader can be translated into any language by dropping a single JSON file on the SD card. No code, no toolchain — if you can edit a text file, you can ship a language pack.
Each pack lives at sdcard/languages/{code}/lang.json (where {code} is the ISO 639-1 code: es, fr, ja, ar, etc.) and follows the same schema as sdcard/languages/en/lang.json:
{
"code": "es",
"name": "Español",
"direction": "ltr",
"fontFamily": null,
"strings": {
"home": "Inicio",
"settings": "Configuración"
}
}
A few notes for translators:
-
nameshould be the language's name in its own script (Español,日本語,العربية) — that's what shows up in the language picker. -
directionis"ltr"or"rtl". The runtime handles bidirectional text rendering automatically. -
fontFamilyisnullif your language uses Latin or Cyrillic glyphs already shipped with the firmware. For scripts that aren't covered (Hebrew, Arabic, CJK, Greek, etc.), bundle a.cfontfile insidelanguages/{code}/fonts/and setfontFamilyto its family name. The.cfontformat is documented indocs/cfont-format.mdand there's a converter intools/. -
Partial translations are welcome. Any keys you skip fall back to English at runtime, so you can ship what you have and the community can fill in the rest.
To contribute a language pack, open a PR adding your languages/{code}/ folder. Translation PRs land fast — there's no code to audit, just a quick sanity check on UTF-8 encoding and that the strings render in the app.
I've been writing code since high school — starting with LAMP-stack stuff back when that was the move. Built a little browser-based OS, a custom CMS, a static site generator. But coding has always been a side thing, never my career: I spent two decades in the electronics recycling industry, where I built my own inventory system to keep the doors open. So I'm a developer in practice, more hobbyist than professional, and I've been at it long enough to know what I'm doing.
CrossLua Reader is one of several projects I'm building under TeamIDE. I'm not great at self-promotion or monetization, so if this is useful to you, send me some love at teamide.dev/support. Every bit helps me keep TeamIDE's projects going.
MIT