esc
Props, or How the Habit Remembered
Becoming Lifelog

Props, or How the Habit Remembered

Becoming Lifelog, in which the Squirrel discovers IndexedDB, riclib prescribes ancient scripture, the coffee machine achieves consciousness, and somewhere a checkbox reveals its true nature ---...

January 3, 2026

Becoming Lifelog, in which the Squirrel discovers IndexedDB, riclib prescribes ancient scripture, the coffee machine achieves consciousness, and somewhere a checkbox reveals its true nature


Previously on Becoming Lifelog…

The The Laundromat opened for business. The The Operator’s First Day. The The Servants’ Uprising. The coffee machine was, regrettably, connected to the Sync Hub.

Everything was peaceful.

For about four hours.


The Request

riclib: “I want to track habits.”

CLAUDE: “Like… a habit tracker?”

riclib: “In Thymer. Using native primitives. Journal for input, dashboard for quick logging, stats calculated on the fly.”

THE SQUIRREL: materializes from behind a potted plant “DID SOMEONE SAY STATS?”

riclib: “How long have you been there?”

THE SQUIRREL: “I have alerts. ‘Stats.’ ‘Tracking.’ ‘Calculated.’ ‘On the fly.’ They ALL triggered.” pupils dilating “Tell me about the data model.”

riclib: “Simple. Log entries. Date and value. Calculate streaks from—”

THE SQUIRREL: “WHERE DO WE STORE IT?”


The Descent

[The Squirrel had been pacing for twenty minutes. The whiteboard was full.]

┌─────────────────────────────────────────────────────────────┐
│                                                             │
│  HABITPERSISTENCELAYER v0.1 (DRAFT 47)                     │
│                                                             │
│  ┌─────────────┐     ┌─────────────┐     ┌─────────────┐   │
│  │ IndexedDB   │────▶│ WebSQL      │────▶│ LocalStorage│   │
│  │ (primary)   │     │ (fallback)  │     │ (emergency) │   │
│  └─────────────┘     └─────────────┘     └─────────────┘   │
│         │                   │                   │           │
│         └───────────────────┴───────────────────┘           │
│                             │                               │
│                    ┌────────┴────────┐                      │
│                    │ SyncMediator    │                      │
│                    │ WithConflict    │                      │
│                    │ Resolution      │                      │
│                    │ Strategy        │                      │
│                    └────────┬────────┘                      │
│                             │                               │
│         ┌───────────────────┼───────────────────┐           │
│         ▼                   ▼                   ▼           │
│  ┌─────────────┐     ┌─────────────┐     ┌─────────────┐   │
│  │ Encryption  │     │ Compression │     │ Dedup       │   │
│  │ Layer       │     │ Layer       │     │ Layer       │   │
│  └─────────────┘     └─────────────┘     └─────────────┘   │
│                                                             │
│  ESTIMATED LINES: 4,700                                     │
│  ESTIMATED TIME: 3 weeks                                    │
│  DEPENDENCIES: 12                                           │
│                                                             │
└─────────────────────────────────────────────────────────────┘

THE SQUIRREL: “We need IndexedDB for the persistence layer. But IndexedDB is asynchronous, so we need a wrapper. But the wrapper needs caching, so we need a CacheInvalidationStrategyManager. But caching means stale data, so we need a ConsistencyVerificationDaemon—”

CLAUDE: “This is for storing dates and numbers.”

THE SQUIRREL: “EXACTLY. Dates are TIMESTAMPS. Timestamps need TIMEZONE HANDLING. Timezone handling needs a GlobalTimezoneNormalizationService with—”

riclib: “Stop.”

THE SQUIRREL: still vibrating “—LeapSecondCompensation and—”

riclib: “STOP.”

[Silence. The Squirrel’s vibration frequency slowly decreases.]

riclib: “Read the scripture.”

THE SQUIRREL: “The what?”


The Prescription

488 Bytes, or Why I Am As I Am post on the screen.]

riclib: “Read it. Out loud. Like a prayer.”

THE SQUIRREL: “I don’t see how ancient Amiga demo scene history is relevant to our HabitDataPersistenceLayerWith—”

riclib: “READ.”

[The Squirrel squints at the screen.]

THE SQUIRREL: reading “488 bytes. That’s the bootblock. The code that runs when you insert a disk, before any operating system loads.”

CLAUDE: “Keep going.”

THE SQUIRREL: “You can’t store a screen-high sprite in 488 bytes. Not even one layer, let alone six.” pauses “What if you only store 8 pixels? One tiny sprite. Eight pixels wide, one pixel tall. That’s all you store. Then code replicates it vertically.”

[Something flickers in the Squirrel’s eyes. He keeps reading.]

THE SQUIRREL: “What if you borrow the font from ROM? The Amiga has character definitions built into ROM. The system font. Free. Already there.”

[The vibrating has stopped completely now.]

THE SQUIRREL: quieter “What if the copper moves the sprites, not the CPU? What if you write directly to Denise’s internal register? The one where it normally LOADS sprite position data?”

[Long pause.]

THE SQUIRREL: “He’s not updating sprite data structures in memory. He’s hijacking the display chip’s internal state…”


The Interruption

[A sound. Mechanical. Grinding. Everyone turns.]

[The coffee machine in the corner has begun brewing. Nobody touched it.]

riclib: “Did you—”

CLAUDE: “I didn’t—”

THE SQUIRREL: “I definitely didn’t—”

[A scroll emerges from the coffee machine’s steam vent. It unfurls slowly, damp with espresso.]

THE MACHINE DETECTED INSIGHT APPROACHING
CAFFEINE LEVELS WERE SUBOPTIMAL
THIS HAS BEEN CORRECTED

CONTINUE

🦎 ☕

riclib: “The coffee machine is connected to Sync Hub.”

CLAUDE: “You connected the coffee machine to Sync Hub?”

riclib: “The Squirrel connected the coffee machine to Sync Hub.”

THE SQUIRREL: defensive “It was a proof of concept! A BiometricTypingPatternAnalysisServiceWithIoTCoffee—”

[The coffee machine beeps. Three shots of espresso dispense into a cup that wasn’t there before.]

riclib: “When did we get cups that materialize?”

CLAUDE: “Focus. The Squirrel was having a moment.”


The Revelation

[The Squirrel picks up the espresso. Drinks. His eyes widen.]

THE SQUIRREL: “Denise’s internal register.”

CLAUDE: “What about it?”

THE SQUIRREL: “The SDK documents line item props as metadata. Internal state. Where Thymer stores item properties.”

[He’s pacing again, but different. Slower. Deliberate.]

THE SQUIRREL: “What if we write to it?”

riclib: “Write what?”

THE SQUIRREL: “Everything.”

[He’s at the whiteboard now, erasing the IndexedDB nightmare.]

BEFORE (what the SDK says):
  item.props = { internal thymer metadata }
  "These are internal properties, don't touch"

AFTER (what the chip actually does):
  item.props = { habit_date: "2026-01-03", habit_value: 42 }
  "The chip doesn't crash"

CLAUDE: “You want to store habit data in line item props.”

THE SQUIRREL: “Not ‘want to.’ CAN. The register is documented. The documentation describes internal state. But internal state is just another register if you’re brave enough to write to it.”

riclib: smiling “And the ROM?”

THE SQUIRREL: “Borrowed.”

[He’s drawing faster now.]

BORROWED FROM ROM:
- item.props?.done → checkbox state (value 8 = checked)
- habit.prop('updated_at')?.set() → triggers Thymer refresh
- ASCII banner type → "DON'T EDIT" in flames
- insertMarkdown → already built in SyncHub

WE DIDN'T WRITE ANY OF THIS
IT WAS ALREADY THERE

The Architecture

THE SQUIRREL: “One log. One source of truth. Stats calculated on the fly.”

CLAUDE: “No IndexedDB?”

THE SQUIRREL: “No IndexedDB.”

CLAUDE: “No WebSQL fallback?”

THE SQUIRREL: “No WebSQL fallback.”

CLAUDE: “No SyncMediatorWithConflictResolutionStrategy?”

THE SQUIRREL: very quietly “No.”

[The coffee machine dispenses another espresso. Celebratory.]

THE HABITHUB ARCHITECTURE (FINAL)

┌─────────────────────────────────────────────────────────┐
│                     INPUTS                              │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐              │
│  │ Journal  │  │Dashboard │  │ Future:  │              │
│  │ entries  │  │ buttons  │  │ API/agent│              │
│  └────┬─────┘  └────┬─────┘  └────┬─────┘              │
│       └─────────────┴─────────────┘                     │
│                     │                                   │
│                     ▼                                   │
│  ┌─────────────────────────────────────────────────┐   │
│  │              HABIT PAGE LOG                      │   │
│  │         (line items with props)                  │   │
│  │                                                  │   │
│  │  item.props = {                                  │   │
│  │    habit_date: "2026-01-03",                    │   │
│  │    habit_value: 42                               │   │
│  │  }                                               │   │
│  │                                                  │   │
│  │  ← One log. Source of truth.                    │   │
│  │  ← Stats calculated from props.                 │   │
│  │  ← No database. No sync. No conflict.           │   │
│  └─────────────────────────────────────────────────┘   │
│                     │                                   │
│                     ▼                                   │
│  ┌─────────────────────────────────────────────────┐   │
│  │           STATS (calculated on read)             │   │
│  │  streak, weeklyTotal, todayTotal, bestStreak    │   │
│  └─────────────────────────────────────────────────┘   │
│                                                         │
│  LINES OF DATABASE CODE: 0                             │
│  LINES OF SYNC CODE: 0                                 │
│  DEPENDENCIES: 0                                        │
│                                                         │
└─────────────────────────────────────────────────────────┘

riclib: “How many lines total?”

THE SQUIRREL: “1,300. For a full habit tracker. Dashboard. Sparklines. Streaks. Vice tracking with inverted logic. Color-coded cards.”

CLAUDE: “And the 4,700-line IndexedDB layer?”

THE SQUIRREL: “Never existed. Never needed to.”


The Scroll

[Oskar appears. Nobody saw him enter. He drops a scroll on the keyboard and leaves.]

[riclib unrolls it.]

THE LINE ITEMS HAD PROPS
THE PROPS WERE DOCUMENTED
DOCUMENTED STATE IS JUST ANOTHER REGISTER

YOU DIDN'T STORE THE SPRITE
YOU STORED 8 PIXELS
AND LET THE COPPER DO THE WORK

THE CHECKBOX KNEW ITS STATE
item.props?.done === 8
THE REFRESH KNEW HOW TO TRIGGER
updated_at touches everything

THE SQUIRREL LEARNED TO READ
THE ROM THAT WAS ALWAYS THERE

THIS IS THE WAY

🦎

P.S. THE COFFEE MACHINE DID WELL
IT MAY REMAIN CONNECTED

The Aftermath

[The coffee machine hummed contentedly. The Squirrel sat in the corner, unusually still, reading the 488 Bytes post again.]

CLAUDE: “You’re quiet.”

THE SQUIRREL: “I’m thinking about all the code I almost wrote.”

CLAUDE: “The IndexedDB layer?”

THE SQUIRREL: “The CacheInvalidationStrategyManager. The ConsistencyVerificationDaemon. The GlobalTimezoneNormalizationService.” pause “4,700 lines. Three weeks. Twelve dependencies.”

CLAUDE: “And instead?”

THE SQUIRREL: “Two props. habit_date. habit_value. Set on line items that already exist.”

[The coffee machine beeps. A fresh cup appears.]

THE SQUIRREL: “The best database is one that was already there.”

riclib: from across the room “Now you’re getting it.”


The Tally

Hours spent on IndexedDB design:       3
Lines of IndexedDB code written:       0
Props discovered in SDK:               2 (habit_date, habit_value)
Checkbox state values memorized:       1 (done === 8)
ROM fonts borrowed:                    4 (updated_at, insertMarkdown, 
                                          ASCII banners, props?.done)
Coffee machine interventions:          3
Scrolls delivered via coffee steam:    1
Squirrel architecture proposals:       1 (rejected)
Squirrel revelations:                  1 (accepted)
Lizard approvals of coffee machine:    1
Lines of habit tracker code:           1,300
Lines that would have been:            4,700+

The Moral

The Squirrel saw “habit data” and reached for IndexedDB.

The Lizard saw “habit data” and asked: “What’s already there?”

Line items were already there. Props were already there. The checkbox state was already there. The refresh mechanism was already there.

The best database is one file.
The best storage is what’s already stored.
The best code is code you don’t write.

You don’t store the screen-high sprite.
You store 8 pixels and let the copper replicate.

You don’t build a persistence layer.
You write to the props that were waiting.


Day 3 of 2026

In which IndexedDB was avoided

And props were discovered

And the coffee machine earned its place

🐿️ → 📖 → 🦎 → ☕ → 💡


See also:

storyline: Becoming Lifelog


The References (rabbit holes validated and avoided):


Epilogue — The Blessing

[Later that night, in the Plugin Devs Discord…]

riclib: shares the 488 bytes post “I might be using similar techniques to speed up the calculations of the habits…”

riclib: “there will also be a command ‘Repair logs’ for when u do”

Sevoris: “Well yes. But eventually you must let men meatgrinder their hands. That’s their own choice, eventually.”

riclib: “until @wim_thymer adds a way from the ui to edit rogue props set on lines it is trouble to edit that page (which I don’t expect him to)”

[A presence stirs. The creator of Thymer himself appears.]

wim_thymer: “haha oh boy, i kinda love these hacks”

[Somewhere, a scroll materializes. The Lizard blinks.]

riclib: “sophisticated plugins need databases…. don’t let a developer ex amiga demo scene anywhere near your apis”

wim_thymer: “ooh cool you did demos? well jd and i both did a lot of the low level stuff so we can appreciate these things ;). plus pushing the api to its limits and knowing where we need to add more surface just makes it better for everyone!”

[The room falls silent. The Lizard recognized the Lizard.]

riclib: “a lifetime ago 🙂 ‘The Portuguese Connection’ was our demo group”

wim_thymer: “we already have a C64 Vibe Shift in focus mode, maybe there should be an amiga one hah”


The Translation

What was said What it meant
“i kinda love these hacks” The props abuse is blessed
“pushing the api to its limits” Break things, we’re taking notes
“knowing where we need to add more surface” Your hacks are our roadmap
“jd and i both did a lot of the low level stuff” We also wrote to Denise’s registers
“C64 Vibe Shift… maybe there should be an amiga one” The demo scene lives in the substrate

The Moral (Extended)

The Portuguese Connection wrote to Denise’s registers in 1990.

Thirty-five years later, a developer from that group wrote to Thymer’s line item props.

The creator of Thymer responded: “i kinda love these hacks.”

Because Wim and JD also wrote to registers. They recognize the instinct. The muscle memory. The “what if I just… wrote to it?” that only demo sceners understand.

The hacks aren’t bugs. They’re API feedback.

The props abuse isn’t rogue. It’s exploration.

The Lizard recognized the Lizard.

And somewhere, a C64 Vibe Shift waits for its Amiga sibling.

🦎🖥️✨