← Projects

Life OS

A personal operating system web app built around a single loop — Capture, Process, Plan, Execute, Review, Repeat — with a calm warm-toned design and a full feature set pulled from Notion and rebuilt from scratch.

What it is

Life OS is a personal operating system for one user. It is not a generic todo app, not a Notion clone, and not a team tool. It is a calm, structured daily system built around a single workflow loop: Capture → Process → Plan → Execute → Review → Repeat.

The app has a sidebar with ten distinct modules — Inbox, Home (Today View), Calendar, Tasks, Projects, Goals, Habits, Learning, Notes, and Review — each serving a specific role in the loop. Every piece of data lives in a Postgres database with row-level security, and every interaction goes through server actions and a typed service layer.

Why I built it

I was running my personal system through a combination of Notion databases, manual reviews, and various habit trackers. It worked, but it was slow, required constant configuration, and never felt like something designed specifically for how I actually think and work.

The goal was to build something tighter. One app, one loop, one data model, designed around my exact workflow and no one else's. The result would have none of the flexibility overhead of a general tool and none of the limitations of a consumer app. Just the system I would actually use every day.

How it works

The stack is Next.js 14 App Router with TypeScript strict mode throughout. All authenticated pages live under a shared layout with a 214px sidebar. The database is Supabase Postgres, accessed via Drizzle ORM through a strict service layer — db is only ever imported in src/services/, and service functions receive userId as an explicit parameter rather than calling auth internally.

All mutations are server actions in features/*/actions.ts. No API route handlers for mutations, no useEffect + fetch for data loading. Server components fetch data and pass it as props. Zod schemas live in features/*/validators.ts and are shared between client-side form validation and server action re-validation.

The ten modules cover the full loop:

  • Inbox: quick capture without context — items land here, get processed into tasks, projects, or goals
  • Home: today's task list with stat row, daily plan panel, and sort controls (Default / Project / Priority)
  • Calendar: week and month views with event detail/edit modal, created events appear in local state immediately
  • Tasks: area-tagged, project-linked, priority-ordered
  • Projects: status-tracked with milestone breakdown and archived projects behind a collapse toggle
  • Goals: long-term targets linked to areas
  • Habits: daily completion with 7-day pip trail and timezone-correct date handling
  • Learning: learning paths with per-module TipTap editors for notes, auto-saved with debounce, and a side panel for completion checkboxes and scroll-synced navigation
  • Notes: persistent rich text documents per area
  • Review: weekly and quarterly review screens

Design system

The visual identity is Variant A — Warm Structured. The page background is #f5f1eb (warm parchment), the sidebar is #eee9e0, and the single interactive color across the entire app is #4f6b8a (slate blue). The type is DM Sans at weights 300, 400, and 500. No 600 or heavier — it would break the calm tone. Borders are 1px, not 0.5px, which adds warmth. Habit pips are 9×9px squares. Progress bars are 3px. Everything is sized deliberately small and quiet.

The Notion migration

After building all ten phases, I migrated my actual Notion data into Life OS: projects, tasks from multiple work streams, learning paths with modules, and habit records. The migration surfaced three real bugs — a timezone issue where habit completions were stored in UTC rather than my local time, tasks filtered by todo status that were stored as in_progress and therefore invisible, and a calendar event fetch that did not account for local week boundaries. All three were fixed before the app became my primary daily system.

Status

All ten phases are functionally complete. The app is running with real user data as my primary personal operating system. Current work is iterative polish, responsive layout improvements, and additional UX refinements.