For AI agents: the complete documentation index is available at https://docs.flashnerd.com/llms.txt, the full documentation bundle is available at https://docs.flashnerd.com/llms-full.txt, and this page is available as Markdown at https://docs.flashnerd.com/reference/flashnerd-format/package.md.
Skip to main content

Package rules and dependencies

A .flashnerd file is an unencrypted ZIP. This page defines its layout and shared record rules; the format overview links to each collection and field definition.

Layout

Paths start at the ZIP archive root. These are example filenames, not mandatory basenames. Every collection and its directory is optional; include the records needed by your references.

Archive root
├── manifest.json                      # Generated on export; ignored on import
├── content/
│   ├── review_folders/
│   │   └── folders.jsonl               # Folders that organize decks
│   ├── decks/
│   │   └── tokyo.jsonl                 # Decks and field definitions
│   ├── tags/
│   │   └── tags.jsonl                  # Reusable tags
│   └── cards/
│       └── notes.jsonl                 # Cards and field values
├── srs/
│   ├── srs_folders/
│   │   └── folders.jsonl               # Folders that organize SRS sets
│   └── srs_sets/
│       └── daily.jsonl                 # SRS sets, settings and linked decks
├── progress/
│   └── schedules/
│       └── current.jsonl               # Current SRS schedules
├── history/
│   ├── srs_reviews/
│   │   └── reviews.jsonl               # SRS review events
│   └── normal_reviews/
│       └── reviews.jsonl               # Flashcard and matching review events
├── preferences/
│   ├── user.json                      # One object of portable preferences
│   ├── card_template_presets/
│   │   └── basic.jsonl                 # Saved question/answer template
│   ├── srs_presets/
│   │   └── daily.jsonl                 # Saved daily study settings
│   ├── ai_instruction_presets/
│   │   └── basic.jsonl                 # Saved AI generation instructions
│   └── search_presets/
│       └── text.jsonl                  # Saved search filters
└── media/
    ├── cat.png                         # Example image bytes
    └── example.wav                     # Example audio bytes

See the linked record pages in the dependency table for every file location and supported property.

JSONL and filenames

  • Each collection accepts any direct child ending exactly in .jsonl. For example, content/cards/basic.jsonl, content/cards/daily.jsonl and content/cards/00000.jsonl are equally valid. Export uses numbered filenames by convention.
  • A file can contain one or many records of that collection's type. Multiple files in a collection are also allowed; their paths are sorted lexicographically. File order does not create relationships.
  • Use UTF-8, with one complete JSON object per physical line, no enclosing array and no comments. Completely empty lines are ignored; lines containing only spaces or tabs are invalid. Use \n inside a string for a newline in card text. Pretty-printing a record across multiple lines is not accepted.
  • preferences/user.json has an exact filename and contains one JSON object, which can be pretty-printed. It is not JSONL.
  • Omit unused files/directories. A package needs at least one valid content or preset record, or one explicitly supplied non-null preference (false and 0 count). Empty JSONL files, {} or all-null preferences/user.json, and manifest-only or media-only archives are not importable. Empty files remain allowed beside meaningful data. Existing syntax, field, and reference errors take precedence.
  • Paths are exact. srs_presets/test.json and a root user.json are ignored; use preferences/srs_presets/*.jsonl and preferences/user.json. study/srs_folders and study/srs_sets are unrecognized; use srs/srs_folders and srs/srs_sets. There is no path repair or JSON reformatting.
  • Unrelated members, including manifests and macOS metadata, are skipped when valid importable data exists. Import does not unwrap an enclosing folder: my-export/content/cards/notes.jsonl is not recognized.
  • Extra JSON properties are ignored in records and nested settings. They are not retained on a later export. Each reference lists the recognized properties; optional does not universally mean nullable.
  • Recognized properties still need valid values, and required properties must still be supplied. Extra properties do not repair missing relationships or unknown field IDs in a card's values map. Malformed JSON, duplicate keys, invalid enums and invalid references remain errors.
  • Settings and values are structured JSON, not JSON encoded a second time inside strings.

Identifiers and enums

  • IDs are opaque strings. Readable keys such as deck-tokyo are valid; UUIDs are not required when authoring a package.
  • Any JSONL record may omit its own id. It receives a temporary source identity, not an ID for later updates. Explicit null, non-string and empty IDs are invalid. Do not construct references to generated identities.
  • Relationship IDs remain required and must name explicitly identified companions in the same package, except that scoped cards-only files omit deckId and use the caller's destination fields. Deck field IDs remain required. Card-template preset fields may omit id unless another field references them; a TTS target must have an explicit ID. Names, filenames and field positions do not resolve references.
  • Search-preset selectedTagIds and selectedDeckIds match exact, explicit IDs in this archive's content/tags/ and content/decks/ records. A matching tag label, deck name, or ID already in the destination collection does not satisfy an absent archive reference. The preset may omit its own id; selected companions must supply theirs. Omitted or empty selections leave that filter unrestricted. See the search-preset reference for a filter and its companion tag file.
  • Omitted preset-field IDs receive temporary source identities and fresh app UUIDs on import. Override Existing preserves supplied field IDs only when the preset itself has an explicit ID; omitted field IDs are regenerated on every import. Updating a saved preset does not change existing deck fields. Exports include concrete field IDs.
  • Ordinary app imports remap readable source IDs to stored IDs. Updating an existing card requires its persisted ID, obtainable from an app export. Anonymous cards always create new cards, including with Override existing enabled; repeated anonymous history imports create new events. Ordinary copy imports can reuse tags by trimmed, case-insensitive label, so omitted IDs do not guarantee a new tag. With override enabled, a schedule is updated by its referenced card and keeps that local schedule ID.
  • A card, folder, deck, tag, set, or schedule needs an explicit ID when another record references it. Anonymous records and explicitly identified companions may coexist in the same package.
  • Enums use the exact strings in the enum catalog. The documented exception is SRS reviewBehavior.noAnswerRating, which uses integer ratings 1–4.

Required authoring input

Own IDs stay optional except that referenced records must supply explicit IDs. Names and filenames do not resolve links.

CollectionRequired keys
Review foldersname
Decksname, fields
Tagslabel
CardsdeckId in ordinary packages; omit it in scoped cards-only files. Omitted values means an empty card.
SRS foldersname
SRS setsname
Card-template presetsname, fields
SRS presetsname
Search presetsname
AI instruction presetsname, instruction
SchedulesreviewCardId, setId, state, exactly one populated timeDue or dueReviewDay, plus state-dependent values
SRS historysrsCardId, occurredAtUtc, reviewPeriodKey, rating
Normal historycardId, deckId, occurredAtUtc, reviewPeriodKey, studyMode, isCorrect

Still required, with specific purposes:

  • Names and labels identify authored content.
  • Relationship IDs name the intended companion.
  • Field definitions keep explicit id, name, side, and type, with valid front/back coverage.
  • Card-value type stays required for typed parsing against the template.
  • History keeps occurrence time and independently assigned review day.
  • Normal-history deckId stays required because the historical deck may differ from the current card deck.
  • Scheduling keeps due time, state, and conditional memory values. New content can omit progress entirely.
  • Nested payloads keep required range endpoints, rectangle dimensions, selected TTS references, and learning-step values/units.

General settings, field settings, partial SRS settings, and user preferences already support omission. There is no blanket defaulting pass.

Timestamps and calendar dates

Timestamps use YYYY-MM-DDTHH:mm:ss, optionally followed by fractional seconds, and end in Z or ±HH:mm; for example 2026-01-01T09:00:00+09:00. Offsets are accepted and normalized to UTC. Writers emit UTC.

The optional fraction has one through six digits. Readers validate real calendar dates, hours 00–23, minutes/seconds 00–59, and offset hours/minutes. Missing zones, incomplete times, leap seconds and impossible dates are rejected. Microsecond precision is preserved. Input years and the resulting UTC year must be 0000–9999.

Calendar dates (reviewPeriodKey and search bounds) are zero-padded YYYY-MM-DD strings, such as 2026-01-01, with real dates in years 0001–9999. Year zero is rejected for calendar dates independently of timestamp validation. They are not timestamps.

createdAt and updatedAt are independently optional on folders, decks, tags, cards, SRS sets, and preset records that support these timestamps. Omission and explicit null mean unavailable metadata. The format does not invent dates from read time, ZIP timestamps, filesystem mtimes, or an epoch placeholder.

When importing an archive through Home or SRS, new records use supplied dates and fill each missing date independently with the captured UTC commit time. Override existing preserves an existing record's creation date and uses the supplied update date or commit time. A copy import that reuses a tag by label keeps that tag's existing dates.

A deck's Add Card flow does not restore source card timestamps, whether the input is cards-only or an ordinary archive. New cards receive the commit time for both dates. Matching updates preserve the existing creation date and set the update date to the commit time.

Both history types require occurredAtUtc and reviewPeriodKey. The review day is independent of the timestamp's UTC date and is preserved without recalculating it from current timezone or rollover preferences. review_date cannot replace the required occurredAtUtc and reviewPeriodKey properties.

Dependencies

All collection files below use JSONL. Filenames are arbitrary within the listed directory; *.jsonl means a direct-child file such as basic.jsonl or 00000.jsonl.

Archive locationStandalone supportRequired or conditional companions
preferences/card_template_presets/*.jsonlYesField definitions are included in the preset. Field-referenced TTS needs an explicitly identified source field within that same preset, not another file type.
preferences/srs_presets/*.jsonlYesSettings are included directly. No SRS set, deck, card, or other preset is needed.
preferences/ai_instruction_presets/*.jsonlYesSupply name and instruction. A deck selecting the preset must include its explicit ID and the preset in the same archive.
preferences/search_presets/*.jsonlConditionalStandalone when selectedDeckIds and selectedTagIds are omitted or empty. Otherwise, include each selected deck/tag and its dependencies.
preferences/user.jsonYesSupply at least one recognized, non-null preference. Explicit false and 0 count; {} or only ignored properties do not. This file is one JSON object, not JSONL.
content/tags/*.jsonlYesTags do not require cards or decks.
content/review_folders/*.jsonlYes, with parent recordsRoot folders need no companions. A non-null parentId requires its parent in this same collection, including any further ancestors. No decks are required.
content/decks/*.jsonlConditionalA root deck can stand alone without cards. A supplied non-null folderId requires a review folder. The deck includes its own field definitions.
content/cards/*.jsonlWith destination context onlyOrdinary deckId requires an explicit deck. Scoped cards-only records omit deckId and use the selected destination's fields. Each supplied tagIds entry still requires an archive tag. Media values may reference files under media/; see the missing-media exception below.
srs/srs_folders/*.jsonlYes, with parent recordsRoot folders need no companions. A non-null parentId requires its parent in this same collection, including any further ancestors. No SRS sets are required.
srs/srs_sets/*.jsonlConditionalAn empty root set can stand alone. Each deckIds entry requires a deck. A supplied non-null folderId requires an SRS folder. Settings are included in the set.
progress/schedules/*.jsonlNoreviewCardId requires a card; setId requires an SRS set. Include the card's deck, and include that deck in the set's deckIds.
history/srs_reviews/*.jsonlNosrsCardId refers to an explicit schedule ID, not a content-card ID. Include that schedule and its card, deck, SRS set, and other dependencies.
history/normal_reviews/*.jsonlNocardId and deckId require explicit card/deck records. Include the card's own deck too if different from the historical deckId. No SRS set or schedule is required.
media/No standalone importCard values reference individual files using exact mediaPath values. Unused media alone does not count as importable content.
manifest.jsonIgnored on importNo record depends on the manifest. It is export metadata and cannot make an otherwise empty archive importable.

AI instruction presets can stand alone in preferences/ai_instruction_presets/. A deck with non-null aiInstructionPresetId also requires that explicitly identified preset in the same archive.

How record references work

  • Include the targets in the same archive. A matching record already in the destination app does not replace a missing companion, including with Override Existing enabled. The explicit exception is scoped cards-only import: the caller supplies the destination template, and card JSON must omit deckId. This does not relax tag references or repair a malformed full archive.
  • Referenced records need explicit IDs. An unreferenced record may omit its own id, but another record cannot target its generated identity. IDs match exactly, including case; names, labels, filenames, and record positions do not substitute for them.
  • Follow every dependency. If a card needs a deck and that deck has folderId, include the folder and its ancestors too. If the card supplies tag IDs, include those tags.
  • File boundaries do not create links. Put related records of one collection in the same JSONL file or separate files in that collection's directory. The filenames do not have to match across directories, and ZIP member order does not determine relationships.
  • The two folder collections are separate. Decks use review folders; SRS sets use SRS folders. Each folder's parent must belong to its own collection.

Decks carry their own fields; they do not have to include or reference a card-template preset. SRS sets carry their own settings; they do not have to include or reference an SRS preset. Importing one of these reusable presets does not create a deck/set or automatically apply its configuration to existing content.

Within a deck or card-template preset, field-referenced TTS uses settings.contentSourceId to identify a field in that same layout. The source must have an explicit field ID and a supported type: text, Chinese, Japanese, or cloze. It cannot reference another deck's field or a separate preset. Manual TTS has no source-field dependency.

Card values keys must identify fields in the card's own deck, with matching value types. Deck field IDs are required. Preset field IDs may be omitted when no other field references them. See the shared field reference for examples and supported settings.

Search presets with filters such as struggle, field types, or date bounds do not require matching cards, schedules, or history to be included. Only their explicit deck/tag selections introduce those record dependencies. Omitting a selection or using [] means no restriction from that selection, rather than zero matching cards. See the search-preset companion example.

Progress and history restoration

Schedules and both history types are optional for new content. A schedule requires its card and SRS set, and the set must include the card's deck. A card can have only one schedule, and a deck can belong to only one SRS set in the archive.

SRS history depends on schedule records; it does not reconstruct a missing schedule by replaying past reviews. Normal history depends on cards and decks without needing SRS data. Its historical deckId may differ from the card's current deck, so include both decks when necessary.

In the app, Include study progress defaults to off and controls restoration of schedules and both SRS and normal review history. When it is off, those records are not restored. Newly imported cards linked to SRS sets start New when no schedule is restored; overriding existing cards with progress off preserves their existing local progress. Progress/history alone cannot form a usable import; include their content companions even when the destination already has them.

If the app cannot load progress/history but the content is otherwise valid, it can continue with content only and show an Unable to load study progress warning. That fallback omits all imported schedules and both history collections, rather than skipping only an individual bad review.

Media is a recoverable exception

Card media references use an exact archive path such as media/cat.png, not a record ID. Image/audio field definitions in decks or template presets do not themselves require media; the dependency begins when a card value supplies mediaPath.

Import allows a referenced media file to be missing. The app retains the card with a blank media value and reports missing media; a missing image-occlusion image also removes its rectangles. Unsafe paths and present but empty, oversized, or ZIP-corrupted referenced media still fail validation. Package checks cover ZIP integrity and size; they do not decode image or audio formats.

Small package combinations

These combinations assume root decks/sets/folders and no optional tag or media references. Include any additional companions named by your actual records.

What to importCollections to include
A saved card template or SRS presetJust preferences/card_template_presets/ or preferences/srs_presets/.
A saved search filter without deck/tag selectionsJust preferences/search_presets/.
A preference such as app themeJust preferences/user.json with a supported value.
Ordinary flashcardscontent/decks/ + content/cards/.
Cards for an already selected deckJust content/cards/, with every deckId omitted and destination template supplied by the Add Card caller. Tags/media are optional companions when referenced.
New SRS study contentcontent/decks/ + content/cards/ + srs/srs_sets/. Link the decks from the set; imported schedules/history are optional.
Flashcard or matching review historycontent/decks/ + content/cards/ + history/normal_reviews/. Enable Include study progress to restore the events.
Current SRS progresscontent/decks/ + content/cards/ + srs/srs_sets/ + progress/schedules/. Enable Include study progress.
SRS progress with review historyThe current-progress combination above + history/srs_reviews/. Enable Include study progress.

Profiles

Import streams whatever recognized files are present; it does not read the manifest profile.

Export profileTypical contentsMeaning
contentContent, media, optional study collections, presets and user preferencesPortable exchange. Exports omit progress/history. Imported cards start New when progress is absent.
backupContent plus schedules and historyLibrary snapshot. Schedules are authoritative; restore does not replay history to reconstruct them.

Archive rules

  • Readers accept STORE (method 0) and DEFLATE (method 8). JSON is normally DEFLATE-compressed. Writers compress media only when that makes it smaller.
  • Writers emit ZIP32 while counts, sizes and offsets fit; otherwise they emit ZIP64 structures.
  • JSONL files have configurable limits of 10,000 records or 64 MiB uncompressed by default. These apply on import too; split larger collections across files.
  • Media uses exact media/<filename> references, with no base64 or asset catalog. Filenames may contain spaces and Unicode; nested media paths are not supported.
  • Streamed members are checked for CRC and actual size. Import does not require SHA-256 hashes.
  • Encryption, unsupported compression, symlinks, path traversal, duplicate ZIP names, overlapping members and excessive resource use are rejected.

Limits

Keep generated files within the app's limits and split large JSONL collections into multiple files. Passing the downloadable schemas does not establish that every app constraint is satisfied.

App behavior

  • A deck holds at most 20,000 cards, and a card has at most five distinct tags. Ordinary archive import retains the first 20,000 cards per source deck and first five distinct tags, with warnings. Add Card rejects an oversized source or a result that would exceed the destination's card limit.
  • Review folders and SRS folders allow at most six nested folder levels. The collection root is level 0; folders occupy levels 1–6. A seventh nested folder is rejected, even if empty. Schema checks alone do not enforce this app rule.
  • The app stores trimmed folder, deck, set, and preset names up to 200 UTF-16 code units, and field/tag labels up to 100. Import shortens longer metadata without splitting a grapheme. The default package and schema name limits below are smaller; short authoring names work across both.
  • Import accepts larger compressed packages, more cards in an archive, and more input tags than those defaults, and accepts longer metadata before shortening it. Other archive resource protections still apply. Available device storage can also prevent an import; these overrides do not promise unlimited file handling.

Default schema and package limits

The table lists default package-validation limits. The app applies the behavior described above. The downloadable schemas separately constrain individual records; they do not check ZIP sizes or every package rule.

For string lengths, schema maxLength counts Unicode code points in the supplied value, without trimming. Package validation counts UTF-16 code units, trimming names and labels first but measuring AI instruction text without trimming. A supplementary character such as an emoji counts as one code point and two UTF-16 code units. The schemas use the same numeric bounds for these strings, but the different counting and trimming rules mean their results can differ. Passing a schema does not prove the app will import the file.

LimitDefault package validation
Cards100,000
Media files100,000
Fields per deck or card-template preset20
Tags per card5
Media file10 MiB
Compressed package2 GiB
Expanded package4 GiB
ZIP entries250,000
ZIP central directory64 MiB
Records per JSONL file10,000
Uncompressed JSONL file64 MiB
JSONL line2 MiB
Folder / deck / set / preset name40 UTF-16 code units, after trimming
Field name30 UTF-16 code units, after trimming
Tag label20 UTF-16 code units, after trimming
AI instruction text10,000 UTF-16 code units, measured without trimming

Manifest

The exporter may write manifest.json at the ZIP root. It is not required, and import never reads it, including its version, profile, feature list, counts, or hashes. A manifest alone cannot make an archive importable. You can omit it when creating or editing a package.

Inspect the complete example manifest or its schema. The following properties describe exported metadata, not required authoring input.

All fields below are emitted by the current writer. They have no omission defaults on import because import ignores the entire file.

FieldTypeMeaning / values
formatstringAlways flashnerd.
versionintegerExport metadata; ignored during import.
profilestring enumcontent or backup; see profiles.
packageIdstringOpaque identity of this export.
createdAttimestamp stringExport creation instant, written in UTC.
generatorobjectname and version, both strings identifying the exporting program.
requiredFeaturesstring arrayFeatures used by the writer. Current feature strings: fsrs_decay, deflate_media. Import does not check this list.
countsobject of integersRecord totals by collection; keys listed below.
shardsobject arrayMetadata for each JSONL record member; fields listed below.
sizesobject of integerscompressedBytes: finished ZIP file length. uncompressedBytes: sum of uncompressed members except manifest.json.

Count keys

KeyCollection
reviewFolderscontent/review_folders
deckscontent/decks
tagscontent/tags
cardscontent/cards
srsFolderssrs/srs_folders
srsSetssrs/srs_sets
schedulesprogress/schedules
srsReviewshistory/srs_reviews
normalReviewshistory/normal_reviews
cardTemplatePresetspreferences/card_template_presets
srsPresetspreferences/srs_presets
searchPresetspreferences/search_presets
aiInstructionPresetspreferences/ai_instruction_presets

There is no assets count or asset collection. User preferences and media are not JSONL record collections and do not appear in this counts object.

Shard entry fields

FieldTypeMeaning
pathstringExact archive member path, e.g. content/cards/00000.jsonl.
recordsintegerNumber of records in this JSONL member.
sha256stringHexadecimal SHA-256 of its uncompressed bytes.
uncompressedBytesintegerLength of its uncompressed bytes.

These hashes are export metadata; import checks ZIP integrity without requiring SHA-256. preferences/user.json and media are not included in the shard list.

The exporter adds fsrs_decay when schedules or SRS reviews contain non-null decay, and deflate_media when it compresses media. Import does not gate on either declaration. A missing historical decay value is not filled during import; app-specific progress handling is described in progress and history.

If you retain an export manifest after editing payload files, its recorded counts and hashes become stale. Omit it or regenerate it with an exporter. Its SHA-256 values do not replace the ZIP integrity checks.

Compatibility and validation

History records require occurredAtUtc and reviewPeriodKey; review_date cannot replace these required properties. Schedules require exactly one populated timeDue or dueReviewDay. Use the documented schedule and history shapes.

Validation and examples explains the distinct roles of schemas and the app preview. Cards-only files have a separate destination-template contract.