I love the idea of subscription and warranty trackers. But the irony of paying a monthly cloud subscription just to track my other subscriptions—while handing over my personal financial data—always bothered me.
I wanted a "Life Ops" command center that was completely local, ridiculously fast, and actually respected my privacy.
So, I built OpenAdmin. It’s an open-source, local-first dashboard built with Tauri, React, and Rust. It features an embedded SQLite database, a beautiful Glassmorphism UI, and—the coolest part—completely offline receipt OCR via WebAssembly.
Here is a breakdown of how I built it and the technical decisions behind it.
The Architecture: Why Tauri?
For a long time, Electron was the default for web-tech desktop apps. But for a simple dashboard, shipping a bundled Chromium browser that eats 500MB of RAM was out of the question.
I chose Tauri v2 because it hooks into the native OS webview (WebKit on Mac, WebView2 on Windows), resulting in:
- A tiny binary size.
- Negligible RAM usage.
- A blazing-fast backend written in Rust.
The architecture is simple:
- Frontend: React + TypeScript + Vanilla CSS (for that sweet custom glassmorphism).
- Backend: Rust.
-
Database: Local SQLite (
rusqlite) embedded directly into the app.
The Challenge: Offline OCR
The standout feature of OpenAdmin is the ability to drag and drop a receipt, have the app scan it, and automatically extract the "Total Cost" and raw text without ever making a network request to an API like Google Cloud Vision or AWS Textract.
To achieve this entirely offline, I used Tesseract.js.
Despite the .js in the name, Tesseract.js is actually a WebAssembly (WASM) port of the famous C++ Tesseract OCR engine. It runs directly inside the Tauri Webview thread.
How the implementation works:
-
The Dropzone: A React component listens for the
onDropevent when a user drops an image file. - The Worker: We spin up a Tesseract WebAssembly worker.
import Tesseract from 'tesseract.js';
const performOCR = async (file: File) => {
// Runs 100% locally in the browser/webview via WASM
const { data: { text } } = await Tesseract.recognize(file, 'eng');
return text;
};
- The Regex Extraction: Once we have the raw text blob, we run a regular expression to intelligently hunt for the final total cost, looking for keywords like "Total" followed by a currency symbol.
const match = text.match(/(?:Total|Amount|Sum)[\s:]*?\$?\s*([0-9,]+\.[0-9]{2})/i);
if (match) {
const extractedCost = parseFloat(match[1].replace(/,/g, ''));
}
Because this runs entirely client-side, it costs $0 in API fees and your receipt data never leaves your hard drive.
Rust Backend: SQLite & Native Notifications
While the frontend handles the UX and WASM, Rust does the heavy lifting for persistence and system-level integrations.
I used the rusqlite crate to automatically initialize a local .db file in the user's hidden app data directory. We use Tauri's #[tauri::command] macro to expose database operations to the React frontend.
But we didn't stop at just CRUD operations. We wanted the app to actively alert you when a warranty or subscription was about to expire.
We spawned a background Rust thread during Tauri setup that wakes up periodically, queries the SQLite database for items expiring within 7 days, and uses tauri-plugin-notification to trigger a native Mac OS push notification.
tauri::async_runtime::spawn(async move {
loop {
// Query SQLite for expiring items
if let Some(item) = get_expiring_item(&db) {
// Trigger native OS notification
app_handle.notification()
.title("Warranty Expiring!")
.body(&format!("Your {} is expiring soon.", item.name))
.show()
.unwrap();
}
tokio::time::sleep(Duration::from_secs(86400)).await; // Sleep for a day
}
});
The Result
The end result is OpenAdmin: a lightning-fast, highly secure, zero-telemetry desktop application that solves a real-world problem without sacrificing user privacy.
Building with Tauri + Rust forces you to think carefully about where your data lives and how it moves, and WebAssembly is proving to be a superpower for bringing complex server-side capabilities (like OCR) directly to the edge.
Check it out!
If you're interested in local-first apps, Rust, or just want a cool dashboard to track your own subscriptions without giving away your data, check out the source code!
I'd love to hear your thoughts, feedback, or any Pull Requests!













