A comprehensive UI framework and API for building gaze-based applications for Raven Prism. Take full advantage of the extensive sensor suite on Raven Prism including eye control, cameras, IMUs, microphones, and more. The framework features gaze-based interactions like buttons and scrolling with eyes, along with voice input, media handling, AI integration, and many more modern UI components—all built on Python for easy development.
If this is your first Raven application, check out the Raven Starter Project repository.
The framework is being developed by Raven Resonance, a team of engineers and designers who have built and used wearable computers for years. [Raven Prism 1] will be out soon and runs RavenOS, a Linux-based operating system designed for all-day wear. This repo contains a preview of Raven Framework and is the first part of the Raven SDK. We would love to hear your feedback in our Discord community!
version = "1.0.2"
- Installation
- Core App Components
- UI Widgets
- Peripherals
- Helpers
- Hardware Specifications
- Building Apps Without the Python Framework
- Designing for Raven OS
- Examples
- Building Apps with AI
- Python >=3.10
git clone https://github.com/RavenResonance/raven-framework.git
cd raven-framework
pip install -e .Note: You might need to use pip3 install -e . instead of pip install -e . depending on your system.
Note: Some components may have special installation requirements. See component documentation for details (e.g., Speaker requires audio-simulator optional dependency for simulator mode).
The standard required base class for all Raven applications. Provides the main application container where widgets are added.
from raven_framework.core.raven_app import RavenApp
class MyApp(RavenApp):
def __init__(self):
super().__init__()
self.app.add(button, x=0, y=10)The main entry point for running Raven applications. Provides application execution and deployment functionality.
from raven_framework.core.run_app import RunApp
if __name__ == "__main__":
RunApp.run(
lambda: MyApp(),
app_id="",
app_key=""
)Use python main.py (or python3 main.py) to run on desktop simulator, and python main.py deploy (or python3 main.py deploy) to run on Raven Prism. Make sure you input app ID and key for deployment; simulator can work without it.
Note: To close an app, use the home icon in the top right corner.
Note: All components inherit from PySide6's QWidget class, so standard Qt methods like hide(), show(), move(), resize(), etc. are still available and work as expected.
A base container widget to organize layout.
from raven_framework.components.container import ContainerSimple container:
container = Container()Container with fixed size:
container = Container(width=640, height=640)Container with spacing:
container = Container(spacing=10)Container with inner margins:
Uniform margin (all sides):
container = Container(inner_margin=20)Horizontal and vertical margin (horizontal, vertical):
container = Container(inner_margin=(30, 10))Individual margins (left, top, right, bottom):
container = Container(inner_margin=(20, 10, 20, 10))Adding widgets to container:
Simple adding (vertical stacking by default):
container = Container()
container.add(button)Adding with absolute positioning:
container = Container()
container.add(text_box, x=100, y=200)Frequently used params: background_color (str, hex code), background_image (str, path of image), corner_radius (int), border_width (int), border_color (str, hex code), width (int), height (int), inner_margin (int), spacing (int)
Frequently used methods: add(widget: QWidget (all UI components), x: int = None, y: int = None), clear()
See detailed params and functions in raven_framework/components/container.py
Note: Use is_main_container=True if this is the main container of your app. It will inherit system themes like borders, positioning, sizing, fonts, etc.
A vertical layout container with automatic widget arrangement.
from raven_framework.components.vertical_container import VerticalContainerSimple vertical container:
vbox = VerticalContainer()Container with fixed size:
vbox = VerticalContainer(width=640, height=480)Container with spacing:
vbox = VerticalContainer(spacing=10)Container with inner margins:
Uniform margin (all sides):
vbox = VerticalContainer(inner_margin=20)Horizontal and vertical margin (horizontal, vertical):
vbox = VerticalContainer(inner_margin=(30, 10))Individual margins (left, top, right, bottom):
vbox = VerticalContainer(inner_margin=(20, 10, 20, 10))Adding widgets to container:
Simple adding (vertical stacking):
vbox = VerticalContainer()
vbox.add(button1, button2, text_box)Frequently used params: background_color (str, hex code), background_image (str), corner_radius (int), border_width (int), border_color (str, hex code), width (int), height (int), inner_margin (Union[int, Tuple[int, int], Tuple[int, int, int, int]]), spacing (int)
Frequently used methods: add(*widgets: QWidget (all UI components)), clear()
See detailed params and functions in raven_framework/components/vertical_container.py
Note: Use is_main_container=True if this is the main container of your app. It will inherit system themes like borders, positioning, sizing, fonts, etc.
A horizontal layout container for arranging widgets side by side.
from raven_framework.components.horizontal_container import HorizontalContainerSimple horizontal container:
hbox = HorizontalContainer()Container with fixed size:
hbox = HorizontalContainer(width=640, height=100)Container with spacing:
hbox = HorizontalContainer(spacing=10)Container with inner margins:
Uniform margin (all sides):
hbox = HorizontalContainer(inner_margin=20)Horizontal and vertical margin (horizontal, vertical):
hbox = HorizontalContainer(inner_margin=(30, 10))Individual margins (left, top, right, bottom):
hbox = HorizontalContainer(inner_margin=(20, 10, 20, 10))Adding widgets to container:
Simple adding (horizontal stacking):
hbox = HorizontalContainer()
hbox.add(icon1, icon2, icon3)Frequently used params: background_color (str, hex code), background_image (str), corner_radius (int), border_width (int), border_color (str, hex code), width (int), height (int), inner_margin (Union[int, Tuple[int, int], Tuple[int, int, int, int]]), spacing (int)
Frequently used methods: add(*widgets: QWidget (all UI components)), clear()
See detailed params and functions in raven_framework/components/horizontal_container.py
Note: Use is_main_container=True if this is the main container of your app. It will inherit system themes like borders, positioning, sizing, fonts, etc.
A text display widget with customizable styling.
from raven_framework.components.text_box import TextBoxSimple text:
text = TextBox(text="Hello World")Custom aligned text:
text = TextBox(text="Hello World", width=400, alignment="left")text = TextBox(text="Hello World", width=400, alignment="center")text = TextBox(text="Hello World", width=400, alignment="right")Custom color and size text:
text = TextBox(text="Hello World", text_color="#FF0000", font_size=48)Using system fonts:
text = TextBox(text="Display Text", font_type="display")text = TextBox(text="Title Text", font_type="title")text = TextBox(text="Headline Text", font_type="headline")text = TextBox(text="Body Text", font_type="body")text = TextBox(text="Small Text", font_type="small")Note: By default, TextBox uses the body font from the theme (theme.fonts.body). When font_type is provided, it automatically applies the corresponding font's color, family, size, and weight from the theme. Individual parameters (text_color, font, font_size, font_weight) can still override the font_type values if explicitly provided.
Frequently used params: font_type (str, one of 'display', 'title', 'headline', 'body', 'small'), text_color (str, hex code), font_size (int), font_weight (str), alignment (str), wrap_words (bool), width (int), height (int)
Frequently used methods: set_text(new_text: str)
See detailed params and functions in raven_framework/components/text_box.py
A customizable button widget with dwell-to-click functionality and scaling animations.
from raven_framework.components.button import ButtonSimple button:
button = Button(center_text="Click Me")Note: Buttons automatically adjust their width and height based on the text content inside. Only specify width and height parameters if you absolutely need a fixed size.
Button with custom size:
button = Button(center_text="Click Me", width=150, height=60)Button with custom colors and styling:
button = Button(center_text="Click Me", background_color="#FF0000", corner_radius=10)Button with icon:
button = Button(
center_text="Click Me",
icon_path="assets/icon.png",
)Button with action icon:
button = Button(
center_text="Click Me",
show_action_icon=True,
width=400,
)Button with icon and action icon:
button = Button(
center_text="Click Me",
icon_path="assets/icon.png",
show_action_icon=True,
width=400,
)Button click handlers:
Simple button with click handler (no params):
self.button = Button(center_text="Click Me")
self.button.on_clicked(self.on_button_click)
def on_button_click(self):
self.button.set_text("Clicked!")Button with click handler (with params):
self.button = Button(center_text="Click Me")
self.button.on_clicked(self.on_button_click, "New Text")
def on_button_click(self, new_text):
self.button.set_text(new_text)Frequently used params: width (int), height (int), background_color (str, hex code), text_size (int), text_color (str, hex code), font_weight (str), corner_radius (int), outline_width (int), outline_color (str, hex code), dwell_time (int), icon_path (str), disabled (bool)
Frequently used methods: set_text(new_text: str), on_clicked(callback, *args, **kwargs), set_disabled(disabled: bool), set_enabled(enabled: bool), is_disabled() -> bool
See detailed params and functions in raven_framework/components/button.py
A circular or rounded-rect icon with dwell-click interaction and optional background image.
from raven_framework.components.icon import IconSimple icon:
icon = Icon(background_image_path="icon.png")Icon with custom size (diameter):
icon = Icon(background_image_path="icon.png", size=150)Icon click handlers:
Simple icon with click handler (no params):
self.icon = Icon(size=80)
self.icon.on_clicked(self.on_icon_click)
def on_icon_click(self):
self.icon.set_text("Clicked!")Icon with click handler (with params):
self.icon = Icon(size=80)
self.icon.on_clicked(self.on_icon_click, "New Text")
def on_icon_click(self, new_text):
self.icon.set_text(new_text)Frequently used params: background_image_path (str), size (int), background_color (str, hex code), center_text (str), text_size (int), text_color (str, hex code), corner_radius (int), outline_width (int), outline_color (str, hex code), dwell_time (int), is_square (bool), enable_click (bool), bottom_text (str), disabled (bool)
Frequently used methods: set_text(new_text: str), on_clicked(callback, *args, **kwargs), set_background_image(image_path: str), set_disabled(disabled: bool), set_enabled(enabled: bool), is_disabled() -> bool
See detailed params and functions in raven_framework/components/icon.py
A simple spacer widget for adding empty space in layouts.
from raven_framework.components.spacer import SpacerVertical spacer:
spacer = Spacer(height=20)Horizontal spacer:
spacer = Spacer(width=50)Frequently used params: width (int), height (int)
See detailed params and functions in raven_framework/components/spacer.py
Displays images, GIFs, or videos with rounded corners and playback controls.
from raven_framework.components.media_viewer import MediaViewerSimple media viewer with image:
viewer = MediaViewer(media_path="assets/image.jpg")Simple media viewer with GIF:
viewer = MediaViewer(media_path="assets/animation.gif")Simple media viewer with video:
viewer = MediaViewer(media_path="assets/video.mp4")Media viewer with image, size and corner radius:
viewer = MediaViewer(media_path="assets/image.jpg", width=400, height=400, corner_radius=10)Media viewer with video, looping and controls:
viewer = MediaViewer(media_path="assets/video.mp4", loop_video=True)
viewer.play_video()
viewer.pause_video()Frequently used params: media_path (str), corner_radius (int), width (int), height (int), loop_video (bool), scale_mode (str: "cover" or "fit")
Frequently used methods: play_video(), pause_video()
Note: width and height must be multiples of 4. If you pass other values (e.g. 385×385), the viewer will adjust them to the nearest multiple of 4 (e.g. 384×384) and log a warning.
See detailed params and functions in raven_framework/components/media_viewer.py
Displays web content.
from raven_framework.components.web_viewer import WebViewerSimple web viewer:
web = WebViewer(url="https://example.com")Web viewer with custom size:
web = WebViewer(url="https://example.com", width=300, height=200)Frequently used params: url (str), width (int), height (int)
See detailed params and functions in raven_framework/components/web_viewer.py
A scrollable widget with gaze-based dwell scrolling and auto-scroll support.
from raven_framework.components.scroll_view import ScrollViewScroll view example:
vbox = VerticalContainer(width=480, inner_margin=30)
for i in range(20):
vbox.add(TextBox(f"This is line {i}."))
scroll = ScrollView(content_widget=vbox, width=480, height=720)Scroll view with continuous scroll:
vbox = VerticalContainer(width=480, inner_margin=30)
for i in range(20):
vbox.add(TextBox(f"This is line {i}."))
scroll = ScrollView(content_widget=vbox, width=480, height=540, enable_continuous_scroll=True)Frequently used params: content_widget (QWidget (all ui components)), width (int), height (int), enable_continuous_scroll (bool)
Frequently used methods: scroll_next(), scroll_prev(), start_auto_scroll, stop_auto_scroll(), clear()
See detailed params and functions in raven_framework/components/scroll_view.py
Displays 3D models from OBJ files with OpenGL rendering.
from raven_framework.components.model_viewer import ModelViewer
viewer = ModelViewer(model_path="assets/model.obj", width=400, height=400)Note: Raven Prism only supports OpenGL ES 2.0, not Vulkan or OpenGL ES 3.x. The ModelViewer automatically uses the appropriate OpenGL context based on the platform.
Frequently used params: model_path (str), width (int), height (int)
See detailed params and functions in raven_framework/components/model_viewer.py
Reusable card components with various layouts and button configurations.
Card with text content and a single button.
from raven_framework.cards import TextCardWithButton
card = TextCardWithButton()Frequently used params:
text(str): Text content to displaycontainer_width(int): Width of the card containerbutton_text(str): Text for the buttonon_button_click(Callable): Optional callback function for button click
See detailed params and functions in raven_framework/cards.py
Card with text content and two buttons.
from raven_framework.cards import TextCardWithTwoButtons
card = TextCardWithTwoButtons()Frequently used params:
text(str): Text content to displaycontainer_width(int): Width of the card containerbutton_text_1(str): Text for the first buttonbutton_text_2(str): Text for the second buttonon_button_1_click(Callable): Optional callback function for first button clickon_button_2_click(Callable): Optional callback function for second button click
See detailed params and functions in raven_framework/cards.py
Horizontal card with text and a button.
from raven_framework.cards import HorizontalTextCardWithButton
card = HorizontalTextCardWithButton()Frequently used params:
text(str): Text content to displaycontainer_width(int): Width of the card containerbutton_text(str): Text for the buttonon_button_click(Callable): Optional callback function for button click
See detailed params and functions in raven_framework/cards.py
Horizontal card with text only (no button).
from raven_framework.cards import HorizontalTextCard
card = HorizontalTextCard()Frequently used params:
text(str): Text content to displaycontainer_width(int): Width of the card containertext_alignment(str): Text alignment
See detailed params and functions in raven_framework/cards.py
Card with media viewer, title, subtitle, and body text (no button).
from raven_framework.cards import MediaCard
card = MediaCard(image_path="assets/image.png")Frequently used params:
title_text(str): Title textsubtitle_text(str): Subtitle textbody_text(str): Body textimage_path(str): Path to the imageimage_height(int): Height of the imagecontainer_width(int): Width of the card container
See detailed params and functions in raven_framework/cards.py
Card with media viewer, title, subtitle, body text, and a single button.
from raven_framework.cards import MediaCardWithButton
card = MediaCardWithButton(image_path="assets/image.png")Frequently used params:
title_text(str): Title textsubtitle_text(str): Subtitle textbody_text(str): Body textbutton_text(str): Text for the buttonimage_path(str): Path to the imageimage_height(int): Height of the imagecontainer_width(int): Width of the card containeron_button_click(Callable): Optional callback function for button click
See detailed params and functions in raven_framework/cards.py
Card with media viewer, title, subtitle, body text, and two buttons.
from raven_framework.cards import MediaCardWithTwoButtons
card = MediaCardWithTwoButtons(image_path="assets/image.png")Frequently used params:
title_text(str): Title textsubtitle_text(str): Subtitle textbody_text(str): Body textbutton_text_1(str): Text for the first buttonbutton_text_2(str): Text for the second buttonimage_path(str): Path to the imageimage_height(int): Height of the imagecontainer_width(int): Width of the card containeron_button_1_click(Callable): Optional callback function for first button clickon_button_2_click(Callable): Optional callback function for second button click
See detailed params and functions in raven_framework/cards.py
Card with a scrollable list of items, each with a button.
from raven_framework.cards import ScrollableListCard
card = ScrollableListCard()Frequently used params:
title_text(str): Title textinfo_strings(List[str]): List of strings to displaybutton_strings(List[str]): List of button textscard_width(int): Width of the card containercard_height(int): Height of the card containeron_item_click(List[Tuple[Callable, ...]]): Optional callback for item button clicks
See detailed params and functions in raven_framework/cards.py
Note: All sensors require special entitlement from developer site for publishing apps in the future, but not for development apps. All sensors accept optional app_id (str) and app_key (str) parameters for entitlement verification.
Camera sensor for capturing images and video.
from raven_framework.peripherals.camera import Camera
camera = Camera()Open camera:
camera.open_camera()Capture image:
frame = camera.capture_camera_image()Close camera:
camera.close_camera()Frequently used methods:
open_camera() -> VideoCapture | None: Open camera and return VideoCapture objectcapture_camera_image() -> ndarray | None: Capture image frame from cameraclose_camera() -> None: Close camera connection
See detailed params and functions in raven_framework/peripherals/camera.py
Microphone sensor for audio recording with level detection.
from raven_framework.peripherals.microphone import Microphone
mic = Microphone()Start recording:
mic.start_recording()Stop recording:
wav_bytes = mic.stop_recording()Frequently used methods:
start_recording() -> None: Start audio recordingstop_recording() -> bytes: Stop recording and return WAV bytesget_level() -> float: Get current audio level (0.0 to 1.0)
See detailed params and functions in raven_framework/peripherals/microphone.py
IMU (Inertial Measurement Unit) sensor for reading accelerometer, gyroscope, and magnetometer data. Note: In simulator mode, arrow keys can be used to simulate accelerometer readings (Up/Down for Y-axis, Left/Right for X-axis).
from raven_framework.peripherals.imu import IMU
imu = IMU()Get reading:
reading = imu.get_reading()
if reading:
accel = reading.get("accelerometer")
gyro = reading.get("gyroscope")Frequently used methods:
get_reading() -> dict | None: Get IMU reading with accelerometer, gyroscope, and magnetometer data
See detailed params and functions in raven_framework/peripherals/imu.py
Gaze position input for Raven Prism. Note: Cannot be simulated in simulator mode.
from raven_framework.peripherals.eye_control import EyeControl
eye = EyeControl()Get gaze position:
position = eye.get_gaze_position()
if position:
x, y = positionFrequently used methods:
get_gaze_position() -> Tuple[int, int] | None: Get current gaze position as (x, y) coordinates
See detailed params and functions in raven_framework/peripherals/eye_control.py
Speaker for asynchronous playback of WAV audio bytes.
Note: In simulator mode, audio playback requires the audio-simulator optional dependency. Install it with pip install -e ".[audio-simulator]" or pip install simpleaudio. Note that simpleaudio may not have pre-built binaries available for all Linux and Windows systems, which can cause installation to fail. If simpleaudio is not available, the framework will log a warning and audio playback will not work in simulator mode (but will still work on Raven devices).
from raven_framework.peripherals.speaker import Speaker
speaker = Speaker()Play audio:
speaker.play_audio(wav_bytes, on_finished=callback)Stop audio:
speaker.stop_audio()Frequently used methods:
play_audio(wav_bytes: bytes, on_finished: Callable | None = None) -> None: Play WAV audio bytes asynchronouslystop_audio() -> None: Stop audio playback
See detailed params and functions in raven_framework/peripherals/speaker.py
Physical button sensor for reading button state and waiting for button presses. Note: Cannot be simulated in simulator mode.
from raven_framework.peripherals.click_button import ClickButton
button = ClickButton()Check if pressed:
if button.is_pressed():
print("Button is pressed")Wait for press:
pressed = button.wait_for_press(timeout=5.0)Frequently used methods:
is_pressed() -> bool: Check if button is currently pressedwait_for_press(timeout: float = 5.0) -> bool: Wait for button press with timeout
See detailed params and functions in raven_framework/peripherals/click_button.py
Note: Additional peripheral support, including spatial microphone and sound processing, and enhanced click button controls, will be added in future releases of the framework.
Timer-based task execution for periodic or delayed execution.
from raven_framework.helpers.routine import RoutineDelay routine:
self.delay = Routine(interval_ms=5000, invoke=self.on_done, mode="delay")
def on_done(self):
print("Done")Periodic routine:
self.routine = Routine(interval_ms=1000, invoke=self.on_tick, mode="repeat")
def on_tick(self):
print("Tick")Stop routine:
self.routine.stop()Frequently used params:
interval_ms(int): Time interval in millisecondsinvoke(Callable): Function to call on timer timeoutmode(str): "repeat" for periodic calls or "delay" for single shotparent(QObject): Optional Qt parent object
Frequently used methods:
stop() -> None: Stop the routine timer
See detailed params and functions in raven_framework/helpers/routine.py
Simple animation utility functions for fading widgets in and out. Note: Call these functions at the end of __init__ for best results.
from raven_framework.helpers.animation_utils import fade_in, fade_outFade in:
fade_in(my_widget)Fade out:
fade_out(my_widget)Fade in with custom parameters:
fade_in(my_widget, duration=750)Frequently used params:
widget(QWidget (all UI components)): The widget to animatestart_value(float): Starting opacity (0.0 to 1.0)end_value(float): Ending opacity (0.0 to 1.0)duration(int): Animation duration in milliseconds
Frequently used methods:
fade_in(widget: QWidget (all UI components), start_value: float = 0.0, end_value: float = 1.0, duration: int = 750) -> None: Fade in a widget from transparent to opaquefade_out(widget: QWidget (all UI components), start_value: float = 1.0, end_value: float = 0.0, duration: int = 750) -> None: Fade out a widget from opaque to transparent
See detailed params and functions in raven_framework/helpers/animation_utils.py
Asynchronous task runner using Qt's thread pool.
from raven_framework.helpers.async_runner import AsyncRunner
runner = AsyncRunner()Run task:
runner.run(long_task, on_complete=callback)Important: Do not update UI components (like buttons or text boxes) directly from background threads. Always update UI components in the on_complete callback, which runs on the main thread. Updating UI from separate threads can cause crashes or undefined behavior.
Frequently used methods:
run(func: Callable, on_complete: Callable | None = None) -> None: Execute a function asynchronously in a background thread
See detailed params and functions in raven_framework/helpers/async_runner.py
Helper class for OpenAI API integration.
from raven_framework.helpers.open_ai_helper import OpenAiHelper
openai = OpenAiHelper(open_ai_key="my_open_ai_key")Get text response:
response = openai.get_text_response("Hello, how are you?")Transcribe audio:
text = openai.transcribe_audio(wav_bytes)Get image response:
response = openai.process_multimodal_with_image("What's in this image?", image_frame)Text to speech:
audio_bytes = openai.generate_tts("Hello world", voice="alloy")Using with Camera:
from raven_framework.peripherals.camera import Camera
from raven_framework.helpers.open_ai_helper import OpenAiHelper
camera = Camera()
camera.open_camera()
frame = camera.capture_camera_image()
camera.close_camera()
openai = OpenAiHelper(open_ai_key="my_open_ai_key")
response = openai.process_multimodal_with_image("What's in this image?", frame)Using with Microphone and TextBox:
from raven_framework.peripherals.microphone import Microphone
from raven_framework.components.text_box import TextBox
from raven_framework.helpers.open_ai_helper import OpenAiHelper
mic = Microphone()
mic.start_recording()
# ... wait for recording ...
wav_bytes = mic.stop_recording()
openai = OpenAiHelper(open_ai_key="my_open_ai_key")
transcription = openai.transcribe_audio(wav_bytes)
response = openai.get_text_response(f"Respond to this: {transcription}")
text_box = TextBox(text=response)Using with Speaker:
from raven_framework.peripherals.speaker import Speaker
from raven_framework.helpers.open_ai_helper import OpenAiHelper
openai = OpenAiHelper(open_ai_key="my_open_ai_key")
audio_bytes = openai.generate_tts("Hello, this is a test", voice="alloy")
speaker = Speaker()
speaker.play_audio(audio_bytes)Frequently used params:
open_ai_key(str): API key for OpenAI
Frequently used methods:
transcribe_audio(wav_bytes: bytes, model: str = "whisper-1", audio_filename: str = "audio.wav", audio_mime_type: str = "audio/wav") -> str: Transcribe audio bytes using Whisper modelget_text_response(prompt: str, model: str = "gpt-4o") -> str: Get a text completion from GPT based on a promptprocess_multimodal_with_image(prompt: str, image: ndarray, model: str = "gpt-4o") -> str: Send a multimodal prompt including text and an image to GPTgenerate_tts(text: str, model: str = "tts-1", voice: str = "alloy", response_format: str = "wav") -> bytes: Generate speech audio from text using TTS model
See detailed params and functions in raven_framework/helpers/open_ai_helper.py
Raven Prism v1 hardware specifications:
- Operating System: RavenOS (Linux-based)
- Processor: Quad-core 64-bit ARM processor
- Graphics: GPU with OpenGL ES 2.0 support
- Display: 30 degree diagonal FoV, full-color waveguide display on the right eye
- Primary Input: Eye control sensors
- Connectivity: WiFi & Bluetooth
- Audio Input: Multiple microphones
- Audio Output: 2 downward-facing speakers
- Camera: World-facing camera
- Motion Sensors: IMU
- Power: Raven Wings™ hot-swappable batteries
- Indicators: Beakon™ lights
- Environmental Sensors: Ambient light and proximity sensors
Raven Prism runs RavenOS (which is based on Linux), so you can run essentially any ARM64 Linux program/runtime (Go, Rust, Node, C/C++, etc.)—you are not limited to this Python framework. The platform has a default runtime entrypoint at core/run.sh. By default it runs python3 main.py (or python3 main.pyc if present). If your app provides its own run.sh, that will override the default. Before choosing a stack, review the Hardware Specifications and note the display is 720×720 (see Designing for Raven OS).
Note: Additional support will be added to access glasses peripherals via Unix sockets. Like this SDK, all sockets will require special entitlement from the developer site for publishing, but not for development apps.
Raven OS is built for display glasses that prioritize comfort, presence, and real world awareness. It supports the user without replacing their environment, using calm, peripheral, and intentional UI.
These guidelines outline how to design interfaces that feel natural, unobtrusive, and aligned with Raven's optical and interaction constraints.
Note: This is very early stage, and we are continuously researching as hardware gets into more people's hands. We strongly suggest using our framework items like buttons and scroll bars, as we plan on updating them based on user feedback and research findings.
Raven OS exists to bring users back to the real world.
- UI should feel ambient, optional, and calm
- Urgency should be rare and intentional
- Reduce eye strain and cognitive load
If the UI feels distracting, it's failing.
Design for the periphery by default. Move content to central focus only when the user intentionally engages.
- Resolution: 720 × 720 LCOS
- Field of View: 30° diagonal
- Offset: Right‑side
The right‑side offset reduces distraction, preserves central vision, and improves long‑term comfort. Designs should assume asymmetry and avoid centering UI for visual balance alone.
Raven uses a waveguide-based additive display. Additive blending means that light from the display is added to the light from the real world. The waveguide projects light into the user's eye, which combines with ambient light from the environment. This means:
- Light from the display adds to real-world light (additive blending)
- White and saturated colors provide the strongest contrast against real world backgrounds
- Dark backgrounds with white or light gray text provide better contrast and readability
- Apply accent colors sparingly to preserve contrast and readability
- Never rely on color alone for meaning
- Black gets completely vanished no matter what — pure black cannot be displayed on an additive display
- Though you can use it for occlusion and showing depth. For example, the background of buttons by default is black so it occludes the content behind it
- White will look best unless seen on top of white background — white text/UI elements work well against dark backgrounds
- All of this is dependent on display brightness
Note: Additive display behavior and color rendering are very complex topics. This is a simplified explanation to help guide design decisions. Actual color appearance depends on many factors including ambient lighting, display brightness, waveguide properties, and user perception.
The desktop simulator approximates how colors will appear on the actual waveguide display, making it useful for color testing during development.
Raven provides an optimized system font scale. We suggest a visual angle range of 0.8° to 1.2°, and Title, Headline, and Body fall within this range.
For Raven Prism (720×720 px display with 30° diagonal FOV), these translate to the following pixel values:
- Title - 38px (1.12° visual angle)
- Headline - 33px (0.97° visual angle)
- Body - 28px (0.83° visual angle)
Use these only if absolutely necessary:
- Display - 45px (1.33° visual angle) - use sparingly
- Small - 18px (0.53° visual angle) - use sparingly
Rules:
- Prefer using system fonts only
- Avoid custom fonts, especially on buttons
- Use Display and Small fonts only when necessary
- Don't stack multiple text sizes in tight areas
See Text Box for how to use these font types in your application.
Layout is based on attention, not symmetry.
Central
- Reading and focus‑heavy content
Peripheral
- Persistent background content (recipes, directions, reference content)
- Buttons and interactive controls
- Elements not triggered by users, such as notifications
- Elements that remain visible without demanding focus
Guidelines:
- Place interactive elements primarily on the right side
- Avoid controls in primary reading areas
- Assume accidental gaze is common
- Users tend to look at bottom center most frequently. For rarely clicked items or critical actions (like going to home, scroll pagination) that need to be interacted with very intentionally, place them in the top right or right periphery to avoid accidental activation
Eye Control is the default mode of interaction for Raven Prism. It provides around ~2–3° accuracy (subject to change as hardware testing progresses). Use large targets, avoid dense layouts, and rely on framework‑provided controls.
Raven OS focuses on hands‑free input methods. For pointing, smooth gaze is used and interactive elements like buttons and icons scale. For clicking, we are prioritizing multiple methods.
This is how buttons work in the framework:
- Dwell‑to‑click (default) — gaze at a button for a set duration to activate
- Double‑blink (default, evolving) — double blink to activate focused elements
For getting long responses, you can use voice input with the microphone. Future input solutions are being explored for typing on Raven Prism.
As a Linux‑based system, Raven supports third‑party Bluetooth HID devices (mouse, keyboard, rings, bands, accessibility tools). Interfaces must remain input‑agnostic.
Traditional scrolling is discouraged due to eye fatigue and attention shifts, though it may sometimes be needed (for example, in a news app with multiple headlines to quickly glance at). Use scroll view when scrolling is necessary.
Raven supports pagination and continuous scrolling, but pagination is recommended. It minimizes eye movement and interaction cost. Auto‑scroll may work for passive content, but requires sustained attention on moving content and can reduce comfort.
For complete, ready-to-run example applications, check out the Raven Starter Projects repository.
The starter projects include:
- Hello World - A simple app displaying "Hello, World!" text
- Counter - A stopwatch app with start, pause, resume, and reset functionality using cards and routines
- Simple AI App - An AI-powered app that uses camera, microphone, and speaker with OpenAI integration
- Art Studio - A painting reference viewer app with scrollable list and media viewer
All examples include full source code and can be run immediately after installing the framework.
The Raven Framework repository includes an AGENTS.md file that contains condensed documentation optimized for AI assistants. Coding tools like Cursor and Copilot should automatically see this as a README and use it for context. You can also copy this file and provide it to AI assistants (like ChatGPT, Claude, or Gemini) to help you build Raven applications. The AI will have all the framework information it needs to generate code and answer questions about components, sensors, and utilities. Learn more about AGENTS.md.
This project is proprietary software. The Raven Framework code and documentation are proprietary and may not be redistributed, modified, or used except as expressly permitted by RavenResonance. Do not push the Raven Framework code to public repositories or distribute it without authorization.










