← Selected Projects

Personal planning, 2026

Lumen Daily

I built Lumen to catch a thought in one sentence and carry it everywhere it matters. It works offline, guards my privacy, and has run my actual days since the first week it existed.

Every screen on this page is a rebuild using fabricated data.
Built for
Independent product
Role
Product direction, design, and build
System
Vanilla JS PWA, Cloudflare Workers + D1, IndexedDB
Where it stands
Live, installed, and used daily, with authenticated personal access and a privacy-safe public demo.

My notes stayed where I left them.

I have never had trouble writing things down. The trouble came after: a note would sit wherever I left it, and unless I happened to look in the right place at the right moment, it may as well not have existed. What I needed was one place that would bring things back when I could actually act on them.

Capture saves the sentence, then sorts it.

Everything I put into Lumen goes through one box. I write the thought in my own wording, and the sort into a task, a reminder, or a note happens after the entry is saved.

Each demo pick runs one capture.

Three fabricated examples: a task, a reminder, a reflection. The post lands on a live endpoint on this site’s own edge; Lumen’s private API stays untouched.

9:41Lumen Daily

Clear your head.

Write it once. Lumen Daily will put it where it belongs.

Selected thought
Choose a demo capture

Capture saves the original sentence first, then works out where it goes.

Ready for a selectionFinish the Cedar House brand guideThe original language stays intact

What happens to one sentence, in five steps.

One timed reminder, traced from the box to the receipt. The sentence keeps its wording at every step.

01Captured

The wording is kept exactly.

Capture takes the thought before asking what kind it is. The original sentence stays attached.

02Kept safe

Saved before anything else happens.

IndexedDB holds the capture if I am offline; when it replays, D1 records it exactly once.

03Routed

The router calls Claude only for ambiguity.

Clear intent routes deterministically. Only genuinely unclear language opens one bounded, event-driven Claude job.

04Placed

One write reaches three destinations.

A timed thought becomes exactly one Actions reminder, one Today entry, and one Calendar event.

05Accounted for

A receipt shows the route.

Web Push delivers it on time. Capture keeps the sentence and route together.

The threadRemind me to call the dentist tomorrow at 1Reminder
01Captured

The wording is kept exactly.

Capture takes the thought before asking what kind it is. The original sentence stays attached.

Remind me to call the dentist tomorrow at 1
Exactly as written
02Kept safe

Saved before anything else happens.

IndexedDB holds the capture if I am offline; when it replays, D1 records it exactly once.

Durable inputSaved
Remind me to call the dentist tomorrow at 1
03Routed

The router calls Claude only for ambiguity.

Clear intent routes deterministically. Only genuinely unclear language opens one bounded, event-driven Claude job.

TaskReminderReflection
Resolved as Reminder
04Placed

One write reaches three destinations.

A timed thought becomes exactly one Actions reminder, one Today entry, and one Calendar event.

DestinationActions + Today + CalendarOne row in each
Remind me to call the dentist tomorrow at 1
05Accounted for

A receipt shows the route.

Web Push delivers it on time. Capture keeps the sentence and route together.

9:41Lumen DailyToday
Scheduled · ReminderThe same sentence, now in context

Today · Tomorrow

1:00 PM
ReminderRemind me to call the dentist tomorrow at 1
Actions · Today · Calendar · Web Push

Actions

Every action keeps the sentence I typed.

I built the write path to survive my own retries.

Operational storyOne action and its receipt
Synthetic local demonstration
From Capture · TaskIdentity act_1042
Ready to actFinish the Cedar House brand guide

Original sentence retained · Anywhere

What happens beneath one tapClear intent routes without an AI call.
  1. 01
    Routed directly

    Clear Task intent bypassed Claude.

    Live
  2. 02
    Committed once

    Offline replay and network retry reuse the same durable identity.

    Next
  3. 03
    Reversible with history

    Undo changes the current state without deleting the original receipt.

    Then

Ready for an action.

Clear intent routes directly, one durable identity prevents duplicate writes, and Undo retains the original receipt.

A task tied to a place appears when I arrive.

Lumen reads the mode from my plan, then surfaces everything held for that place at once.

The day’s mode

Stored per date and versioned. No location permission is ever requested.

10:00 AM

Tasks captured for a place are held in Actions until the day’s mode matches, then surfaced together. The mode is read from the plan alone.

Thu · July 30Morning
10:00
Good morning
HomeFrom your plan
Day FlowCurrent block
NowCedar House brand guide9:30–11:30
NextErrands
Full day4 blocks
    Held for Home
    HomeStart laundry
    HomeWater the herbs
    Why there is no geofence
    I considered detecting arrival and decided against it. The mode comes from my plan, so nothing on the page asks for location permission.

    Operational proof

    Six rules I enforced under the surface.

    Software decides everything it can, Claude gets only bounded jobs, and everything ships private.

    1. Machinery

      Known commands route without a model call.

      Claude runs only when the source is genuinely ambiguous or needs bounded extraction.

    2. Offline state

      Offline captures replay when the device reconnects.

      Stable idempotency keys and D1 mutation receipts prevent an offline replay from becoming a duplicate.

    3. Automation

      I removed the pollers.

      The one scheduler left cannot run the same slot twice.

    4. Observability

      I can see why a job stopped.

      Every request-backed job is a durable row carrying its attempts, next attempt, and error category.

    5. Boundary

      The recovery route is absent from the public build.

      A test asserts that absence. The demo ships through a six-file allow-list.

    6. Shape

      I added versioning after a real conflict.

      The day's mode carries a version because two devices were editing one date; a stale write returns 409 and refreshes instead of overwriting.

    Logging a workout on a treadmill.

    I gave Plan exactly two ways to log a workout: a plain sentence, or a photo of the machine's screen. On a treadmill, nobody wants a form.

    SourceTwo low-friction paths
    Tell Lumen50 minutes of Pilates, then a 20-minute walk
    or scan a machine screen
    Fabricated photo of an unbranded treadmill console
    Only source-visible values are usedMovement photo ready

    Event-driven
    Lumen DailyPlanMovement

    Movement summary

    Source ready

    Both inputs create the same session record.

    Either explicit source creates one bounded route. Unreadable values are never invented.

    Filed from photo

    Treadmill

    Time
    38 min
    Distance
    2.4 mi
    Calories
    285 cal
    Incline
    4%
    Completed consequenceCamera roll → one job → fitness diary

    Returned context carries a link to its source.

    Lumen pulls from my email and returns private notes when I ask for them. Work in progress comes back with the state I left it in.

    Requested

    A private note moves after I request it.

    Private session notesFabricated summary

    Request-only source

    Session recap

    Complete · Summary available

    Waiting for an explicit request.

    Private notesSource intact
    Destination / JournalWaiting for a request.
    Lumen DailyJournalPrivate

    Latest recap

    Session recap

    • Protect recovery time after demanding weeks.
    • Name the decision instead of carrying the whole question.
    Completed consequencePrivate source → requested → Journal
    Automatic

    The same email is filed once.

    Confirmation emailRead only

    Appointment confirmed

    Dentist visit

    Tomorrow · 1:00 PM · Fabricated

    Stable message identityProcessed once
    EmailDeduped
    Lumen DailyTodayFiled

    Tomorrow

    Dentist visit

    Calendar
    1:00 PM
    Reminder
    12:30 PM
    Completed consequenceEmail → deduped → Today
    Workstream

    I can resume a thread from where it stopped.

    Incoming workstreamFabricated

    Cedar House

    Brand guide

    Summary ready · concise by design

    The handoff is ready when you are.

    WorkstreamStable handoff
    Destination / WorkWaiting for the handoff.
    Lumen DailyWorkResumable

    Workstream handoff

    Ready to resume.

    Last completed
    Voice and tone pages approved.
    Next move
    Draft launch captions from the approved voice.
    Completed consequenceWorkstream → stable handoff → Work
    Durable

    A fact is kept only after I approve it.

    Operational data lives in the database. The facts that describe a life live somewhere slower and more deliberate: preferences, constraints, the things worth still knowing next year. They only arrive there when I approve them. Approved text is committed to its own private repository, and revisions are versioned, so a bad fact is corrected by moving a pointer. Most nights nothing is approved, so nothing is filed and no commit is made.

    From build to habit

    Where Lumen stands now.

    Lumen stopped being a thing I opened to test and became the app I open every day. It lives on my home screen and holds me to the things I said I would do.

    Live
    Production
    Installed
    Home screen
    Trusted
    Daily use
    Offline replay
    Verified without duplicates
    Public demo
    Synthetic and isolated
    Release checks
    Nine contract suites

    The real contents stay private.