Files
astrolabe/docs/spec/08-import-export.md
T

5.7 KiB

08 · Import & Export

Astrolabe lets a user back up or transfer their entire workspace as a single JSON file, and bring data back in by importing such a file. Both actions are triggered from header controls labelled Import and Export. Import always merges with existing data; it never replaces what is already stored.

Export

Export produces one downloadable JSON file containing every snippet (see Snippet Library) and every dataset (see Datasets), wrapped in an envelope carrying format metadata.

  • Trigger: the Export header control runs the export immediately (no intermediate dialog).
  • Contents: all snippets and all datasets currently stored, plus envelope metadata.
  • Empty workspace: if there are no snippets, the user is informed ("No snippets to export") and no file is downloaded — even if datasets exist.
  • Filename: astrolabe-project-YYYY-MM-DD.json, where the date is today's date (export day).
  • Feedback: on success a toast reports the counts, e.g. "Exported 4 snippets and 2 datasets" (the dataset clause is omitted when there are no datasets; singular/plural wording adapts to the counts).

Export envelope shape

The downloaded file is a single JSON object: an envelope with a format version, an export timestamp, an exporter tag, and the two data arrays.

{
  "version": "1.0",
  "exportedAt": "2026-06-03T12:00:00.000Z",
  "exportedBy": "Astrolabe",
  "snippets": [
    /* full snippet objects (see Data Model) */
  ],
  "datasets": [
    /* full dataset objects (see Data Model) */
  ]
}
  • version — export format version (currently "1.0").
  • exportedAt — ISO 8601 timestamp of the export.
  • exportedBy — fixed identifier "Astrolabe".
  • snippets / datasets — arrays of complete records as defined in Data Model, each including its record version field. (This is the per-record schema version, not the envelope version above.)

Import

Import lets the user pick a JSON file from their device; its contents are normalized, merged into the current workspace, and saved.

  • Trigger: the Import header control opens a file picker restricted to JSON files. After a file is chosen (or the picker cancelled) the control is ready to be used again immediately.

Accepted inputs

The importer recognizes several shapes so that both Astrolabe exports and looser snippet files work:

  • Astrolabe export envelope — an object with a version and a snippets array; an optional datasets array is imported too.
  • Bare array of snippets — a top-level JSON array is treated as a list of snippets (no datasets).
  • Single snippet object — any other object is treated as one snippet.
  • Older / foreign snippet shapes — snippets that do not match the current model are normalized onto it:
    • Alternative field names are mapped: content → spec, draft → draft spec, createdAt → creation timestamp.
    • Missing timestamps are generated at import time (creation and modification set to now, or derived from the source timestamp when present).
    • Missing identifiers, names, comments, tags, dataset references, metadata, and record version are filled with defaults (a missing version is treated as the earliest shape and migrated up on read — see Data Model).
    • Such normalized imports are tagged "imported" so the user can find them.

A snippet is treated as already in current Astrolabe format when it carries an ISO-style creation timestamp; in that case its existing fields (id, name, timestamps, spec, draft spec, comment, tags, dataset references, metadata) are preserved as-is, with sensible fallbacks for any missing field.

Merge behavior

  • Imported snippets are appended to the existing library; nothing is overwritten or removed.
  • ID collisions (an incoming snippet whose id already exists) are resolved by assigning the incoming snippet a fresh unique id; the original snippet keeps its id.
  • Datasets are imported before snippets so that snippet dataset references can resolve.

Dataset conflicts

When an imported dataset's name already exists in the library, it is auto-renamed to a unique name rather than overwriting the existing one (see Datasets).

  • A numeric suffix is appended to the original name; further suffixes are added until the name is unique.
  • The renamed datasets are reported to the user via a warning toast listing each original -> new rename.
  • If a single dataset fails to import, it is skipped and the rest of the import continues.

Storage limit handling

Snippet storage has an approximate 5 MB budget (see Snippet Library storage monitor).

  • If the incoming snippets would push total snippet storage over the budget, the user is warned about the overage amount, but the app still attempts to save the import.
  • If the save ultimately fails because the storage quota is exceeded, the user is told to delete some snippets and try again, and no partial snippet import is committed.
  • The storage check applies to snippets; datasets are stored separately and saved during the dataset phase above.

Feedback

  • Success: a toast reports how many snippets (and datasets, when any) were imported, e.g. "Imported 4 snippets and 2 datasets".
  • Renames: when datasets were renamed, the success message is shown as a warning toast that also lists the renames.
  • Empty file: if no snippets are found in the file, the user is informed ("No snippets found in file") and nothing is imported.
  • Quota failure: a clear error advising the user to delete snippets and retry.
  • Invalid file: a non-JSON or unparseable file produces a clear error ("Failed to import. Please check that the file is valid JSON."); an unreadable file produces a read error. In all error cases the existing workspace is left unchanged.