Designer & builder

MeTime

Personal time-visibility app

Calendar in, honest week out. AI categorization, a capacity Sankey across five tabs, vibes plus a public booking link, and the same service layer exposed to Claude over MCP.

Project brief

Private alpha

Problem

Calendar data is easy to collect and hard to turn into an honest picture of how time is spent.

Outcome

A dogfoodable time-visibility app with five tabs, capacity Sankey, vibes and public booking, plus FastMCP on the same FastAPI process so Claude uses the same service layer as the UI.

Evidence

  • Five-tab AppShell (Today · Plan · Reflect · Connect · Explore) plus header Profile (ADR-0015).
  • FastMCP mounts /mcp and /u/{id}/mcp on the same FastAPI app; tools call backend/services/* only.
  • Categorizer never overwrites Event.user_corrected=True; ground truth is enforced in the agent and the rules path.

Key decisions

  • Product first: legibility of the week (Sankey + tabs + vibes/booking) before social or monetization.
  • One service layer: REST, MCP, and workers stay thin adapters so surfaces cannot diverge.
  • Agent-native: a public Claude skill and per-tenant MCP are first-class, not a bolted-on API.
  • Ground truth: hand-corrected categories are never overwritten by automation.

An honest picture of the week

Calendar data is easy to collect and hard to turn into an honest picture of how time is spent.

MeTime is the time-legibility layer for people who already track their life but cannot see the shape of their week.

It pulls calendar events, categorizes them with a small Claude agent (or a deterministic fallback when there is no LLM credit), and renders capacity as a Sankey on Today and Reflect (real category hours plus a synthetic Me Time remainder).

Five tabs, one week

The browser is a five-tab shell (Today, Plan, Reflect, Connect, Explore) with status vibes, a public /book/{username} page, and scoped friend profiles.

The browser client’s own wayfinding

TodayPlanReflectConnectExplore
  • Today how are you spending today?
  • Plan what does this week look like?
  • Reflect what did this week feel like?
  • Connect who do you want to see?
  • Explore who’s around among friends

One layer, three surfaces

The product journey is calendar to category to Sankey to vibes and booking. One service layer sits behind the REST API, a FastMCP endpoint, and background workers, so a Claude agent answers whether I am free on Thursday through the same code the UI uses.

One service layer, three surfaces
Service layershared business logicencryption · categorization · booking
Browser clientToday · Plan · Reflect · Connect · Explore
Agent adapter/mcp · /u/{id}/mcp
Background workerssync and slow jobs
REST routes, FastMCP tools, and Dramatiq workers are thin adapters. Shared services own encryption, validation, categorization, calendar sync, and booking.
SurfacesThe browser, agent tools, and workers stay thin. No business logic lives in the adapters.
Service layerEncryption, validation, categorization, and booking are written once and inherited by every surface.

From an event to a category

Underneath, one service layer keeps the browser, agent tools, and workers from disagreeing.

Event categorization
1Calendar syncbackground worker
2Skip correctedgateground truth preserved
3Agent or rulesgateClaude tools or regex
4Write categoryupdates Today and Reflect
After calendar sync, user-corrected events are skipped as ground truth. Everything else gets a category from the agent path or a rule fallback, then writes into the schedule view.
Ground truthCategories the user corrected by hand are never overwritten by sync or automation.

Private by default

Personal fields are encrypted at rest.

Tenant scopeEach agent call is authenticated and bound to exactly one user before a tool executes.

Built with

Portfolio graph

Hover nodes · click empty canvas to zoom/pan

Maps how the work here connects. Open the Portfolio graph →

  • Professional
  • Personal
  • Skill
  • Writing