███████ ██ ██ ███████ ███ ██ ███████ ██████ ██ ██ ███ ██ ██████ ██████ ██ ██ ██ ██ ████████ ████████ ██ ██ ██ ██ ████ ██ ██ ██ ██ ██ ██ ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ╚══██╔══╝╚══██╔══╝ █████ ██ ██ █████ ██ ██ ██ █████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██████ ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ╚██ ██╔╝ ██ ██ ███████ ████ ███████ ██ ████ ██ ██████ ██████ ██ ████ ██████ ██ ██ ██ ╚████╔╝ ██ ██
Project a glanceable HUD of your FoundryVTT D&D session onto Even Realities G2 AR glasses (576 × 288, 4-bit greyscale phosphor green), driven by tap / scroll / long-press gestures from the Even R1 smart ring. Eyes on the table, not on a laptop.
The MVP is deterministic — every action is explicit gesture → tool → Foundry. AI is an optional V2 add-on, never a dependency.
Map base · persistent status corner card · overlay panels stacked like Foundry desktop windows. A single layered UI, never a paginated app.
R1 ring: tap to cycle, double-tap to back, scroll to navigate, long-press for the Quick Action menu. No on-glass keyboard, ever.
Every action goes through Activity#use() with all rules, hooks, MidiQOL, advantage / disadvantage. The DM keeps full veto power.
Optional foundry-mcp server exposes Foundry tools as Model Context Protocol. Drive from Claude Desktop or any MCP client. Plug-out, no cascade.
Every PR, every audit, every release must satisfy them. They're constraints, not guidelines — ratified in §0.1 of the spec as the contract between today's design and tomorrow's implementation.
Formatting and layout are dynamic and always perfect. Frame corners, dividers and columns align to the character in every state — HP 7 / 70 / 700, names from 4ch to 16ch, Italian to English — never misaligned for any reason. Snapshot tests + Box/TextRun render contract.
Every technical claim cites a canonical upstream source — Even Hub, foundryvtt.com/api, dnd5e wiki, MCP spec, vendor pricing. Re-verified before each version bump and Phase 0 GO/NO-GO. Drift is classified, fixed and logged. Three rounds completed; the fourth is the next pre-implementation audit.
Spec / README / showcase are always coherent and updated in the same commit for any cross-cutting change — version, fps target, phase count, hardware spec, locale set. No half-updated states. Cross-reference integrity is a hard gate.
Code is clean, optimized, documented — and zero dead or unreachable code tolerated. Biome + TS strict + Vitest coverage gate enforce in CI. // TODO without an issue/ADR link fails the build. JSDoc/TSDoc on every public API. Hot-path benchmarks gate regressions.
Every spec parameter below is cited verbatim from Even Realities and FoundryVTT documentation, re-verified across 3 cross-check rounds on 2026-05-10.
| Resolution | 576 × 288 px / eye |
|---|---|
| Color | 4-bit greyscale (16 levels green) |
| Containers | max 4 image + 8 text/list per page |
| Image size | 20–200 px W × 20–100 px H |
| Text container | 1 000 char (2 000 with upgrade) |
| List container | 20 items × 64 char, no in-place updates |
| Networking | fetch / XHR / WebSocket · whitelisted origins |
| Layout | absolute pixel from top-left, no DOM/CSS |
| Microphone | 4-mic directional array · PCM 16 kHz s16le mono via bridge.audioControl() |
| Audio out | ❌ no speaker · feedback is visual only |
| Camera | ❌ none (intentional) |
| Plugin runs on | paired phone WebView (not on G2 firmware) |
| Connection | BLE → Even App → G2 |
|---|---|
| Gestures | tap · scroll · long-press |
| Biometrics | HR · HRV · SpO₂ · skin temp · steps · sleep |
| Material | zirconia ceramic + medical-grade stainless steel |
| Water | IP68 · 50 m / 30 min |
| Battery | ~4 days · ~90 min full charge |
| Operating temp | -10 °C to 45 °C |
The G2 has no virtual keyboard, by design. Foundry connection bootstrap — bridge URL, auth token, character pick — lives in the Even Realities App per-plugin settings UI, the same surface Conversate / Translate / Teleprompt use. Pairing is a QR scan from the Foundry desktop module: no manual token copy-paste in the clipboard, audit trail kept by the DM. See §3.8 / §7.14.7.
┌───────────────────────────────────────────────────────────────────┐ │ EvenFoundryVTT — Setup ✕ │ ├───────────────────────────────────────────────────────────────────┤ │ │ │ STEP 1 / 3 · Connection profile │ │ ◉ Homelab (LAN) ○ Cloud bridge ○ Local dev │ │ Bridge URL │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ https://homelab.lan:8910 │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ │ STEP 2 / 3 · Auth token │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ evf_••••••••••••••••••••••••• │ │ │ └─────────────────────────────────────────────────────────┘ │ │ [ 📷 Scan QR from Foundry module ] [ 📋 Paste from clipboard ] │ │ │ │ STEP 3 / 3 · Character │ │ ✓ Connected to Foundry world "Homebrew 2024" │ │ ◉ Thorin Mountainforge (Fighter 3 / Wizard 5, multi) │ │ ○ Lyra Brightleaf (Cleric 7) │ │ ○ Drak'val (Barbarian 6) │ │ ☑ Auto-connect when G2 is worn │ │ │ │ [ Back ] [ Save & connect ▶ ] │ └───────────────────────────────────────────────────────────────────┘
Foundry world (server-side, all players). Even App phone settings (text input, per-device bootstrap). G2 device-local (gesture toggles only, e.g. [M] map mode, [N] language). A simple decision tree picks where each new setting lives. §7.14.6
Foundry module Settings → "Pair a G2 device" → 24h opaque bearer + QR. Scan once, persist on phone. The bearer never sees the user's clipboard. Pairings are listed and revocable from Foundry by the DM. §7.14.7.3 / §11.5.4
Plugin code lives on a server (CDN-friendly static HTML+JS). The Even Realities App fetches the URL into the WebView. Two URLs in app.json: plugin host + bridge. Local dev uses your LAN IP — not localhost (the phone can't resolve it). §3.7
Click a tab to mount a panel over the map base layer. The persistent status HUD never disappears — it's always there in the corner, exactly like a Foundry window with a pinned mini character sheet. Mockups taken verbatim from the spec § 7.
Every plugin slot is versioned. dnd5e v6 lands? swap the Foundry adapter — no cascade. Even SDK changes? swap the provider. New ring (R2)? swap the event source. Forward compat is a primary requirement.
Inspired by the Doom-on-exotic-devices pattern: state runs on capable hardware, gets rasterized + dithered server-side, frames stream to the constrained display via slow channel. Nine deterministic stages, each with a time budget.
Library stack benchmarked: image-q + upng-js + xxhash-wasm = 30–50 % compute reduction vs roll-your-own. Bundle ~ 90 KB gzipped.
BLE bandwidth is the bottleneck on a 4-bit greyscale phosphor display. The MVP commits to 5 fps event-based standard. The 15 fps stretch needs all six layers + Phase 0 favorable signals (partial-update API, BLE 4.2 DLE).
Internationalization is wired in from the MVP — the locale auto-detects from game.i18n.lang in Foundry and broadcasts at handshake; the player can override it directly from the glasses without touching the world setting. Catalogs live in Foundry (dnd5e + module languages), the G2 carries no strings of its own. See §7.16 of the spec.
╔═══════════════════════════════════════════════════════════════════════════════╗ ║ ◈ LANGUAGE ║ ║ ║ ║ ▶ [ • ] Auto (Foundry: it) ║ ║ [ ◦ ] English (en) ║ ║ [ ◦ ] Italiano (it) ║ ║ [ ◦ ] Deutsch (de) ║ ║ [ ◦ ] Español (es) ║ ║ [ ◦ ] Français (fr) ║ ║ [ X ] Cancel ║ ║ ║ ║ R1 scroll=select tap=apply long=cancel ║ ╚═══════════════════════════════════════════════════════════════════════════════╝
Locale is read from game.i18n.lang at handshake. Catalogs come from dnd5e (en/de/es/fr/it/ja/ko/pl/pt-BR/ru/zh-CN) and the evenfoundryvtt module. The G2 ships no strings.
Long-press R1 → Quick Action → [N] Language. Selection is device-local: it never modifies the world setting. Auto mode follows the GM live; explicit override sticks per-device.
Every i18n key carries a _max width. The build verifies all locales fit, otherwise falls back to English. Layout integrity (INV-1) holds even when Italian strings run 30% longer than English.
updateImageRawData format · BLE bandwidth · partial-update API · DLE 4.2+ · GO/NO-GO decision tree (Branch A / B / C)V2 only — never required. The MCP server lives outside the core, exposes the same tool registry the MVP already uses for manual actions. Add Claude Desktop or any MCP client; remove it without touching anything else.
Verified upstream (hub.evenrealities.com/docs/guides/device-apis): G2 4-mic array streams PCM 16 kHz s16le mono to plugins via bridge.audioControl(true). No extra hardware. §3.5
EvenAI ("Hey Even") is proprietary, cloud-backed, and exposes no API to dev apps — not us, not anyone. The voice/transcript event types simply aren't in the SDK taxonomy. Our MCP-via-external-client is therefore a platform constraint, not a design choice. §3.6
The G2 has no speaker, bone-conduction or audio output (verbatim Even docs: "no audio output, no arbitrary pixel drawing, no camera"). Every result lands as a toast banner (§7.15.2) or status HUD update — never a beep, never a TTS line.
cast_spell tool received by foundry-mcp/v1/action/use-activity on bridgeactivity.use() + MidiQOL + AbilityTemplateThe G2 itself never runs an LLM. It receives the result, renders a 3-second toast banner over the map, and the persistent status HUD updates (HP, slots, conditions). The LLM is free to be replaced — every component is a plugin slot.
Library choices are research-driven and documented as ADRs. Every external dependency was evaluated against alternatives in § 11.5.7 of the spec.