Jasmine
← Selected projects

Personal planning, 2026

Lumen Daily

I built Lumen Daily to catch a thought in one sentence and carry it everywhere it matters. It works offline and guards my privacy. It has run my 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’ve never had trouble writing things down. The trouble came after I’d written them down: 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 act on them.

Capture saves the sentence, then sorts it.

Everything I put into Lumen Daily 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 Daily’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 as I typed it.

Capture stores the thought before it's sorted.

02Kept safe

Saved before anything else happens.

If I'm offline, IndexedDB holds the capture until the connection is back, and when it replays with the same idempotency key, D1 records it exactly once.

03Routed

The Worker saves the sentence, then one Claude job sorts it.

Every typed capture lands in D1 as an inbox row and a sorting job in one batch. Captures in the same 15-minute window share that job, and when the wording is unclear the sorter files it for me to decide.

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 when it comes due.

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

The wording is kept as I typed it.

Capture stores the thought before it's sorted.

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

Saved before anything else happens.

If I'm offline, IndexedDB holds the capture until the connection is back, and when it replays with the same idempotency key, D1 records it exactly once.

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

The Worker saves the sentence, then one Claude job sorts it.

Every typed capture lands in D1 as an inbox row and a sorting job in one batch. Captures in the same 15-minute window share that job, and when the wording is unclear the sorter files it for me to decide.

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 when it comes due.

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.

Each tap writes once, and a receipt records it.

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 tapThe Worker saved it before one Claude job sorted it.
  1. 01
    Saved, then sorted

    One Claude job filed it under Task.

    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.

One durable identity prevents duplicate writes, and Undo keeps the original receipt. The Worker saves the sentence before one Claude job sorts it.

A task tied to a place surfaces on the day my plan puts me there.

Lumen Daily 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’s no geofence
    The mode comes from my plan, so the app never 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

      Claude gets one bounded job per capture batch.

      The Worker writes the inbox row and its sorting job in one D1 batch, and the job covers a 15-minute window. A submitted photo creates one parsing job the same way.

    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 can't 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 two ways to log a workout without filling in a form: a plain sentence, or a photo of the machine's screen.

    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 Daily 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 are different: preferences, constraints, the things worth still knowing next year. Those live in their own private repository, and nothing gets there until I approve it. Revisions are versioned, so a bad fact is corrected by moving a pointer. Most nights nothing is approved, so the filer ends without filing anything or making a commit.

    From build to habit

    Where Lumen Daily stands now.

    I stopped opening Lumen Daily to test it. It's the app I open every day now, from my home screen, and it holds me to the things I said I'd 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.