Emmanuel Doji

Portfolio · 2026

000%

EmmanuelED · 26
All case studies

Schoolbox · 2025 · Full-stack engineer

Schoolbox — Offline-First AI Tutor on Tauri + Rust

Bundle size
~12MB
Cold start
< 800ms
Offline capability
100%
Platforms
Windows / macOS / Linux

Why Tauri + Rust

Electron was off the table — a 200MB binary is unshippable on the connections this app is deployed over. Tauri ships a WebView pointed at the OS's native renderer (~12MB), with Rust handling the heavy lifting: SQLite, file system, LLM inference, encryption.

The frontend is a normal React + Tailwind app. The backend is a Rust crate invoked via Tauri's command system. Everything that can run on-device does; the network is opportunistic.

Architecture

┌──────────────────────────────┐
│  React 18 + Tailwind         │
│  (WebView, ~3MB)             │
└────────────┬─────────────────┘
             │  Tauri IPC (typed)
┌────────────▼─────────────────┐
│  Rust backend                │
│  - reqwest (sync when online)│
│  - SQLite (sqlx)             │
│  - bcrypt (account auth)     │
│  - DOCX parser (mammoth-rs)  │
│  - Local LLM runtime         │
└──────────────────────────────┘

Key decisions

Local LLM, not cloud. A small quantized model runs locally for tutoring conversations. Quality is below GPT-4 but it's there when there's no internet. When connectivity returns, the app upgrades to a cloud model transparently.

SQLite everywhere. All user data, all course material, all conversation history lives in a local SQLite file. Sync is a separate concern that runs in the background when network is available; the foreground app never blocks on it.

KaTeX, not MathJax. KaTeX renders math 10x faster and ships as static CSS — no runtime font loading, no network requests, predictable performance on low-end hardware.

What I learned

Building for low-connectivity regions forces architecture decisions that improve every other deployment too. The offline-first version is faster, smaller, and more reliable than the broadband-assumed version would have been. Constraint became feature.