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 reviewstatus: activescheduled: 2026-01-28recurrence: 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: activeWhy 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
| Feature | What it does | Design decision |
|---|---|---|
| Task Management | Create, edit, complete, archive tasks | File-per-task, YAML frontmatter |
| Smart Grouping | Past / Now / Upcoming / Wrapped views | Automatic based on scheduled date |
| Recurring Tasks | Daily, weekly, monthly with instance tracking | RRULE format, per-instance status |
| Time Tracking | Manual time entries per task | 15-minute snapping, no timers |
| Calendar Overlay | Read-only Google Calendar / ICS display | Context only, no write-back |
| Multi-device Sync | Works with Syncthing out of the box | Conflict files, not hidden merges |
Deliberate Omissions
| Not included | Why |
|---|---|
| Real-time collaboration | Single-user by design; file sync has inherent latency |
| Built-in cloud sync | Users control their sync; no server dependency |
| Timer-based tracking | Manual entry is more accurate for interrupted work |
| Calendar write-back | Clear boundary between tasks and events |
| Natural language dates | Ambiguity causes more problems than it solves |
| Mobile widgets | Platform 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.