Daylight

Case Study

The Challenge

Build a task manager that respects user data ownership while delivering the reliability people expect from cloud apps—without a cloud.

Most productivity tools make a bargain: convenience in exchange for your data living on someone else’s servers. Daylight asks: what if you didn’t have to make that trade?

Starting Constraints

  • Local-first requirement: All data must live on user devices as readable files. No server, no account, no data hostage situations.
  • Markdown-native storage: Tasks must be plain text files that work in any editor, survive any app, and version-control cleanly.
  • Cross-platform sync: Must work across Android and Linux without building sync infrastructure. Users bring their own sync tool.
  • Single-developer reality: Every feature must be maintainable by one person. Complexity is the enemy.

Key Decisions

Decision 1: YAML Frontmatter for Metadata

The choice: Store task metadata (status, dates, tags, recurrence) as YAML frontmatter in Markdown files.

---
title: Weekly team review
status: active
scheduled: 2026-01-28
recurrence:
rule: FREQ=WEEKLY;BYDAY=TU
---
Meeting notes go here.

Why this wins:

  • Human-readable without the app
  • Parseable by any language
  • Git-friendly diffs
  • Survives app abandonment

Tradeoff accepted: No binary attachments, no rich formatting in metadata, slower than a database for large task counts. Worth it for portability.

Decision 2: Syncthing Instead of Built-In Sync

The choice: Don’t build sync. Recommend Syncthing and make the file format sync-friendly.

Why this wins:

  • Zero server infrastructure to maintain
  • Users control their sync (privacy)
  • Battle-tested sync technology
  • Works offline by default

Tradeoff accepted: Users must set up Syncthing themselves. Conflicts are visible (not hidden). This requires documentation and honest messaging about the operational reality. Worth it for data ownership.

Decision 3: Instance-Based Recurring Tasks

The choice: Track each recurrence as a separate instance with its own status, not just a next-date pointer.

recurrence:
rule: FREQ=WEEKLY;BYDAY=FR
instances:
- date: 2026-01-24
status: completed
- date: 2026-01-31
status: active

Why this wins:

  • Completing Friday’s task doesn’t affect next Friday
  • Skip without breaking the series
  • Reschedule one instance without moving all future instances
  • Full history visible in the file

Tradeoff accepted: More complex file format. Instance array grows over time. Requires careful UI to show “this week’s instance” vs “the series.” Worth it for recurrence you can trust.

Decision 4: Manual Time Tracking Only

The choice: No timers. Manual entry of time spent, with optional 15-minute rounding.

Why this wins:

  • Timers assume uninterrupted work (rare in reality)
  • Manual entry captures what actually happened
  • No timer state to persist across restarts or sync
  • Simpler implementation, fewer edge cases

Tradeoff accepted: No automatic tracking. Users who want Pomodoro or stopwatch-style tracking need a separate tool. Worth it for simplicity and accuracy.

Decision 5: Read-Only Calendar Overlays

The choice: Show calendar events from Google/ICS for context, but never write back.

Why this wins:

  • Planning context without leaving the app
  • No OAuth token management complexity
  • No conflict between “task scheduled date” and “calendar event”
  • Clear data ownership boundary

Tradeoff accepted: Can’t create events from Daylight. Users manage calendars in native apps. Worth it for reduced scope and clear boundaries.


What Shipped

Core Features Delivered

FeatureWhat it doesDesign decision
Task ManagementCreate, edit, complete, archive tasksFile-per-task, YAML frontmatter
Smart GroupingPast / Now / Upcoming / Wrapped viewsAutomatic based on scheduled date
Recurring TasksDaily, weekly, monthly with instance trackingRRULE format, per-instance status
Time TrackingManual time entries per task15-minute snapping, no timers
Calendar OverlayRead-only Google Calendar / ICS displayContext only, no write-back
Multi-device SyncWorks with Syncthing out of the boxConflict files, not hidden merges

Deliberate Omissions

Not includedWhy
Real-time collaborationSingle-user by design; file sync has inherent latency
Built-in cloud syncUsers control their sync; no server dependency
Timer-based trackingManual entry is more accurate for interrupted work
Calendar write-backClear boundary between tasks and events
Natural language datesAmbiguity causes more problems than it solves
Mobile widgetsPlatform complexity; core app first

Outcomes

What Worked

Data ownership resonates. Users who’ve been burned by app shutdowns or data exports that lose information respond strongly to “your tasks are just files.”

Instance-based recurrence builds trust. The most common recurrence complaint in other apps—“I completed today but it moved to next week”—doesn’t exist when each instance is independent.

Sync conflicts are honest. Showing conflict files instead of silently merging forces users to understand what happened. Counterintuitively, this builds more trust than hiding conflicts.

What’s Still Hard

Onboarding Syncthing. File sync is unfamiliar to many users. The setup documentation has to do heavy lifting.

Android permissions. MANAGE_EXTERNAL_STORAGE permission sounds scary. Explaining why it’s needed (to access the Syncthing folder) requires clear messaging.

Scale ceiling. File-per-task works great up to ~10,000 tasks. Beyond that, you need a database. This is the right tradeoff for a personal tool, but it’s a ceiling.


Lessons Learned

1. Constraints are features

Every constraint forced a better decision. “No server” led to file-based storage. “No sync infrastructure” led to Syncthing compatibility. “One developer” led to simplicity.

2. Ship the tradeoffs

The Limitations page is one of the most valuable pages on the site. Honest documentation of what Daylight doesn’t do builds more trust than pretending tradeoffs don’t exist.

3. Local-first is a positioning advantage

In a market of cloud-first apps, “your data stays on your device” is differentiation, not limitation. The right audience sees this as the feature, not the compromise.

4. Recurrence is make-or-break

For daily/weekly task managers, recurrence reliability is table stakes. Instance-based tracking adds implementation complexity but eliminates the most common user frustration.


The Meta-Lesson

This case study exists because the product decisions are defensible. Every tradeoff has a reason. Every omission is intentional.

Product content strategy isn’t about spin—it’s about making decisions you can explain honestly, then explaining them well.