Repository navigation
Two-way sync with the self-hosted sync server - #7
Draft
Oliver-Johnson wants to merge 9 commits into
Draft
Oliver-Johnson wants to merge 9 commits into
Oliver-Johnson wants to merge 9 commits into
Conversation
…6-10-06.1) seedCustomFoods() ran on every launch and added 11 foods to each user's custom foods list, re-adding any the user had deleted. The list is now only used as a fibre lookup. Existing users keep whatever is already in their list. Also removes plans/training_plan_2026.md, which held personal health data, and corrects the v2026-09-02.2 changelog date. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019C67htt6KV7fmxsGCf5FR7
- README: use the Macrolog name, list current features, correct the default targets, explain Developer Mode, link the beta, and state the GPL-3.0 licence and the correct Open Food Facts data licence (ODbL). - CONTRIBUTING: list the checks CI actually runs, and describe the sync server and AI features as opt-in extras. - Sync server README and developer guide: port 5001, the cd into sync-server, SYNC_API_KEY, where data is stored, what syncs today, Developer Mode, and that browsers block plain http:// servers from the HTTPS app, so a tunnel or HTTPS proxy is needed. - Changelog: add the 3 Sep beta release and 7 Sep docs guides, and fix the old /beta/ path. - Docs home: drop the mention of Docker instructions, which don't exist. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019C67htt6KV7fmxsGCf5FR7
…(v2026-10-06.2) - Trends and Macro History: dates under the charts were cut off; the Trends kg/kcal labels overlapped the top axis values and the end bars covered the axis numbers. - History calendar: an inline padding override put "Jump to Today" behind the bottom nav, so tapping it opened Settings. - Additional Nutrients in Manual and Quick Add never collapsed because no .hidden rule existed. It now collapses on tap and stays open by default, as users see it today. - Macro breakdown popup: escape food names before inserting them. - First-run tour: steps whose target is hidden show the tip centred. - Ko-fi card on tablets sits above the bottom nav. - Docs: What's New cards now reveal in Chrome; the observer watched a card clipped to nothing, which never intersects. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019C67htt6KV7fmxsGCf5FR7
Devices that point at the same sync server now share one food log: entries, notes, weight, water, exercise, fasting, recipes, custom foods, targets and settings. A desktop left open picks up what a phone logs. How it merges: - Each device keeps a fingerprint of every record from its last sync. A record that still matches on one side wasn't changed there, so the other side's version or deletion wins. - When both sides changed a record, this device's edit wins and an edit beats a delete. Water added on two devices the same day is summed. - A device's first sync is a union. Against an old one-way copy this device wins, as the one-way push did; on a server others already sync to, the server's targets win over a new device's defaults. - Uploads carry the revision they started from; the server answers 409 if another device synced in between and the app merges again. Edits made during a sync are kept on top of what was uploaded. Safety: - Never syncs while the tour's demo data is active. - A sync that would delete more than a fifth of either side (and more than 10 records) pauses, and Sync now asks before going ahead. - Clear All Data forgets the last sync, so the next sync restores from the server instead of deleting everywhere. - Unreadable local or server data stops the sync instead of counting as empty. - Changes wait while a sheet is open or someone is typing. When: shortly after a change, on opening the app, when it comes back to the foreground or online, and every 2 minutes while open. Server: new GET/PUT /sync/state with a content-hash revision, so edits made to the file directly (agents filling in fibre) are picked up. Writes are atomic and locked; unknown top-level keys are kept. The old POST /sync/food-log still works until a server has two-way data, then refuses so an outdated app can't overwrite it. Servers without /sync/state still get the old upload and fibre fill-in. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019C67htt6KV7fmxsGCf5FR7
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019C67htt6KV7fmxsGCf5FR7
Developer guide, sync server README and README now describe two-way sync, how merging works and the upgrade path from one-way sync. The changelog gets a beta entry. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019C67htt6KV7fmxsGCf5FR7
This was referenced Oct 6, 2026
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CRtr2mPSPusKdCyJWSbct5
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CRtr2mPSPusKdCyJWSbct5
- Today's targets filled in from settings at launch are marked auto. When both sides changed a day's targets, an auto record gives way to one someone set, and if both are auto the server's stand. A desktop opening later in the day no longer reverts targets set on the phone. - An automatic sync that pauses because it would delete too much now says so with a toast, once, instead of stopping silently. - Unreadable local logs stop the sync with "can't be read" rather than "server offline?". - Seed foods that older versions added on every device, each with its own id, are matched by content, so syncing two devices doesn't list them twice. - Server: the legacy one-way push holds the state lock from its read to its write, so it can't overwrite a two-way sync that lands in between. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CRtr2mPSPusKdCyJWSbct5
4 of 5 tasks
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Checks
index.htmlorsw.jswithout understanding the PWA cache implicationsindex.htmlhas been bumped (format:Version YYYY-MM-DD.N). Left for promotion, see notesmanifest.jsonis still valid JSON (unchanged)sw.js; sync just waits when offline).nojekyll, symlinks, conflict markers, plus a new sync server test job)What this changes
Before: Sync only pushed a full snapshot from one device to the server. On launch the app pulled back only missing fibre, sugar and sodium, plus today's targets. A desktop never saw what a phone logged.
After: every device pointed at the same server shares one log. That covers entries, notes, weight, water, exercise, fasts, recipes, custom foods, targets and settings. A sync runs a few seconds after a change, on opening the app, on coming back to it or back online, and every 2 minutes while open. Settings shows when the last sync ran.
How it merges: each device keeps a fingerprint of every record from its last sync and merges record by record.
Safety:
navigator.locks.Server: new
GET/PUT /sync/state. The revision is a hash of the stored file, so direct edits (agents filling in fibre) are picked up. A PUT carries the revision it started from and gets 409 if another device synced in between. Writes are atomic and locked, and unknown top-level keys are kept. The oldPOST /sync/food-logkeeps working until the file has two-way data, then refuses, so an outdated app can't overwrite it. An app talking to a server without/sync/statefalls back to the old push and fibre fill-in.Docs: the developer guide, sync server README and README describe two-way sync, and the changelog has a beta entry.
Testing done
sync-server/test_server.py, run by a newsync-serverjob in CI.Notes for reviewer
This is a draft. It goes to beta testers first via #9. Before it leaves draft it needs a version bump and a What's New entry on top of master.
Known trade-off: on the first sync after upgrading from one-way sync, an entry deleted since the last one-way upload comes back once, which is the safe side. The same amount of water added on two devices between syncs counts once.
This builds on #2, #1 and #3 (merged in), so its own changes are commits ba5aaeb and 53d73ed.
🤖 Generated with Claude Code
https://claude.ai/code/session_019C67htt6KV7fmxsGCf5FR7
Generated by Claude Code