Lantern is a local-first projection-appliance prototype built around a Raspberry Pi 4, a Dell M110 projector, and an MPU-6050 inertial sensor. It provides a fullscreen projector view and a phone-friendly control UI. The intended behavior is to blank the projection while the lamp moves, then select a channel for a calibrated desk, wall, or ceiling pose after the device settles.
This is an independent Linux/web implementation inspired by Nord Projects' Android Things Lantern. Nord Projects' original used Android Things and Kotlin, an Android companion app, Nearby Connections, a laser projector, and its own mechanical design.
This repository instead uses Raspberry Pi OS, FastAPI/Python, Svelte/TypeScript, WebSockets, Cage, and Chromium. It does not contain the original project's Kotlin applications, companion app, or CAD files, and it is not an official Nord Projects project. The shared concept is a movable projector whose orientation selects surface-specific content.
The original project is Apache-2.0 licensed. This independent implementation is intentionally being prepared without a license for now; default copyright restrictions therefore apply. If reuse or contributions should be permitted later, add an explicit license then. Manually confirm that the attribution and independence statement above accurately describes how the code was developed before publication.
Implemented and locally tested/simulated
- FastAPI state and health APIs
- Svelte projector and control routes
- WebSocket state updates
- immediate blanking and delayed simulated pose selection
- clock, status, and calibration channels
- persistent per-surface channel assignments
- MPU-6050 register decoding and live telemetry
Tested on the prototype hardware
- Raspberry Pi 4 running Raspberry Pi OS Lite
- Dell M110 at its detected 1280×800 mode
- Cage/Chromium fullscreen startup through systemd
- boot startup and backend restart after a forced failure
- MPU-6050 detection at I²C bus 1, address
0x68, with live accelerometer and gyroscope telemetry
Incomplete / TODO
- calibrating physical desk, wall, and ceiling gravity vectors
- automatic motion detection and IMU-driven pose/channel switching
- measured motion thresholds, confidence, and hysteresis
- proven fail-safe blanking for stale or failed sensor data
- complete cursor suppression on the projected output
- final arm/enclosure integration and long-duration reliability testing
- publishable CAD/mechanical drawings (none were found in the existing project)
software/— backend, frontend, tests, dependency locks, scripts, and service templateshardware/— verified wiring and prototype BOM; CAD is currently a TODOdocs/— architecture, setup, development notes, and publication checklistassets/— safe screenshots captured from the prototype UI
Requirements: Python 3.11 or newer, uv, Node.js 22.12 or newer (required by the current Vitest dev dependency), and npm.
cd software
cp config/lantern.example.yaml config/lantern.yaml
uv sync --dev
npm --prefix frontend ci
npm --prefix frontend run build
uv run uvicorn lantern.main:app --app-dir backend --host 127.0.0.1 --port 8000Open:
- projector UI: http://127.0.0.1:8000/display
- control UI: http://127.0.0.1:8000/control
- health endpoint: http://127.0.0.1:8000/api/health
See docs/setup.md for Raspberry Pi and I²C prerequisites and docs/development.md for verification commands.
Power the Raspberry Pi off before changing I²C wiring. The included thresholds are prototype defaults, not calibrated values. Until sensor-driven failure behavior is implemented and tested, do not assume that a running process guarantees a safely blanked projection.
