Files
initiative/specs/007-json-import-export/quickstart.md
Lukas fba83bebd6 Add JSON import/export for full encounter state
Export and import encounter, undo/redo history, and player characters
as a downloadable .json file. Export/import actions are in the action
bar overflow menu. Import validates using existing rehydration functions
and shows a confirmation dialog when replacing a non-empty encounter.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 14:28:39 +01:00

2.5 KiB

Quickstart: JSON Import/Export

Feature: 007-json-import-export Date: 2026-03-27

Overview

Export and import the full application state (encounter, undo/redo history, player characters) as a JSON file. Enables backup/restore and sharing encounters between DMs.

Key Concepts

  • ExportBundle: A JSON object containing version, exportedAt, encounter, undoStack, redoStack, and playerCharacters. This is the file format.
  • Full replacement: Import replaces all existing state — encounter, undo/redo, and player characters. It's not a merge.
  • Validation reuse: Import validation uses the same rehydrateEncounter() and player character validation functions that localStorage loading uses.

Implementation Layers

Domain Layer

No new domain functions are needed. The existing types (Encounter, PlayerCharacter, UndoRedoState) and validation functions are reused as-is.

A new ExportBundle type is defined in the domain layer as a pure data structure.

Application Layer

A new use case for import validation and bundle assembly:

  • validateImportBundle(data: unknown) — validates and rehydrates an export bundle, returning the validated bundle or an error.

Export assembly is straightforward enough to live in the adapter layer (it's just reading and packaging existing state).

Adapter Layer (Web)

  • Export: Read state from contexts, assemble bundle, trigger browser download via URL.createObjectURL() + anchor element.
  • Import: File picker input, parse JSON, delegate to application-layer validation, show confirmation dialog if encounter is non-empty, replace state via context setters.
  • UI: Two new overflow menu items in the action bar — "Export Encounter" and "Import Encounter".

File Locations

Artifact Path
ExportBundle type packages/domain/src/types.ts or new file
Import validation use case packages/application/src/
Export/import adapter functions apps/web/src/persistence/
UI integration apps/web/src/components/action-bar.tsx
Confirmation dialog apps/web/src/components/ (new or reuse existing confirm pattern)

Testing Strategy

  • Domain: No new domain tests needed (existing types unchanged).
  • Application: Test validateImportBundle() with valid bundles, invalid bundles, missing fields, wrong types, and edge cases (empty encounter, empty stacks).
  • Adapter: Test export bundle assembly and import file handling.
  • Integration: Round-trip test — export then import should produce identical state.