Day Light

Sync & Conflicts

Syncthing-Ready Architecture

Daylight doesn’t include its own sync engine. Instead, each task is a single markdown file on your filesystem, and you sync that folder using Syncthing — a peer-to-peer, end-to-end encrypted file sync tool that runs independently. Daylight reads and writes files; Syncthing moves them between devices. The two never talk to each other directly.

Why Syncthing

This design is intentional. Building sync into the app would mean maintaining a server, handling authentication, and managing uptime — the exact dependencies Daylight avoids:

  • No cloud dependency: Syncthing is peer-to-peer. Your data moves directly between your devices without touching a third-party server.
  • Peer-to-peer: No central point of failure. If one device is offline, the others continue syncing between themselves.
  • End-to-end encryption: Data is encrypted in transit. No intermediary can read your tasks.
  • You control the servers: If you want a relay for NAT traversal, you can run your own. Or use Syncthing’s public relays. Your choice.

Folder Structure

~/Sync/TaskNotes/
├── Tasks/ # One markdown file per task
│ ├── Buy groceries.md
│ ├── Weekly review.md
│ ├── Client proposal.md
│ └── ...
├── conflicts/ # Archived conflict versions
│ ├── Buy groceries_local_2026-01-31T17-45-32.md
│ └── ...
└── meta.json # App settings and calendar config

Each task is its own file. This means Syncthing handles conflicts at the task level, not at the database level — if two devices edit different tasks simultaneously, there’s no conflict at all. Conflicts only happen when the same file is edited on two devices before sync completes.


How Sync Works

Normal Flow

The sync cycle is straightforward because Daylight operates entirely on the local filesystem:

  1. Edit on Device A: Task modified, saved to disk as a markdown file
  2. Syncthing detects change: File hash updated, queued for transfer
  3. Transfer to Device B: Delta sync — only changed bytes are sent
  4. Daylight detects change: Task reloaded from disk on next app start or refresh

Conflict Detection

Conflicts happen when the same task file is edited on two devices before Syncthing can sync the change:

Device A: task.md (edited 10:00)
Device B: task.md (edited 10:01, no sync yet)
Sync happens: CONFLICT
Result:
task.md (Device A version)
task.sync-conflict-20260127-100100-ABCD.md (Device B version)

Understanding Conflict Files

What Causes Conflicts

Not every simultaneous edit produces a conflict. Syncthing tracks file versions per-device, so sequential changes sync cleanly:

ScenarioConflict?Reason
Edit on A, sync, edit on BNoSequential changes
Edit on A and B simultaneouslyYesNo sync between edits
Edit offline on both devicesYesChanges diverged

Conflict File Naming

original-filename.sync-conflict-YYYYMMDD-HHMMSS-DEVICEID.md

Example:

weekly-review.sync-conflict-20260127-143022-LAPTOP.md

Resolving Conflicts

Resolution Options

When Daylight detects a conflict file, it surfaces the conflict in Settings and offers three options:

  1. Keep Local: Your device’s version wins. The remote version is archived to conflicts/.
  2. Keep Remote: The other device’s version wins. Your local version is archived.
  3. Keep Both: Both versions are preserved — the conflict file is renamed as a separate task for manual review.

Resolution Workflow

1. Daylight shows conflict indicator
└── Task: Weekly Review ⚠️
2. View both versions side by side
└── Local: "Agenda: Q1 planning, budget review"
└── Remote: "Agenda: Q1 planning, hiring update"
3. Choose action
├── Keep Local
├── Keep Remote
└── Keep Both
4. Conflict resolved
└── Rejected version archived to conflicts/
└── Task: Weekly Review ✓

Archiving vs Deletion

Why Archive

Daylight never deletes conflict files automatically. Rejected versions are moved to the conflicts/ folder with a timestamp in the filename. This is a deliberate safety choice:

  • Recovery possible: If you chose the wrong version, the other one is still on disk. Open it, copy what you need, done.
  • History preserved: The conflict archive is a record of what happened. You can see when conflicts occurred and what the competing versions looked like.
  • Sync-safe: Deleting files in a Syncthing folder propagates the deletion to all devices. Archiving to a subfolder keeps the file available locally without syncing it back as a “new” task.
  • No data loss risk: The worst case is a folder with some old files in it. The alternative — silent deletion — means lost work with no recovery path.

Archive Structure

conflicts/
├── Weekly review_local_2026-01-15T09-30-00.md
├── Weekly review_remote_2026-01-15T09-32-15.md
└── Client proposal_local_2026-01-22T14-10-45.md

Filenames encode the task name, which version was rejected (local or remote), and the timestamp of the conflict resolution.

Hard Delete (When Necessary)

If you want to permanently remove archived conflict files:

  1. Conflict was already resolved and archived (automatic)
  2. Manually delete files from the conflicts/ folder
  3. Syncthing propagates deletion across devices (if the folder is synced)
  4. Syncthing file versioning keeps a backup in .stversions/ if enabled

Best Practices

Sync Configuration

SettingRecommendedReason
Sync interval30 secondsFrequent sync reduces the window for conflicts without meaningfully increasing resource use
File versioningSimpleKeeps one previous version of each file. Useful as a last-resort backup without filling disk.
Ignore patternsNone for Tasks/All task files should sync. Ignore patterns risk silently excluding tasks from other devices.

Avoiding Conflicts

  1. Sync before editing — Let Syncthing finish before opening the app on a second device. Check the Syncthing UI for “Up to Date” status.
  2. One device at a time — The simplest conflict prevention: don’t edit the same task on two devices simultaneously.
  3. Check sync status — Syncthing’s web UI and tray icon show sync progress. If a device shows “Syncing,” wait before editing.
  4. Small, frequent syncs — A 30-second sync interval means the conflict window is narrow. Longer intervals increase the chance of overlapping edits.