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!
Top comments (0)