A fast, glanceable tactical HUD for Even Realities G2.
Warning
Development status: Sandevistan is still under active development and has not been officially published on Even Hub. Builds from this repository are experimental and intended for local testing on supported G2 hardware.
Sandevistan is an unofficial, fan-made personal HUD for the Even Realities G2.
It renders a 576×288 tactical interface to Canvas, splits it into four 288×144
images, and sends those tiles through a bounded four-call SDK pipeline. The
current product candidate is /hud-canvas-fast.
The project favors useful information, predictable controls, and hardware-proven
behavior over browser-only effects. It has been tested on physical G2 glasses
with the Even Hub SDK pinned to 0.0.11, Even App 2.2.6, and updated G2
firmware.
- Why Sandevistan
- Phone companion
- HUD pages
- Interaction model
- Transport design
- Live data
- Localization
- Ask AI
- Optional navigation
- Local development
- Build, test, and package
- Project structure
- SDK compatibility
- Privacy, attribution, and limitations
- Contributing
- License and trademarks
G2 is a constrained display, not a miniature phone. Sandevistan is designed around that fact:
- Large, high-contrast typography that remains legible on the optical display.
- Dense overview information distributed across four focused pages.
- Full-screen detail decks for maps, news, tasks, weather, and navigation.
- Canvas-first rendering for visual consistency and fast page changes.
- Serial, fail-fast image transport with no deferred refresh queue.
- Keyless location, weather, news, and map data.
- Optional OpenRouteService routing with a device-local key or development fallback.
- An Even-style phone companion for configuration and live status.
- A dedicated developer screen for physical-hardware diagnostics.
The same /hud-canvas-fast entry point provides a light, touch-friendly
companion UI around the persistent G2 Canvas. Its home screen follows the Even
app's compact two-column card rhythm and keeps the live HUD preview mounted
while settings screens are open.
Nine cards open their settings directly, without an intermediate management menu:
| Card | Phone capability |
|---|---|
| Devices | G2/R1 availability, battery, and transport state |
| HUD layout | Enable and reorder glasses pages while keeping Overview |
| News | Enable, rename, add, or remove up to six HTTPS RSS/Atom sources |
| TODO | Add, edit, complete, reopen, and delete up to six tasks |
| Weather | Inspect current conditions and request one immediate refresh |
| Navigation | Validate and store a user-owned ORS key on the device |
| Language | Follow the system language or select one of 180 bundled languages |
| Ask AI | Configure OpenAI BYOK, response pacing, local usage, and MCP servers |
| Developer | Inspect, copy, and clear the WebView trace |
The footer identifies the project, app-manifest version, development status, and GitHub repository. The phone UI never remounts the Canvas during navigation, so opening settings does not restart the G2 transport.
The dashboard keeps a 288×288 live map on the left and a page-specific information panel on the right.
| Page | Purpose |
|---|---|
OVERVIEW |
Local time, full date, current weather, and the connected device battery |
NEWS |
Current headlines from the enabled local RSS source list |
TODO |
Three persistent checklist items and today's completion progress |
WEATHER |
Current conditions, apparent temperature, humidity, precipitation, and wind |
ASK AI |
Recent conversation excerpts and locally estimated weekly/monthly spend |
NAVIGATION (active route only) |
Route state, remaining distance, next maneuver, and destination |
A single tap opens the active page's four-tile detail deck:
OVERVIEWopens the full-screen map.NEWSopens one real RSS story at a time with paginated body text.TODOopens the full checklist and selected item.WEATHERopens current conditions, hourly context, and a large tactical weather icon.ASK AIstarts a new text-only Realtime conversation using the G2 microphone.NAVIGATIONopens the current maneuver and route progress.
The same gestures work from the G2 temple and the R1 ring:
- Scroll: move between dashboard pages.
- Single tap: open the active detail deck or activate its selected item.
- Fast double tap: return from a detail deck to its dashboard page.
- Dashboard double tap: on the production route, replace the image page with one blank event-capture container without sending images; double tap again to rebuild the image page and restore the latest view.
Within full-screen details:
- News scrolls through the current article body before advancing to another story.
- TODO scroll selects an item; tapping toggles it in either direction.
- Navigation scroll selects route instructions; tapping returns to the active step.
- Map scroll direction is reserved for zoom: down zooms in and up zooms out.
The map zoom radius is remembered across dashboard, detail, and location updates:
850m, 650m, 500m, 375m, or 280m.
The display is divided into four named G2 image containers:
| Container | Image ID | Bounds |
|---|---|---|
sandevistanTL |
2 | left, top — 288×144 |
sandevistanTR |
3 | right, top — 288×144 |
sandevistanBL |
4 | left, bottom — 288×144 |
sandevistanBR |
5 | right, bottom — 288×144 |
The hardware-proven send order is:
- Initial display, restore, and full-screen detail:
3 → 5 → 2 → 4. - Dashboard page change: right side only,
3 → 5. - Map movement: left side only,
2 → 4. - Visible minute or battery change: top-right only,
3.
Only one accepted refresh owns the transport at a time. Up to four SDK tile
calls belonging to that refresh may be in flight; missing or invalid pipeline
values resolve to four, while explicit values from 1 through 4 remain
available for diagnosis. A tile whose encoded bytes match the last successful
send is skipped. Any refresh request arriving while transport is busy is
dropped immediately: it is not queued, merged, replayed, or retried. A failed
refresh remains failed and the next independent event may try again.
Content tiles use a four-level grayscale palette by default. On physical G2
hardware this reduced the measured full-frame payload by 54.4% and the median
restore latency by 24.8%. Explicit black-control hide frames bypass palette
conversion because their encoded payload is already minimal. Use
?levels=original for the palette rollback, or
?pipeline=1&levels=original for an explicit serial/original comparison.
See the pipeline hardware gate
and palette comparison.
An opt-in 1-bit BMP path remained reliable but was 14.7% slower in the
controlled full-frame comparison, so PNG remains the production default. See
the BMP hardware gate.
A Base64 string SDK bridge was also rejected: all four tile calls returned
sendFailed within 3–4 ms before transfer began. The stable typed-byte path
remains mandatory, and stale bridge query values are ignored. See the
Base64 bridge hardware gate.
The query-free fast HUD replaces the image page with one blank, full-screen
event-capture container when hiding. It performs no image encode or image send;
restoring rebuilds the normal page and resends all four current tiles. The path
is fail-fast and never falls back within the same input event. Physical G2
evidence reduced median hide latency from 394 ms to 87.5 ms (77.8%) with no
sampled transport failure, so the owner promoted it to the production default.
Use exact ?hide=black only for the former four-black-tile diagnostic control.
See the fast blank display hardware record.
This policy replaced an earlier backlog design that could accumulate tens of thousands of stale minute and location operations and eventually freeze the WebView.
Core features do not require an API key.
| Feature | Source | Refresh policy |
|---|---|---|
| Current location | Even Hub SDK | Initial reading, then accepted at 15s / 15m |
| Weather | Open-Meteo | 15-minute cache plus foreground recheck |
| News | Device-selected HTTPS RSS/Atom through a hardened same-origin proxy | Progressive library up to 100 stories; one-hour refill while idle |
| Roads and place labels | OpenStreetMap via Overpass | When the rounded location cell changes |
| Clock | Local device time | Minute boundary, skipped if that minute was already rendered |
| Battery | Even SDK device-state event | Only when the visible value changes |
If live position is unavailable, Sandevistan uses a recent cached position. If
there is no cached position, the HUD clearly identifies demo data instead of
presenting it as live. Missing map data renders NO DATA; missing GPS renders
NO GPS DATA. A location without a heading uses a hollow position circle rather
than a directional arrow.
Weather, news, and map failures retain the last successful value as stale data. RSS and Overpass access use same-origin server routes. Custom feeds are limited to validated public HTTPS URLs, reject credentials, fragments, non-default ports, IP literals, local/private host suffixes, redirects, non-feed content, responses over 1 MB, and requests over eight seconds.
Persistent values use the sandevistan:*:v1 local-storage namespace.
Sandevistan ships 180 structurally complete, offline locale packs. The original thirty are:
Korean, English, Japanese, Simplified Chinese, Traditional Chinese,
Spanish, French, German, Italian, Portuguese, Dutch, Polish,
Russian, Ukrainian, Turkish, Arabic, Hebrew, Hindi, Bengali,
Indonesian, Vietnamese, Thai, Malay, Filipino, Swedish,
Norwegian, Danish, Finnish, Czech, and Romanian.
Each pack owns all phone, HUD, route, weather, default-task, and weekday copy. There is no runtime translation service and no English fallback for a registered language. Arabic and Hebrew set the phone companion to RTL while the fixed tactical HUD geometry remains LTR.
Every language receives exactly three built-in news channels from the shared
server catalog. The catalog contains 540 feeds; locales without a stable local
RSS edition explicitly fall back to the three English international feeds. It can be
checked live, one request at a time, with npm run verify:rss-live. See
Adding a Sandevistan language for the
type-safe extension workflow.
Ask AI is an optional, text-only OpenAI Realtime surface designed for the G2's microphone-only hardware. Its dashboard page shows excerpts from the three most recent conversations and device-local estimates for this week's and this month's usage. Merely viewing that page never opens the microphone or creates an API session; tapping the page starts a new conversation.
The detail view uses one official Even Hub Text container rather than image tiles. OpenAI semantic VAD owns turn detection, user transcription appears in the same rolling transcript as the response, and assistant text is presented one Unicode grapheme at a time. The default interval is 200 ms and can be adjusted from 100–1,000 ms in 50 ms steps on the phone. A single tap reveals an already received answer immediately or cancels an active response; a double tap exits, closes microphone ownership, and restores the Canvas dashboard.
Built-in tools provide current time, current live location, and bounded web search. Users may also add bounded HTTPS MCP servers with optional bearer authentication and tool allowlists. Every MCP call requires explicit approval on the glasses. Active tool state appears in the transcript's trailing status line instead of replacing conversation text.
OpenAI access is BYOK. The key is stored only through the Even local-storage bridge and is sent directly to OpenAI solely to mint a short-lived Realtime client secret for serverless Private Builds. It is never bundled or logged. Conversation excerpts, citations, usage, and cost records remain device-local. Weekly and monthly estimates include Realtime token/audio usage and recorded web-search calls using the versioned local pricing snapshot; they are estimates rather than OpenAI billing records.
Only destination search and route calculation require a key. The preferred flow is to enter a user-owned key in the Navigation card. Sandevistan validates it, stores it through the Even local-storage bridge, and sends it only in a dedicated same-origin request header. The server uses it for that request and never stores, returns, or logs it.
ORS_API_KEY remains an optional local-development fallback. Neither key path
uses Vite client variables or embeds a key in source, browser responses, logs,
or the EHPK package.
Without a key, location, weather, news, and the OSM map continue to work. Routing controls stay out of the way rather than occupying a disabled HUD panel.
With a key, the companion WebView can search Korean destinations and request
walking, cycling, or driving routes. During active guidance, location sampling
increases to 2s / 5m. Three consecutive positions at least 35m off route trigger
a recalculation, limited to one request every 30 seconds. Ending guidance clears
the route and restores the normal 15s / 15m location policy.
Recent routes are stored for at most six hours and return as stale context; the app never resumes guidance automatically.
Requirements:
- Node.js 22 or newer.
- npm.
- Even Realities app with Even Hub access for physical G2 transport.
- Tailscale or another phone-accessible local network when testing on hardware.
Install dependencies:
npm installStart the development server:
npm run dev -- --host 0.0.0.0 --port 4176 --strictPortOptionally enable the server-side development fallback:
ORS_API_KEY='<server-only-key>' \
npm run dev -- --host 0.0.0.0 --port 4176 --strictPortOpen the app through Even Hub → Scan QR:
http://<PHONE-REACHABLE-IP>:4176/hud-canvas-fast?sdk=0.0.11&build=<BUILD-ID>
No performance query is required. The hardware-proven four-call pipeline is the production default. For an explicit serial and original-palette comparison, use:
http://<PHONE-REACHABLE-IP>:4176/hud-canvas-fast?sdk=0.0.11&pipeline=1&levels=original&build=<BUILD-ID>
You can generate the configured QR code with:
npm run qr
npm run qr:hide-black
npm run qr:rollbackThese convenience scripts target the maintainer's current Tailscale hardware
preview on port 4179. Other developers should replace the host with their own
phone-reachable address and the development-server port selected above.
Run the production qr and diagnostic qr:hide-black routes one at a time.
Close the first Even Hub WebView before opening the second so their transport
sessions cannot overlap.
A normal desktop or mobile browser shows the Canvas preview. G2 transfer starts only when the page is opened through the Even app bridge.
All test execution is serial to avoid resource contention with the G2 development environment.
npm test
npm run test:repo
npm run typecheck
npm run build
npm run test:sites
node --test --test-concurrency=1 tests/*.test.mjs
npm run verify:rss-live
git diff --checkConfirm that the client cannot access the ORS secret:
git grep -n "ORS_API_KEY" -- src app.json package.jsonBuild an Even Hub package locally:
npm run packThe resulting sandevistan.ehpk is a local artifact. The npm package is marked
private, and this repository does not publish to npm or Even Hub.
src/ Phone companion, Canvas renderers, G2 transport, live state
server/ Same-origin weather, news, map, and optional route APIs
tests/ Node tests for API and production-worker behavior
scripts/ Build preparation and repository policy checks
docs/design/ Selected HUD visual direction
docs/hardware/ Physical G2 checkpoints and measured transport records
docs/research/ Even Hub and G2 constraint research
docs/superpowers/ Historical design specifications and implementation plans
app.json Even Hub application manifest
Preserved diagnostic routes include:
/hud-canvas— original four-tile Canvas HUD./hud-hybrid— Canvas plus native Text layer experiment./hud-hybrid-z— explicit Text z-order experiment./calibration-max— 576×288 display-boundary calibration./diagnostic-v10— tap-to-send 1-bit BMP transport diagnostic.
| SDK | Physical G2 result | Status |
|---|---|---|
0.0.11 |
Four-tile bounded image transport works | Current pinned fallback |
0.0.12 |
The old host failed immediately on its compressed image path | Historical reproduction only |
0.0.13 |
Passed bilateral transport checkpoints but later showed intermittent compression instability | Held for comparison |
SDK 0.0.12 introduced the compressMode: 2 path that failed on the earlier
Even app and glasses combination. After the Even App and G2 firmware update,
the same compressed-image contract passed checkpoints through SDK 0.0.13,
but later intermittent behavior justified returning the active build to
0.0.11. The minimal
historical failure remains available on the unchanged
0.0.12-reproduce
branch for the Even Realities team.
Useful hardware records:
- First successful G2 image transfer
- SDK 0.0.11 transport checkpoint
- SDK 0.0.12 LZ4 experiment
- SDK 0.0.13 physical promotion gate
- 1-bit BMP versus PNG hardware gate
- Typed-array versus Base64 SDK bridge gate
- Fast blank display hardware gate
- Unchanged-tile skip experiment
- Current project readiness audit
- Phone companion completion audit
- Location, task, route, and cache data are stored through the Even local-storage bridge on the user's device.
- Requests to Open-Meteo, configured RSS providers, OpenStreetMap/Overpass, optional OpenRouteService, OpenAI, and approved MCP servers necessarily disclose request data to those services.
- OpenAI and ORS keys remain in Even local storage and scoped request headers; they are never bundled into the WebView, committed, logged, or persisted by Sandevistan's server routes.
- OpenStreetMap data is © OpenStreetMap contributors and available under the ODbL.
- Public endpoints are used conservatively for a personal, non-commercial prototype. This is not a hosted multi-user service.
- Neither the production blank-page display toggle nor its black-tile control is an official G2 sleep mode; the app and listeners continue running.
- Hardware timing varies with the phone, Even app, glasses state, and radio link.
Issues and focused pull requests are welcome. Before opening a change:
- Keep image transport bounded and fail-fast.
- Do not add a deferred refresh queue.
- Never bundle, commit, or log credentials; preserve device-local BYOK and server-environment fallback boundaries.
- Preserve the 576×288 and 288×144 transport boundaries.
- Run the complete serial verification suite above.
- Keep tracked Markdown in English.
The source code is available under the MIT License.
Sandevistan is an unofficial fan project. It is not affiliated with, endorsed by, or sponsored by CD PROJEKT RED, the Cyberpunk franchise, Even Realities, or their respective owners. “Cyberpunk 2077,” “Sandevistan,” “Even Realities,” and related names and marks belong to their respective owners. This repository includes no game logo, extracted game UI, or proprietary game asset.