Skip to content

feat(backup): export any backup version as JSON - #643

Open
dmnyc wants to merge 8 commits into
zapcooking:mainfrom
dmnyc:feat/backup-json-export
Open

feat(backup): export any backup version as JSON#643
dmnyc wants to merge 8 commits into
zapcooking:mainfrom
dmnyc:feat/backup-json-export

Conversation

@dmnyc

@dmnyc dmnyc commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Stacked on #641 — this branch is cut from feat/settings-follow-recovery, so it also contains that commit. Both touch NostrBackupSection.svelte; keeping them stacked avoids a guaranteed conflict. Merge #641 first and this diff reduces to the export commit alone.

Why

Backups are NIP-78 events only the user can decrypt. That's right for privacy and wrong for portability: the data could only ever be read back by this app, and only for as long as the account's signer still works. There was no way to get a copy out.

The change

"Export JSON" on every backup row — Follows, Mute List, Profile — downloading the latest backup's contents as a file.

The expandable Versions list gets a per-version JSON button too, next to its existing Restore. That's arguably the more useful one: when several versions exist, "export this one" is the thing you actually want.

listFollowsBackups() and friends already decrypt eagerly, so the payload is in hand — export costs no extra signer round-trip and no network call.

File contents

The payload is wrapped in a little provenance so the file is still intelligible months later, out of context:

{
  "source": "zap.cooking",
  "exportedAt": "2026-08-20T…",
  "pubkey": "",
  "type": "follows",
  "kind": "kind:3",
  "backedUpAt": "2026-08-14T…",
  "data": { }
}

Filename is zapcooking-<type>-<backup date>.json — dated by when the backup was taken, not when it was exported, so several exports of different versions don't collide.

Buttons are disabled when a row has no decrypted backup to export.

Verification

  • pnpm check — 1 error / 152 warnings, identical to main (pre-existing delete-operator error)
  • pnpm test — 1267 passed
  • Checked in a browser that all three rows render an Export JSON button, correctly disabled when there is nothing to export

Not verified: an actual download with real backup data, which needs a signed-in account with backups. The download path is the standard blob/anchor approach, but the resulting file is worth eyeballing once.

Worth deciding separately

There's no import counterpart. Export alone is still worth having — it gets data out, which is the part that's currently impossible — but "restore from a JSON file" is the obvious follow-up if you want these files to be more than an archive.

@dmnyc
dmnyc force-pushed the feat/backup-json-export branch from c652fc5 to d5282c1 Compare August 20, 2026 04:41
@dmnyc
dmnyc force-pushed the feat/backup-json-export branch from d5282c1 to 4919bc6 Compare August 20, 2026 04:44
@dmnyc
dmnyc force-pushed the feat/backup-json-export branch from 4919bc6 to 77c03e3 Compare August 20, 2026 04:45
@dmnyc
dmnyc force-pushed the feat/backup-json-export branch from 77c03e3 to 93539f3 Compare August 20, 2026 04:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant