← All projects

Maya

A commercial productivity manager: one core, four interfaces, no change without a test.

  • 7Rust crates
  • 1156tests
  • 95.3%coverage
  • 100%mutants killed
Role
One of two developers at Rikagaku
Stack
Rust · Rocket · Diesel · SQLite · WebAssembly (Yew) · Tauri · Next.js · Stripe
Links
Releases

Context

Maya is a productivity manager — not just another task app. Its central idea is to invert the usual flow: instead of picking what to do first, the system helps you decide what not to do, measures what actually got done, and treats long-term consistency as the product itself, not an add-on.

It is a commercial product not yet published, built by two developers at Rikagaku — me among them. Licensing and desktop builds are already in place; the launch is what is missing.

Maya's task list in dark theme, with projects in the sidebar

The main view in March 2025: prioritized tasks, each with its project context.

The same Maya main view today, in dark theme, with the task list and projects in the sidebar

The same view today: the visual evolution of nineteen months of development.

The problem

The engineering challenge was never a single feature — it was the combination:

  • four surfaces — API, CLI, web app and desktop app — that must share the same semantics core;
  • a non-trivial domain: tasks, recurrence, time tracking, statistics, undo, importing data from other systems;
  • quality as a product requirement: something you intend to sell cannot live broken;
  • and a two-developer team. Without tests, every refactor becomes a gamble.

Verification was not there on day one: it became policy after a large refactoring, when the cost of changing code without a safety net became obvious. From then on, TDD as repository policy, a shared contract between surfaces, and automated quality gates.

How it was built

The heart is a Rust workspace with seven crates arranged in layers:

  • core — zero-dependency marker traits that define the vocabulary of operations;
  • macros — a proc macro that turns route annotations into a contract generated at compile time;
  • contract library — request/response types, errors and HTTP client, feature-gated for backend and browser;
  • API — a Rocket server, SQLite persistence through Diesel, task semantics built on the Taskwarrior/Timewarrior ecosystem, and WebSocket for real-time events;
  • CLI — a terminal client, with internationalization; the interactive interface (TUI) does not exist yet;
  • frontend — a WebAssembly SPA, written in the same Rust as the backend;
  • desktop — a thin Tauri shell: activates the license and hosts the app locally, without duplicating business logic.
Maya's calendar view
Calendar view — one of the four surfaces, all sharing the same core.

The contract between surfaces is not documentation that rots: the proc macro generates it from the code itself, so API, CLI, web and desktop cannot drift apart without breaking the build.

Decisions and trade-offs

  • Rust all the way into the frontend (WebAssembly). The ecosystem is smaller than JavaScript’s, but the cost of a second mental model disappears: all four surfaces share types, errors and routes. Wrong domain types become compile errors, not runtime bugs.
  • One contract, generated at build time. Instead of a hand-written OpenAPI spec, the route macro is the single source; drift between surfaces is impossible by construction.
  • Repository-mandated TDD — adopted after the big refactoring. Tests-after-the-fact is forbidden by policy; contract tests run against more than one repository implementation, which gives confidence to refactor persistence.
  • Thin desktop. All logic lives in the local API; the desktop app is a shell with packaging and licensing. Less surface, fewer places for expensive bugs.
  • Commercial verification ready before launch. Licensing with a cryptographic signature bound to the machine, validated against the payment provider — product infrastructure, not just code.

Quality and verification

Numbers from the last documented cycle of the repository:

  • 1156 tests passing;
  • 95.3% line coverage;
  • mutation floor of 70% — the measured result was 100% of mutants killed, meaning the tests don’t just execute code: they actually assert behavior;
  • multi-platform CI (Linux, macOS and Windows) with warnings treated as errors — nothing gets in;
  • UI tests running in a headless browser (WASM), plus contract tests for the data layer;
  • Docker-based test environment, same Dockerfile on any machine.

The repository itself is guarded by mido, the verification tool I built — including a tuned mutation budget for the frontend crate.

Results

Maya is not published yet. What exists is the whole product built and verified end to end — builds for Windows, macOS and Linux plus licensing, ready for launch. More than a working app, the result is a system I can move fast in without fear: the combination of shared contract + TDD + quality gates means changes either pass verification, or get stopped before they become a problem.

Maya's own development tasks listed inside the app
Maya’s own development tasks, inside the app.

What I learned

Verification came late, and the bill came with it: a large refactoring showed how much it costs to change code without a net. That is why it became policy, not a campaign — it is the only sustainable way for a two-person team to keep four surfaces alive. And the verification tooling Maya was missing became a project of its own: sometimes the shortest path is building the tool that is missing.