๐ฅ A personalized, asynchronous dashboard for Waveshare E-Ink displays, built with Python and Dock
10K+
Powered by Pi, rendered in Pixels.
A modern, modular, and highly customizable dashboard for Waveshare E-Ink displays. Built with Python 3.14+ using async/await patterns and a clean, testable architecture.
The easiest way to run is using Docker - it handles all dependencies and driver setup automatically.
| Todo | HackerNews |
|---|---|
![]() | ![]() |
| Quote | Poetry | Wallpaper | Year-End Summary |
|---|---|---|---|
![]() | ![]() | ![]() | ![]() |
| Happy Birthday | Anniversary | Valentine's Day |
|---|---|---|
![]() | ![]() | ![]() |
| Happy New Year | Spring Festival | Mid-Autumn Festival | Christmas |
|---|---|---|---|
![]() | ![]() | ![]() | ![]() |
# Pull the latest image
docker pull palemoky/paper-pi:latest
# Or use GitHub Container Registry
docker pull ghcr.io/palemoky/paper-pi:latest
# Run with docker-compose (recommended)
git clone https://github.com/palemoky/paper-pi.git
cd paper-pi
cp .env.example .env
# Edit .env with your API keys
# For dashboard/quote/wallpaper modes (default)
docker-compose up -d
linux/arm64 - Raspberry Pi 3/4/5 (64-bit)asyncio and httpx for concurrent operationstenacitywatchdogThe E-Ink Dashboard follows a modular, event-driven architecture with clear separation of concerns:
flowchart LR
%% --- Style Definition ---
classDef control fill:#e1f5fe,stroke:#01579b,stroke-width:2px;
classDef data fill:#f3e5f5,stroke:#4a148c,stroke-width:2px;
classDef render fill:#fff3e0,stroke:#e65100,stroke-width:2px;
classDef hw fill:#e8f5e9,stroke:#1b5e20,stroke-width:2px;
classDef subBox fill:#ffffff,stroke:#90a4ae,stroke-width:1px,stroke-dasharray: 5 5;
%% --- 1. Control Layer ---
subgraph ControlLayer ["๐ฎ Core & Control"]
direction TB
Main("Main Orchestrator")
Config("Config & Hot Reload")
DisplayCtrl{{"Display Controller"}}
TaskMgr("Task Manager")
end
%% --- 2. Data Layer ---
subgraph DataLayer ["๐ก Data Acquisition"]
direction TB
Fetcher("Data Fetcher")
subgraph Providers ["Providers"]
External["External APIs<br/>(Weather, GitHub, BTC, HN)"]
Local["Local Info<br/>(Quotes, Poetry, TODO)"]
end
subgraph Storage ["State Management"]
Cache[("Cache (TTL/LRU)")]
State[("Persistence DB")]
end
end
%% --- 3. Render Layer ---
subgraph RenderLayer ["๐จ Rendering Engine"]
direction TB
ImgBuilder("Image Builder")
subgraph Strategies ["Layout Strategies"]
DashLayout["Dashboard Layout"]
ContextLayouts["Context Layouts<br/>(Holiday, Quote, Poetry)"]
end
Renderer["Primitive Renderers<br/>(Text, Icons, Shapes)"]
end
%% --- 4. Hardware Layer ---
subgraph HWLayer ["๐ฅ๏ธ Hardware Output"]
direction TB
DriverFac("Driver Factory")
EPD["E-Paper Driver"]
Mock["Mock (PNG)"]
end
%% --- Connection Logic ---
%% Control Flow
Main --> Config & TaskMgr
Main --> DisplayCtrl
Config -.-> Main
%% Data Flow
Main --"Trigger"--> Fetcher
Fetcher --> External & Local
External & Local -.-> Storage
%% Render Flow
DisplayCtrl --"Select Mode"--> ImgBuilder
ImgBuilder --"Get Data"--> Storage
ImgBuilder --> DashLayout & ContextLayouts
DashLayout & ContextLayouts --> Renderer
%% Output Flow
Renderer --> DriverFac
DriverFac --> EPD & Mock
%% --- Application Style ---
class Main,Config,DisplayCtrl,TaskMgr control
class Fetcher,External,Local,Cache,State data
class ImgBuilder,DashLayout,ContextLayouts,Renderer render
class DriverFac,EPD,Mock hw
class Providers,Storage,Strategies subBox
When your tokens are only available on macOS (Keychain/local auth files), use file-based secrets and sync them to Raspberry Pi:
docker-compose.yml):volumes:
- ${PAPER_PI_SECRETS_DIR:-./secrets}:/run/secrets:ro
.env:CLAUDE_OAUTH_TOKEN_FILE=/run/secrets/claude_oauth_token
CHATGPT_OAUTH_TOKEN_FILE=/run/secrets/chatgpt_oauth_token
KIMI_API_KEY_FILE=/run/secrets/kimi_api_key
# install (interactive โ prompts for repo path, Pi SSH host, secrets dir)
bash <(curl -fsSL https://raw.githubusercontent.com/palemoky/paper-pi/main/scripts/install_launchd.sh)
# view logs
tail -f /tmp/sync_ai_tokens.log
# uninstall
bash <(curl -fsSL https://raw.githubusercontent.com/palemoky/paper-pi/main/scripts/install_launchd.sh) uninstall
Note
- The app reads token files on every usage query (no restart needed after token refresh).
- If a usage request returns non-200 (token likely expired), that provider switches to
--fallback and pauses further requests with the same token until a new token is synced.- Secret files are mounted read-only in container and written only on Raspberry Pi host.
EPD_MODEL env var (supports most models in the official repoโ )Antigravityโ for the pair programming
Waveshareโ for E-Ink display drivers
Chinese Poetryโ , LxgwWenKaiโ , Hanyiโ for poetry
Flaticonโ , Weather Iconsโ for icons
CoinGeckoโ for BTC price
OpenWeatherMapโ for weather
Figmaโ for UI design
CodexIslandโ and BluETagโ for AI token usage
All the open-source libraries that make this project possible
Content type
Image
Digest
sha256:7efa0ab9aโฆ
Size
72 MB
Last updated
about 1 month ago
docker pull palemoky/paper-pi