Oriel is an open-source native macOS app for placing lightweight HTML, CSS, and JavaScript widgets directly on the desktop.
It is local-first: no Electron, account, telemetry, marketplace, cloud service, shell execution, or unrestricted widget filesystem access.
- renders every widget in an isolated non-persistent
WKWebView; - keeps widgets behind normal windows, supports multiple displays and explicit edit mode;
- saves each instance's position, size, enabled state, and configuration locally;
- previews and edits package-contained HTML/CSS/JS from the app;
- reloads changed widget files through FSEvents;
- denies network by default, then asks for consent for exact declared domains;
- supports local folders and signed directory packages;
- includes a CLI, JSON Schema, TypeScript declarations, and curated built-in widgets.
- Swift 6, SwiftUI, AppKit, and WebKit;
- Foundation-only domain core;
- Swift Package Manager for tests and command-line tooling;
- Xcode project for the distributable sandboxed app.
Oriel targets macOS 14+ on Apple Silicon. Intel support is not intentionally excluded but is not yet tested.
DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer swift build
DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer swift test
Scripts/build-app.sh Debug
open Artifacts/Oriel-Debug.appScripts/build-app.sh Release creates a hardened-runtime bundle. A Developer ID identity and Apple notarization profile are required only for a distributable release.
Open Oriel Settings from the menu bar.
- Discover adds another instance of an included template.
- Your widgets lists the instances currently on your desktop. Enable/disable them there, then preview, configure, edit source, or add another instance.
- Press + or use Install Widget… to import a local widget folder or package. Oriel displays its author, exact requested domains, and signature state before installation.
- Use Edit Widget Positions from the menu bar to move and resize desktop widgets.
Oriel does not download community widgets automatically. This is deliberate: a community widget must be inspected and installed explicitly.
DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer swift run oriel create hello-widget
DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer swift run oriel validate hello-widget
DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer swift run oriel preview hello-widgetThe minimum package is a folder containing widget.json and index.html:
hello-widget/
├── widget.json
└── index.html
{
"$schema": "https://oriel.invalid/widget.schema.json",
"formatVersion": 2,
"id": "org.example.hello",
"name": "Hello",
"version": "1.0.0",
"entrypoint": "index.html",
"defaultSize": { "width": 280, "height": 100 },
"permissions": [],
"minimumOrielVersion": "0.2.0"
}<!doctype html>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<style>
:root { color-scheme: light dark; font: 16px system-ui; }
body { margin: 0; background: transparent; color: CanvasText; }
</style>
<p>Hello from Oriel.</p>Widgets receive read-only context through window.oriel: theme, locale, time zone, screen information, configuration, and bounded host data. window.glint remains as a compatibility alias for older packages. No native shell, secret, unrestricted filesystem, or arbitrary message bridge is exposed.
To request network access, declare exact hosts; Oriel still blocks them until the user approves them:
"permissions": [
{ "type": "network", "allowedDomains": ["api.example.org"] }
]The JSON Schema and TypeScript declarations are in WidgetSDK/.
Keep changes small, add deterministic tests for core behavior, and run the build/test commands above. Do not commit credentials, private media, proprietary assets, or build artifacts. Before publishing, run:
zsh Scripts/audit-public-tree.sh
git status --short