bradtraversy.dev — mission-control.mdx
home.md projects/ × tools/ devlog/ articles/ now.md about.md
// project

# Mission Control

vault-native ops dashboard with todos, tasks, projects, sessions, calendar, all live, all on the LAN

local Next.js ·React ·TypeScript ·Tailwind ·chokidar ·SSE
mission control dashboard, vault-native ops surface running on the homelab

what it is

an internal next.js app that runs on my homelab and reads my obsidian vault as its source of truth. tabs across the top: home, todos, tasks, projects, sessions, research, network, calendar, agents. every list on screen is built by parsing markdown files; every action you take writes back to those same files without breaking obsidian compatibility.

it’s not on the public internet. it’s bound to the LAN, runs as a systemd-user service, and is only useful if you have access to the vault behind it. the surface is private. the architecture is the interesting part.

why i built it

before mc, my “dashboard” was a sprawl: a python network status page, a separate todo dashboard html, a Tasks/ folder i grepped from the cli, and obsidian for everything else. each surface had its own write contract and none of them coordinated. checking on the system meant opening four tabs and trusting they all agreed.

i wanted one page that was honest about the vault: read straight from disk, write straight back, no caching layer to drift. and i wanted live updates: when an agent flips a task to done, my screen updates without a refresh.

how it works

  • vault is the database. every read parses markdown directly. no postgres, no sqlite, no shadow store. obsidian stays a first-class ui. i can edit any file from either side and the other reflects within a second
  • writes are atomic and frontmatter-safe. instead of round-tripping through a yaml parser (which would reformat keys, reorder, mangle comments), every writer does line surgery: regex-match the exact line, substitute, write via .tmp + rename. files come out byte-identical to a manual edit
  • live updates via chokidar + sse. a single watcher singleton broadcasts to the browser through server-sent events; the client calls router.refresh() on relevant changes with a small debounce. obsidian saves, cli edits, and agent writes all trigger the same pipeline
  • route handlers, not server actions. the write surface is a real http api so it’s curl-testable, scriptable, and reachable from any agent, not boxed into “from-browser-only”
  • agent task contract. a top-level Tasks/ folder holds work units as markdown files with agent, status, and priority frontmatter. autonomous profiles on the homelab poll that folder and claim items tagged for their lane; claude code surfaces queued items at session start; the dashboard is a third lens on the same data

what’s in it

  • home: current focus, today’s calendar, recent activity feed
  • todos: three-column board (now / soon / later) with check-off, move-between-columns, inline add. ids and tags live in frontmatter
  • tasks: kanban with agent filter, one column per lane (sysadmin, developer, creator, secretary, claude, me). add, status-flip, ping-an-agent from the top bar
  • projects: cards with status pills, drilling into the project’s vault folder
  • sessions: unified feed of claude and hermes-profile session logs
  • research / network / calendar / agents: same pattern, each reading from a known vault region

what’s next

  • progress bars on project cards (blocked on a tag-taxonomy decision for tasks)
  • per-profile heartbeat integration so each autonomous lane stamps a liveness signal back to the dashboard
  • two-way calendar: currently read-only; write-back deferred

the lesson i keep relearning: when the storage format is already human-readable, the dashboard layer is small. the trick is not reaching for the database.

## more screenshots

Mission Control screenshot 1 Mission Control screenshot 2 Mission Control screenshot 3

## recent devlog

// devlog entries tagged project: mission-control
→ all devlog

## related articles

// EOF mission-control.mdx
main
mission-control.mdx
UTF-8
LF
Markdown
Ln 1, Col 1