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/cards.md.
Skip to main content

Card records

A card belongs to a deck and stores values for that deck's fields. It may also name tags. New hand-authored cards can omit their own IDs. Ordinary packages include that deck; cards-only imports use the selected destination's template instead.

Location and basic example

Put one card object per physical line in any content/cards/*.jsonl file, such as content/cards/notes.jsonl or content/cards/chapter-1.jsonl. Filenames are arbitrary; files must be directly inside that canonical directory. Omit the collection when there are no cards.

These two complete JSONL records use the basic Tokyo deck. The second also requires the tag-beginner record and your own files at media/cat.png and media/example.wav:

{"deckId":"deck-tokyo","values":{"field-front":{"type":"text","value":"Sumimasen"},"field-back":{"type":"text","value":"Excuse me"}}}
{"id":"card-konichiwa","deckId":"deck-tokyo","createdAt":"2026-01-01T00:00:00Z","updatedAt":"2026-01-01T00:00:00Z","tagIds":["tag-beginner"],"values":{"field-front":{"type":"text","value":"Konnichiwa"},"field-back":{"type":"text","value":"Hello"},"field-image":{"type":"image","mediaPath":"media/cat.png"},"field-audio":{"type":"audio","mediaPath":"media/example.wav"}}}

The first card intentionally omits id, timestamps, tagIds, and values for the media fields. It imports as a new card with no tags and empty media fields. The second card keeps explicit dates for backup-style preservation.

Cards-only example for Add Card

When using a selected deck's Add Card import, omit deck files and omit every card's deckId. This line assumes the selected deck already has text fields with IDs field-front and field-back:

{"values":{"field-front":{"type":"text","value":"Hello"},"field-back":{"type":"text","value":"Bonjour"}}}

Keep the destination field IDs and types from the downloaded starter. Duplicate this anonymous line for another new card; no ID editing is needed. Tags and media remain optional, but referenced tags must still be in this archive. Only cards, tags, and media are supported. A full archive with deck shards still uses the ordinary examples above. See the cards-only contract for the starter-file workflow and validation requirements.

Full example

Copy the runnable content/cards/00000.jsonl, or read its expanded records below. Each object occupies one physical line in the file; the formatting here is for reading.

Use these records with both full decks, the linked package tags, and the image/audio files. The inherited records omit display overrides; the override records include every applicable settings property. Chinese and Japanese can retain content-specific pronunciation corrections while inheriting display settings. The linked card file also includes card-read-line, used by the initial-learning schedule.

Language card inheriting its template

{
  "id": "card-station",
  "deckId": "deck-japanese-travel",
  "createdAt": "2026-03-01T09:00:00.000000Z",
  "updatedAt": "2026-03-02T09:00:00.000000Z",
  "tagIds": [
    "tag-beginner",
    "tag-travel"
  ],
  "values": {
    "field-ja-word": {
      "type": "japanese",
      "value": "駅",
      "useTemplateSettings": true,
      "settings": {
        "furiganaOverrides": [
          {
            "sourceIndex": 0,
            "expectedKanji": "駅",
            "rubyOverride": "えき"
          }
        ],
        "romajiOverride": "eki",
        "pitchOverridePattern": [
          "H",
          "L"
        ]
      }
    },
    "field-ja-meaning": {
      "type": "text",
      "value": "station",
      "useTemplateSettings": true
    },
    "field-ja-audio": {
      "type": "audio",
      "mediaPath": "media/pronunciation.wav",
      "useTemplateSettings": true
    },
    "field-ja-photo": {
      "type": "image",
      "mediaPath": "media/station.png",
      "useTemplateSettings": true
    },
    "field-ja-speak": {
      "type": "tts",
      "useTemplateSettings": true
    },
    "field-zh-word": {
      "type": "chinese",
      "value": "站",
      "useTemplateSettings": true,
      "settings": {
        "pinyinOverrides": [
          {
            "tokenIndex": 0,
            "pinyin": "zhan4"
          }
        ]
      }
    },
    "field-ja-map": {
      "type": "image_occlusion",
      "mediaPath": "media/station.png",
      "occlusionRects": [
        {
          "x": 0.1,
          "y": 0.2,
          "width": 0.3,
          "height": 0.25
        },
        {
          "x": 0.6,
          "y": 0.1,
          "width": 0.2,
          "height": 0.3
        }
      ],
      "useTemplateSettings": true
    }
  }
}

Language card with complete overrides

{
  "id": "card-ticket",
  "deckId": "deck-japanese-travel",
  "createdAt": "2026-03-01T09:00:00.000000Z",
  "updatedAt": "2026-03-02T09:00:00.000000Z",
  "tagIds": [
    "tag-travel"
  ],
  "values": {
    "field-ja-word": {
      "type": "japanese",
      "value": "切符",
      "useTemplateSettings": false,
      "generalSettings": {
        "isHidden": false
      },
      "settings": {
        "showPitchAccent": true,
        "showFurigana": true,
        "showRomaji": true,
        "annotationSetting": "hint",
        "furiganaOverrides": [
          {
            "sourceIndex": 0,
            "expectedKanji": "切符",
            "rubyOverride": "きっぷ"
          }
        ],
        "romajiOverride": "kippu",
        "romajiType": "ascii",
        "pitchOverridePattern": [
          "L",
          "H",
          "H"
        ]
      }
    },
    "field-ja-meaning": {
      "type": "text",
      "value": "ticket",
      "useTemplateSettings": false,
      "generalSettings": {
        "isHidden": false
      },
      "settings": {}
    },
    "field-ja-audio": {
      "type": "audio",
      "mediaPath": "media/pronunciation.wav",
      "useTemplateSettings": false,
      "generalSettings": {
        "isHidden": false
      },
      "settings": {
        "autoplay": true
      }
    },
    "field-ja-photo": {
      "type": "image",
      "mediaPath": "media/station.png",
      "useTemplateSettings": false,
      "generalSettings": {
        "isHidden": true
      },
      "settings": {}
    },
    "field-ja-speak": {
      "type": "tts",
      "value": "切符",
      "useTemplateSettings": false,
      "generalSettings": {
        "isHidden": false
      },
      "settings": {
        "autoplay": true,
        "sourceType": "manual",
        "contentSourceId": "",
        "locale": "ja-JP"
      }
    },
    "field-zh-word": {
      "type": "chinese",
      "value": "票",
      "useTemplateSettings": false,
      "generalSettings": {
        "isHidden": false
      },
      "settings": {
        "chineseType": "simplified",
        "showPinyin": true,
        "annotationSetting": "hint",
        "pinyinOverrides": [
          {
            "tokenIndex": 0,
            "pinyin": "piao4"
          }
        ]
      }
    },
    "field-ja-map": {
      "type": "image_occlusion",
      "mediaPath": "media/station.png",
      "occlusionRects": [
        {
          "x": 0.1,
          "y": 0.2,
          "width": 0.3,
          "height": 0.25
        },
        {
          "x": 0.6,
          "y": 0.1,
          "width": 0.2,
          "height": 0.3
        }
      ],
      "useTemplateSettings": false,
      "generalSettings": {
        "isHidden": false
      },
      "settings": {}
    }
  }
}

Programming card inheriting its template

{
  "id": "card-list-literal",
  "deckId": "deck-dart-fundamentals",
  "createdAt": "2026-03-01T09:00:00.000000Z",
  "updatedAt": "2026-03-02T09:00:00.000000Z",
  "tagIds": [
    "tag-beginner",
    "tag-programming"
  ],
  "values": {
    "field-dart-prompt": {
      "type": "text",
      "value": "Growable list literal",
      "useTemplateSettings": true
    },
    "field-dart-code": {
      "type": "code",
      "value": "final items = <String>[];",
      "useTemplateSettings": true
    },
    "field-dart-cloze": {
      "type": "cloze",
      "value": "Dart has null safety.",
      "clozeRanges": [
        {
          "start": 9,
          "end": 13
        }
      ],
      "useTemplateSettings": true
    },
    "field-dart-notes": {
      "type": "rich_text",
      "value": [
        {
          "insert": "List literal",
          "attributes": {
            "bold": true
          }
        },
        {
          "insert": " creates a growable list.\n"
        }
      ],
      "useTemplateSettings": true
    },
    "field-dart-formula": {
      "type": "tex",
      "value": "\\sum_{i=1}^{n} i = \\frac{n(n+1)}{2}",
      "useTemplateSettings": true
    }
  }
}

Programming card with complete overrides

{
  "id": "card-null-safety",
  "deckId": "deck-dart-fundamentals",
  "createdAt": "2026-03-01T09:00:00.000000Z",
  "updatedAt": "2026-03-02T09:00:00.000000Z",
  "tagIds": [
    "tag-programming"
  ],
  "values": {
    "field-dart-prompt": {
      "type": "text",
      "value": "Null safety",
      "useTemplateSettings": false,
      "generalSettings": {
        "isHidden": false
      },
      "settings": {}
    },
    "field-dart-code": {
      "type": "code",
      "value": "String? name;",
      "useTemplateSettings": false,
      "generalSettings": {
        "isHidden": false
      },
      "settings": {
        "selectedLanguage": "dart",
        "showLineNumbers": true,
        "wrapLines": true,
        "forceDarkMode": true,
        "showLanguageHeader": true,
        "fitToContent": false,
        "minLines": 3,
        "maxLines": 12
      }
    },
    "field-dart-cloze": {
      "type": "cloze",
      "value": "Dart has null safety.",
      "clozeRanges": [
        {
          "start": 9,
          "end": 13
        }
      ],
      "useTemplateSettings": false,
      "generalSettings": {
        "isHidden": false
      },
      "settings": {}
    },
    "field-dart-notes": {
      "type": "rich_text",
      "value": [
        {
          "insert": "Nullable",
          "attributes": {
            "bold": true
          }
        },
        {
          "insert": " types use the ? suffix.\n"
        }
      ],
      "useTemplateSettings": false,
      "generalSettings": {
        "isHidden": false
      },
      "settings": {}
    },
    "field-dart-formula": {
      "type": "tex",
      "value": "\\sum_{i=1}^{n} i = \\frac{n(n+1)}{2}",
      "useTemplateSettings": false,
      "generalSettings": {
        "isHidden": false
      },
      "settings": {
        "autoSize": false
      }
    }
  }
}

Record properties

PropertyRequiredValues and defaultExplicit null
idNoNonempty string when supplied. Omission creates a temporary source identity and always imports as a new card. See identity rules below.Invalid
deckIdOrdinary packages onlyID of an existing record in content/decks/. Must be omitted in scoped cards-only files; the selected deck supplies the destination template.Invalid
createdAtNoTimestamp with a timezone when supplied. Omission and null mean unavailable metadata.Unavailable
updatedAtNoTimestamp with a timezone when supplied. Omission and null mean unavailable metadata.Unavailable
tagIdsNoArray of existing tag ID strings; omission means []. The default schema limit is five entries; the app keeps at most five distinct imported tags per card.Invalid; use []
valuesNoMap from this deck's field IDs to typed card value objects. Omission means {} and leaves every field empty.Invalid

Extra record and nested value properties are ignored. Duplicate JSON keys remain invalid, and entries in values must still name actual deck field IDs. Optional timestamps have no generated default; see timestamp syntax.

Card identity

Readable IDs such as card-konichiwa are allowed and must be unique across all card files. Field IDs remain required even when a card omits its own id. Ordinary cards also require deckId; scoped cards-only records must omit it.

Only an omitted id requests a generated identity. "id":null, "id":"", or a non-string ID is invalid. The reader assigns a temporary source identity. It is not an ID to copy into another record's references.

That temporary identity does not enable later updates. Cards with omitted IDs always become new records, even with override-existing import. To update an existing card, keep its persisted ID from an app export. Ordinary imports remap source IDs to destination IDs.

Cards referenced by schedules or normal review history must supply explicit IDs. Do not attempt to reconstruct a generated identity for those references. Generated source-identity metadata is not an extra JSON property.

Values and settings

Each key in values is a field ID, not its display name. The value must be an object containing type, and that type must match the deck definition. There are 11 exact wire strings: text, rich_text, image, cloze, tts, audio, image_occlusion, chinese, japanese, code, and tex.

Field familyValue shapeEmpty form
text, tts, chinese, japanese, code, tex{"type":"…","value":"text"}Omit the field, omit value, or set value to "" or null.
rich_text{"type":"rich_text","value":[{"insert":"text\n"}]}Omit the field/value, or use "", [], or null.
image, audio{"type":"…","mediaPath":"media/filename.ext"}Omit the field/path, or set the path to "" or null.
clozeString value plus clozeRanges:[{"start":0,"end":5}].Omit the field, or use value:"" and no ranges. A present cloze field requires a string value.
image_occlusionmediaPath plus occlusionRects:[{"x":0.1,"y":0.2,"width":0.3,"height":0.15}].Omit the field, or omit the media path and use no rectangles.

Do not put nested values, settings, Delta arrays, or masks inside a serialized JSON string. Strings containing line breaks use escaped \n, so the whole card remains one physical JSONL line.

Each field value inherits its template's settings by default. Set useTemplateSettings:false to provide card-specific general/type settings. While inheriting, only Chinese pronunciation corrections and Japanese furigana/romaji/pitch corrections are allowed. The complete field reference documents every setting, default, null behavior, and override rule.

Relationships and missing media

  • In ordinary packages, deckId must resolve to a deck in the same package. Cards-only files omit it and use the selected destination deck's template.
  • Every key in values must resolve to a field defined by that deck, or by the supplied destination in cards-only mode. Unknown field IDs and mismatched types fail validation; omitting unused fields is valid.
  • Every tagIds entry must resolve to a tag. Omit tagIds or use [] when the tags collection is absent.
  • A media value points directly at an exact media path, such as media/cat.png. No asset ID, hash, MIME declaration, or size declaration is needed in a card.
  • If the media directory or referenced file is missing, import retains the card/field/settings with an empty media value and reports missing media. Missing image-occlusion media also clears its rectangles. Unsafe paths and present but corrupt or oversized media still fail.
  • Schedules/history can refer to an explicitly identified card. Content-only imports do not require schedules or review history.

Additional examples

This card uses the one-field deck-cloze shown in the deck examples. It hides Tokyo and Japan using sorted UTF-16 offsets. This is a complete JSONL record:

{"id":"card-geography","deckId":"deck-cloze","createdAt":"2026-01-01T00:00:00Z","updatedAt":"2026-01-01T00:00:00Z","values":{"field-sentence":{"type":"cloze","value":"Tokyo is in Japan.","clozeRanges":[{"start":0,"end":5},{"start":12,"end":17}]}}}

This complete record uses the Tokyo deck and changes audio autoplay for this card only. Other fields stay empty:

{"id":"card-audio-practice","deckId":"deck-tokyo","createdAt":"2026-01-01T00:00:00Z","updatedAt":"2026-01-01T00:00:00Z","values":{"field-audio":{"type":"audio","mediaPath":"media/example.wav","useTemplateSettings":false,"settings":{"autoplay":true}}}}

For an intentionally blank card, an empty values map is valid. Its deck still needs a valid template:

{"deckId":"deck-tokyo"}

Schemas: ordinary card record, field values, general settings, and type settings. The ordinary card schema requires deckId and does not describe cards-only records; those require validation against the selected destination template. Cross-record relationships and type-specific constraints are also checked by the reader.