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 configEach 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:
- Edit on Device A: Task modified, saved to disk as a markdown file
- Syncthing detects change: File hash updated, queued for transfer
- Transfer to Device B: Delta sync — only changed bytes are sent
- 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:
| Scenario | Conflict? | Reason |
|---|---|---|
| Edit on A, sync, edit on B | No | Sequential changes |
| Edit on A and B simultaneously | Yes | No sync between edits |
| Edit offline on both devices | Yes | Changes diverged |
Conflict File Naming
original-filename.sync-conflict-YYYYMMDD-HHMMSS-DEVICEID.mdExample:
weekly-review.sync-conflict-20260127-143022-LAPTOP.mdResolving Conflicts
Resolution Options
When Daylight detects a conflict file, it surfaces the conflict in Settings and offers three options:
- Keep Local: Your device’s version wins. The remote version is archived to
conflicts/. - Keep Remote: The other device’s version wins. Your local version is archived.
- 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.mdFilenames 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:
- Conflict was already resolved and archived (automatic)
- Manually delete files from the
conflicts/folder - Syncthing propagates deletion across devices (if the folder is synced)
- Syncthing file versioning keeps a backup in
.stversions/if enabled
Best Practices
Sync Configuration
| Setting | Recommended | Reason |
|---|---|---|
| Sync interval | 30 seconds | Frequent sync reduces the window for conflicts without meaningfully increasing resource use |
| File versioning | Simple | Keeps one previous version of each file. Useful as a last-resort backup without filling disk. |
| Ignore patterns | None for Tasks/ | All task files should sync. Ignore patterns risk silently excluding tasks from other devices. |
Avoiding Conflicts
- Sync before editing — Let Syncthing finish before opening the app on a second device. Check the Syncthing UI for “Up to Date” status.
- One device at a time — The simplest conflict prevention: don’t edit the same task on two devices simultaneously.
- Check sync status — Syncthing’s web UI and tray icon show sync progress. If a device shows “Syncing,” wait before editing.
- Small, frequent syncs — A 30-second sync interval means the conflict window is narrow. Longer intervals increase the chance of overlapping edits.