CASOON Open Source
Desktop apps that stop reinventing the platform.
Origin is a reference architecture and starter system for modular desktop applications in Rust and Tauri: architecture rules, reusable platform crates, security conventions and build processes, plus a reference application that demonstrates all of it.
cargo add origin-app origin-tauripnpm add @casoon/origin-client @casoon/origin-uigit clone https://github.com/casoon/origin{
"$schema": "../gen/schemas/desktop-schema.json",
"identifier": "standard-dashboard",
"description": "Main window: reads application state and receives platform events. No filesystem, no shell, no process execution. Generated from app.toml — do not edit.",
"windows": [
"main"
],
"permissions": [
"core:default",
"core:event:allow-listen",
"core:event:allow-unlisten"
]
}- crates on crates.io, all at 0.2.0
- 29
- binding rules in ARCHITECTURE.md
- 15
- architecture decision records
- 31
- named security profiles instead of permission lists
- 4
What it does
Domain code does not know Tauri exists
Tauri is the desktop host. The application is a set of Rust components that depend on traits, not on an AppHandle, and the whole of it is testable without starting Tauri.
Least privilege, checked by the build
Each window gets a named security profile. Notifications and URL opening happen in Rust, so the frontend needs no permission for either, and cargo xtask validate fails on a blanket fs:* or shell:* grant.
OAuth and sync that do not cut corners
PKCE always, state verified before the code is used, a loopback redirect and single-flight refresh. The sync engine owns scheduling: retry, backoff with jitter, offline handling.
Contracts generated, not mirrored
Capability files come from app.toml and IPC types from their Rust definitions. A rename in Rust fails CI instead of surfacing as undefined in production.
Bring your own AI client
MCP makes the application controllable by the AI the user already has, with a permission level of its own that defaults to read and propose.
Generated at build time
All examples →// Generated from PulseSnapshot in src-tauri/src/pulse.rs. Do not edit.
import type { Alert, Health, Metric } from "@casoon/origin-client";
export type PulseSnapshot = { health: Health, metric: Metric | null, alerts: Array<Alert>, };Derived from the Rust struct PulseSnapshot with ts-rs. The demo's test suite fails when this checked-in file drifts from the declaration.
examples/demo/src/pulse.generated.tsQuickstart
Run the reference application: a tray app with a background loop, cached read model, typed events, native notifications and a Svelte 5 frontend that never calls invoke directly.
- Install Rust 1.88+, Node 22+, pnpm 10+ and the Tauri CLI.
- Clone the repository and run
pnpm install. - Start the demo with
cargo xtask demo, then read its composition root.
git clone https://github.com/casoon/origin
cd origin
pnpm install
cargo xtask demolet application = ApplicationBuilder::in_memory()
.clock(Arc::new(FakeClock::new(now)))
.notifications(Arc::new(RecordingNotificationService::new()))
.module(PulseModule)
.build()?;