Przewodnik

Jak tworzyć fiszki — przewodnik RepeatMe

A good card is half the memorization. This guide explains how RepeatMe cards work, when each mode makes sense and how to avoid the classic traps: synonyms, dictionary vs in-context forms, discontinuous expressions. It doubles as the specification for AI: the machine version of the format lives at /prompts/v1/card-format — hand that link to any model.

How a card is structured

A card is one unit of knowledge. It has one or more cases and, for every case, a set of modes the knowledge is tested in.

  • A case is a front / back pair. One case = a regular card. Several cases = a "rule card" (e.g. the conjugation of to be): a random case is shown each time, while the review schedule is shared by the whole card.
  • A mode is the form of the exercise: flip, multiple choice, typed answer, fill-in-the-blank, pair matching.

A profile is a preset of modes reflecting the intent:

Profile Modes For what
Fact Flip, ReverseFlip, Choice, ReverseChoice, Type, Match facts, formulas, definitions — self-assessment + auto-checked discrete answers
Lexical / translation the full set words, expressions, grammar — distractors, synonyms, sentences

A profile only pre-fills the mode set; the author can change modes freely. It does not restrict the available modes: fact cards happily use Choice/Type/Match when distractors or an exact answer exist. The lexical generation rules are language-independent — no separate "English / French" subtypes are needed.

"What we show" ≠ "what we accept"

  • back / front hold the canonical form — what is displayed when the answer is revealed.
  • Accepted answers are the set of forms that count as correct (synonyms, gender/number variants, spelling variants). Any of them is correct; the canonical form is always accepted.

Accepted answers live in the mode data (answers), not on the case: Flip must not have any, and the case keeps only the fields shared by all modes.

context and explanation — two different hints; do not confuse them:

  • context is shown with the question, before answering. Its only job is to resolve genuine ambiguity: set it when the front alone admits more than one correct answer, to pick the intended reading. A homonym front: "язык" → context "орган" ⇒ the expected answer is tongue, not language. An article case: front "Я вижу птицу.", back "I see a bird."the bird is an equally correct translation, so context "какую-то, не конкретную" selects a. The litmus test: would a different answer also be correct without the cue? If not, context MUST stay null — null is the default.
  • context clarifies what the front means, never how the answer is formed: it MUST NOT contain the answer or any part of it, and it MUST NOT hint at the rule being drilled. On an a/an card, context "university starts with the consonant sound [j]" recites the very rule under test and turns recall into reading — that sentence belongs in explanation. A learner who does not know the rule must learn nothing from context.
  • context is shown only when the prompt is the front side (direct modes: Flip, Type, Choice, ClozeType, ClozeChoice); reverse modes and Match do not display it. So context cannot resolve ambiguity on the reverse side: when one back answers several different fronts (a polysemous word), the senses are listed in the answers of the reverse modes — see E18. Keep the cue in context only — never bake it into front itself (front "высокий", context "о росте" — NOT front "высокий (о росте)"): anything inside front becomes part of the term in reverse modes, choice options, typed answers and term listings. front holds the clean term only.
  • explanation is shown after the answer (a lightbulb button): a rule recap, breakdown or mnemonic; it MAY reference the answer and the rule.

context sits on the case (each case of a rule card can carry its own cue); explanation and title belong to the whole card. Set them only when they genuinely help — empty values are the norm. When unsure, omit them.

title: set it only when it adds information not already conveyed by front and context — a grammatical tag ("Phrasal verb"), a topic category, a register note. Never copy front verbatim into title: that just duplicates what the learner sees. In the vast majority of cards title is null.

answers format (important): an array of slots — one slot per {{answer}} blank (for Type/ReverseType there is exactly one slot). A slot is an array of accepted forms, the in-context form first. The number of {{answer}} blanks in sentence MUST equal the number of slots.

Two different meanings of "several answers" — do not mix them up:

  • Synonyms / alternatives — ANY variant counts as correct (till / until; оба / обе) → put them into one slot: [["оба","обе"]].
  • Sequence / separate blanks — ALL parts are required, each in its own place (the 3 forms of an irregular verb; a discontinuous from … till …) → one slot per part: [["from"],["till","until"]].
  • Different senses of one word (fair = «справедливый» and «ярмарка») behave like synonyms — one slot — but only on the side where the question does not tell them apart. Both senses share the same reverse prompt (fair), so the answers of every reverse mode list all of them; each sense has its own forward prompt, where the slot stays single. See the polysemy recipe and E18.

A slot exists only for a {{answer}} blank — never add a slot for words that stay visible in the sentence. For "Our team {{answer}} new features." the answers are [["develops","builds"]], not [["develops","builds"],["new features"]] (1 blank vs 2 slots — the import rejects it).

Every equally valid form goes into the slot — not just one "canonical" one. Typing is graded character by character: a correct form the slot does not list is marked wrong and drops the card into relearning. So the slot holds everything you would accept yourself:

  • politeness and who is addressed: успокойтесь / успокойся;
  • gender and number when the prompt does not fix them: оба / обе, рад / рада;
  • aspect where both fit: остыть / остывать;
  • equally good translations: till / until;
  • senses of a polysemous word the prompt does not tell apart: fairсправедливый / ярмарка;
  • a function word that may be dropped: to go for a walk / go for a walk.

Letter case, ё/е, the flavour of a quote and trailing punctuation are not answers — the app levels those itself, so do not spell such spellings out. The main form still comes first in the slot: that is the one the card reveals as the correct answer.

{ "front": "Calm down", "back": "Успокойтесь",
  "modes": [
    { "type": "Flip" },
    { "type": "Type", "data": { "answers": [["Успокойтесь", "Успокойся"]] } }
  ] }

When the correct answer is "no word belongs here" — the zero article, the zero preposition — the accepted form is the empty string, and back is empty too. Never invent a stand-in token (, 0, no article): the app renders the empty answer with its own label, so the learner leaves the field empty in typed modes and picks a "no word" option in choice modes.

{ "front": "article with most country names (France, Russia)", "back": "",
  "modes": [
    { "type": "Flip" },
    { "type": "Choice", "data": { "distractors": ["a", "an", "the"] } },
    { "type": "ClozeType", "data": { "sentence": "She lives in {{answer}} France.", "answers": [[""]] } },
    { "type": "ClozeChoice", "data": { "sentence": "She lives in {{answer}} France.", "answers": [[""]], "distractors": ["a", "an", "the"] } }
  ] }

Answer texts must not contain the | character (it is reserved as a separator).

The dictionary-form trap (citation vs in-context)

A word in its dictionary form carries service elements that must not appear inside a sentence:

  • the infinitive to: to go for a walk → in a sentence "we often go for a walk";
  • an article: an apple → "I ate the apple";
  • a copula: be keen on → "he is keen on …";
  • conjugation: wait for → "I'm waiting for …".

The rule: in a sentence/answer use the form the word actually takes in context. When it differs from the canonical one, put both into the slot, the in-context form first: [["go for a walk","to go for a walk"]].

Recipes by data type

Below, data is shown as an object — that is what the card form's JSON tab and the deck import accept. (In the raw POST /api/cards API, data is a JSON string: the same object serialized.)

Fact / formula / definition → profile Fact

{ "front": "Площадь круга", "back": "πr²",
  "modes": [ { "type": "Flip" }, { "type": "ReverseFlip" } ] }

Minimal — self-assessment only. When plausible wrong values of the same kind exist, add Choice with distractors (facts are auto-checked too — that does not make them "vocabulary").

Word → translation → profile Lexical / translation

{ "front": "яблоко", "back": "apple",
  "modes": [
    { "type": "Flip" }, { "type": "ReverseFlip" },
    { "type": "Type" },
    { "type": "Choice",  "data": { "distractors": ["banana","orange","grape"] } },
    { "type": "ClozeType", "data": { "sentence": "I eat an {{answer}} every day.", "answers": [["apple"]] } }
  ] }

Synonyms / gender variants → one answers slot

Storing front: "оба, обе" is wrong (the learner would have to type it literally, comma and all). Instead: the canonical form plus accepted variants on the answer side:

{ "front": "оба", "back": "both",
  "modes": [
    { "type": "ReverseType", "data": { "answers": [["оба","обе"]] } },
    { "type": "Type" }
  ] }

Now ReverseType accepts both оба and обе.

A polysemous word (several senses) → one card, one case per sense

The forward side of such cases is unambiguous (справедливыйfair, ярмаркаfair), but the reverse side breaks: every case prompts with the same word — fair — while only that case's own sense counts as correct, so the learner has to guess which one is being asked. context cannot help here: it is displayed in direct modes only.

The fix lives on the answer side, and it is the same mechanism synonyms use: the answers slot of each reverse mode lists every sense (the case's own first — that is the one shown as the correct answer), and a sibling sense never appears among ReverseChoice distractors, where it would be a second correct option.

{ "title": "fair",
  "cases": [
    { "front": "справедливый", "back": "fair",
      "modes": [
        { "type": "Flip" },
        { "type": "Choice", "data": { "distractors": ["unfair", "honest", "equal"] } },
        { "type": "ReverseChoice", "data": { "distractors": ["честный", "равный", "нечестный"] } },
        { "type": "ReverseType", "data": { "answers": [["справедливый", "ярмарка"]] } },
        { "type": "ClozeType", "data": { "sentence": "The judge made a {{answer}} decision.", "answers": [["fair"]] } }
      ] },
    { "front": "ярмарка", "back": "fair",
      "modes": [
        { "type": "Flip" },
        { "type": "Choice", "data": { "distractors": ["market", "festival", "exhibition"] } },
        { "type": "ReverseChoice", "data": { "distractors": ["рынок", "фестиваль", "выставка"] } },
        { "type": "ReverseType", "data": { "answers": [["ярмарка", "справедливый"]] } },
        { "type": "ClozeType", "data": { "sentence": "We went to a street food {{answer}}.", "answers": [["fair"]] } }
      ] }
  ] }

One word, one card: the senses are learned and scheduled together instead of competing for the same prompt from separate cards. ReverseFlip is safe to keep — it is self-assessed, so the learner credits their own sense. Match is safe too: two tiles with identical text never share a round. title earns its place here — it names the word itself, which appears in no front.

Dictionary form with to / an article → in-context form + accepted variant

{ "front": "идти на прогулку", "back": "to go for a walk",
  "modes": [
    { "type": "Type", "data": { "answers": [["to go for a walk","go for a walk"]] } },
    { "type": "ClozeType", "data": {
        "sentence": "After dinner we often {{answer}} in the park.",
        "answers": [["go for a walk","to go for a walk"]] } }
  ] }

In the sentence — go for a walk (the in-context form first); the dictionary form is kept as an accepted variant.

Discontinuous expression from … till … → one slot per part

{ "front": "с … до …", "back": "from … till …",
  "modes": [
    { "type": "ClozeType", "data": {
        "sentence": "The shop is open {{answer}} 9 a.m. {{answer}} 6 p.m.",
        "answers": [["from"],["till","until"]] } },
    { "type": "ClozeChoice", "data": {
        "sentence": "The shop is open {{answer}} 9 a.m. {{answer}} 6 p.m.",
        "answers": [["from"],["till","until"]],
        "distractors": ["at","on","in"] } }
  ] }

Two {{answer}} blanks ↔ two slots. In ClozeChoice the button shows the canonical variant (from / till); until is never offered as a (wrong) button.

Irregular verb (3 forms) → 3 blanks

{ "front": "идти", "back": "go, went, gone",
  "modes": [
    { "type": "ClozeType", "data": {
        "sentence": "{{answer}}, {{answer}}, {{answer}}",
        "answers": [["go"],["went"],["gone"]] } }
  ] }

Each form is checked on its own, instead of "guess the punctuation" of one long string.

Grammar rule → one card, many cases, blank at the decision point

The learner keeps mixing up do/does. Wrong: one card per corrected sentence — the sentence gets memorized, the rule doesn't. Right: one rule card where every case is a different sentence, the blank sits exactly where the decision happens, and the distractors are the forms actually being confused:

{ "title": "Present Simple questions: do or does?",
  "explanation": "he/she/it → does; I/you/we/they → do. After does the main verb returns to its base form.",
  "cases": [
    { "front": "Она живёт в Польше?", "back": "Does she live in Poland?",
      "modes": [
        { "type": "ClozeChoice", "data": { "sentence": "{{answer}} she live in Poland?", "answers": [["Does"]], "distractors": ["Do", "Did", "Is"] } },
        { "type": "ClozeType", "data": { "sentence": "{{answer}} she live in Poland?", "answers": [["Does"]] } },
        { "type": "Flip" }
      ] },
    { "front": "Ты работаешь по выходным?", "back": "Do you work on weekends?",
      "modes": [
        { "type": "ClozeChoice", "data": { "sentence": "{{answer}} you work on weekends?", "answers": [["Do"]], "distractors": ["Does", "Did", "Are"] } },
        { "type": "ClozeType", "data": { "sentence": "{{answer}} you work on weekends?", "answers": [["Do"]] } },
        { "type": "Flip" }
      ] },
    { "front": "Почему он изучает английский?", "back": "Why does he study English?",
      "modes": [
        { "type": "ClozeChoice", "data": { "sentence": "Why {{answer}} he study English?", "answers": [["does"]], "distractors": ["do", "did", "is"] } },
        { "type": "ClozeType", "data": { "sentence": "Why {{answer}} he study English?", "answers": [["does"]] } },
        { "type": "Flip" }
      ] }
  ] }

A real card continues to 6–12 cases: vary the subjects, verbs and topics, and invent new sentences beyond the ones the learner already saw. Each review shows one random case, so the schedule tracks the rule, not any single sentence. Every case and every mode stays on the same decision the card is about — here the blank is always at do/does. A mode that blanks a different word (say, the main verb) tests different knowledge and belongs on a different card.

A per-case context is legal in a rule card only when the front admits several correct answers. Articles are the canonical example: a Russian front has no articles, so for front "Я вижу птицу." both I see a bird and I see the bird are right — context "какую-то, не конкретную" picks the intended meaning, and without that cue the distractor the would be a second correct option (an invalid choice mode). Never use context to restate the rule's trigger — context "university starts with the consonant sound [j]" on an a/an card gives the answer away before recall. When a case has only one correct answer, leave context null; the rule recap lives in the card's explanation, shown after answering.

An article card also has cases where the right answer is no article at all. Write that as the empty string — in back and in the answer slot — and keep the full mode set: the zero article is exactly the decision the learner must be able to produce, so it must not be tested only by picking from a list.

{ "front": "артикль с большинством стран (Франция, Россия)", "back": "",
  "modes": [
    { "type": "Flip" },
    { "type": "Choice", "data": { "distractors": ["a", "an", "the"] } },
    { "type": "ClozeType", "data": { "sentence": "She lives in {{answer}} France.", "answers": [[""]] } },
    { "type": "ClozeChoice", "data": { "sentence": "She lives in {{answer}} France.", "answers": [[""]], "distractors": ["a", "an", "the"] } }
  ] }

Its sibling cases ("back": "the" for the UK, "back": "a" for a doctor) carry "" among their distractors for the same reason: "no article" has to stay a live option everywhere, or the learner picks the right article by elimination.

Confusable words → one discrimination card, cases alternate the correct member

The learner mixes up speak (can use a language) and learn (the process of studying it). One card per confusable set; the other members are the distractors, and the cases alternate which member is correct — so the learner has to discriminate, not pattern-match one fixed answer:

{ "title": "speak vs learn",
  "explanation": "speak = уметь говорить на языке; learn = учить, осваивать (процесс).",
  "cases": [
    { "front": "говорить (на языке)", "back": "speak",
      "modes": [
        { "type": "Flip" }, { "type": "Match" },
        { "type": "ClozeChoice", "data": { "sentence": "Do you {{answer}} Polish?", "answers": [["speak"]], "distractors": ["learn", "study", "talk"] } },
        { "type": "ClozeType", "data": { "sentence": "Do you {{answer}} Polish?", "answers": [["speak"]] } }
      ] },
    { "front": "учить, осваивать (язык)", "back": "learn",
      "modes": [
        { "type": "Flip" }, { "type": "Match" },
        { "type": "ClozeChoice", "data": { "sentence": "I {{answer}} Polish and English.", "answers": [["learn", "study"]], "distractors": ["speak", "talk"] } },
        { "type": "ClozeType", "data": { "sentence": "I {{answer}} Polish and English.", "answers": [["learn", "study"]] } }
      ] }
  ] }

This is a word card, so front/back carry only the word and its meaning — the context sentences live inside the cloze modes' data. That keeps Flip clean (word ↔ meaning, not a sentence pair) and unlocks Match, the fastest mode for running through many word cards at once. When several members genuinely fit a sentence, accept them all in one answers slot (as learn / study above) — a distractor must never coincide with an accepted variant. When the sentence alone does not force one reading, add a per-case context cue instead of distorting the sentence.

One word, several contexts → one card, a case per context

The learner misused a single word (make a service → should be develop a service). Focus the card on that word and show it working in different sentences — one random case per review:

{ "title": "Collocation: develop (software)",
  "explanation": "develop / build a service, an app — not \"make a service\".",
  "cases": [
    { "front": "разрабатывать (сервис, приложение)", "back": "develop",
      "modes": [
        { "type": "Flip" }, { "type": "ReverseFlip" }, { "type": "Type" },
        { "type": "ClozeType", "data": { "sentence": "I {{answer}} a spaced repetition service.", "answers": [["develop", "build"]] } }
      ] },
    { "front": "разрабатывать (сервис, приложение)", "back": "develop",
      "modes": [
        { "type": "ClozeChoice", "data": { "sentence": "We {{answer}} mobile apps for banks.", "answers": [["develop", "build"]], "distractors": ["make", "do", "invent"] } },
        { "type": "ClozeType", "data": { "sentence": "Our team {{answer}} new features every month.", "answers": [["develops", "builds"]] } }
      ] }
  ] }

The typed answer is always the word, never the whole sentence. Note the second case's ClozeType: the in-context form (develops) comes first in its slot, per the answer-slot rules.

Fact with distractors (road-rules style, native language)

{ "front": "Что означает сплошная линия разметки?", "back": "Пересекать запрещено",
  "modes": [
    { "type": "Flip" },
    { "type": "Choice", "data": {
        "distractors": ["Можно перестраиваться","Только для автобусов","Парковка разрешена"] } }
  ] }

Distractors are plausible but wrong facts. (The "translation" framing is wrong here — this is a fact intent deck.)

The text format (cards)

Cards can be written as plain text instead of JSON — the shape the "Your AI" prompts ask a chatbot for, and the easiest one to write by hand. A card names what it knows — its sides, the forms it accepts, the wrong options, a sentence with a blank — and the modes are assembled from that and the deck's mode menu. The same cards take about a third of the characters they take as JSON, a cut-off answer loses one card instead of the whole deck, and the import preview says card by card what it could not read. The "Import deck" dialog, the paste boxes of the AI paths and the lesson result all read it; machines get the contract at /prompts/v2/card-format.

Deck text contract (the cards format). What the "Import deck" dialog, the "Your AI" paste boxes and the lesson result read — next to the older deck JSON, which they still accept. A document is a header (deck keys) followed by cards. Every line is key: value with the key in column 0; a card names the facts it knows — its sides, accepted forms, wrong options, a sentence with a blank — and never its modes: those are assembled from the facts and the deck's mode menu (see the facets table below).

deck: English basics
description: Core vocabulary, first 100 words.
front-language: ru
back-language: en
modes: Flip | ReverseFlip | Match | Type | Choice | ClozeType | ClozeChoice
---
front: яблоко
back: apple
wrong: banana | orange | grape
cloze: I eat an {{apple}} every day.
---
note: till and until are interchangeable; from opens the interval.
front: с … до …
back: from … till …
cloze: The shop is open {{from}} 9 a.m. {{till|until}} 6 p.m.
cloze-wrong: at | on | in

Grammar:

  • --- on a line of its own starts a new card. case: (its value is an optional label) starts another case of the same card — a rule card with many example sentences, a word with several senses. A second front: with neither in between is read as a new card.
  • A value continues on the following lines when they are indented by at least one space (Markdown inside a side, a multi-line note). A line with no key and no indent is ignored.
  • Listswrong, accept, front-wrong, front-accept, cloze-wrong, tags, modes — separate items with |. Write "" for the empty option ("no word belongs here").
  • Nothing else is escaped or quoted. Reserved: a key in column 0, --- in column 0, | inside a list, {{ }} inside cloze.
  • Print the whole document inside one fenced ```cards block; anything outside the fence is ignored, so no other text belongs inside it.

Keys:

Where Key Meaning JSON name
header deck deck name (required) title
header description one or two sentences about the deck description
header front-language, back-language language codes (ru, en, …) of the question side — the learner's own language — and of the studied side, which drives pronunciation frontLanguage, backLanguage
header modes the deck's mode menu: every mode a card may get. A card gets those of them its facts and the size rules allow
header tags, visibility (private / unlisted / public) optional tags, visibility
card title optional label (a grammar tag, a topic); never a copy of the front title
card note note shown after the answer — a rule recap, a mnemonic; it may name the answer explanation
card format markdown when a side uses Markdown; plain text by default contentFormat
case front question side (required) — the one clean term, no asides in brackets front
case back answer side — one canonical form; empty when the answer is "no word" back
case context cue shown with the question — ONLY when the front admits more than one correct answer; never hints the answer or the rule context
case accept other typed forms of the back the learner may enter (accept: go for a walk) Typeanswers
case front-accept other typed forms of the front ReverseTypeanswers
case wrong three wrong options in the back language Choicedistractors
case front-wrong three wrong options in the front language ReverseChoicedistractors
case cloze one sentence with the answer inside {{ }} — see the blanks rules sentence + answers
case cloze-wrong three wrong options for the blank ClozeChoicedistractors

Never write front-image, back-image, back-audio or front-audio: pictures are uploaded by the deck owner, pronunciation is attached by the server — an invented link is a broken one (E19).

Where a rule below speaks in the JSON names, read it through the last column: a "slot" is a {{a|b}} group in cloze, or the back together with its accept list; "distractors" are wrong, front-wrong and cloze-wrong; "sentence" is cloze; explanation is note; a mode's "data" is these facts.

How facts become modes. A card never lists its modes. From the deck's modes menu each case gets:

Fact on the case Mode it enables Only when
Flip, ReverseFlip in the menu; ReverseFlip needs a non-empty back
Match in the menu and both sides are word-sized
back (+ accept) Type in the menu and the back is a word or a short phrase — never a whole sentence
front (+ front-accept) ReverseType in the menu and the front is a word or a short phrase
wrong Choice in the menu
front-wrong ReverseChoice in the menu
cloze ClozeType in the menu
cloze + cloze-wrong ClozeChoice in the menu
cloze + wrong, no cloze-wrong Choice and ClozeChoice share the wrong list the blank's answer is the back itself

So a sentence-sized card (a grammar rule drilled by example sentences) naturally gets the cloze modes and Flip but no typed side, and a word card gets Flip / ReverseFlip / Match / Type plus whatever its facts add. To keep a mode off one card, leave its fact out: no wrong: — no Choice. Give a fact only when you can fill it well — three plausible wrong options, a natural sentence with the blank at the decision point; a weak fact is worse than none.

Blanks and accepted forms (important). The answer of a blank sits inside the sentence:

front: Она живёт в Польше?
back: Does she live in Poland?
cloze: {{Does}} she live in Poland?
cloze-wrong: Do | Did | Is

Two different meanings of "several answers" — do not mix them up:

  • Synonyms / alternatives — ANY of them counts as correct (till / until; оба / обе) → one group, separated by |, the in-context form first: {{till|until}}. The first one is what the card reveals as the correct answer.
  • Sequence / separate blanks — ALL parts are required, each in its own place (the three forms of an irregular verb; a discontinuous from … till …) → one group per blank: cloze: The shop is open {{from}} 9 a.m. {{till|until}} 6 p.m.
  • Different senses of one word (fair = «справедливый» and «ярмарка») behave like synonyms, but only on the side where the question does not tell them apart: each sense is its own case with its own front, and the reverse side accepts every sense (E18).

A group exists only for a blank — nothing that stays visible in the sentence is an answer, and nothing outside {{ }} is. Our team {{develops|builds}} new features. has one blank and one group.

Every equally valid form goes into the group — not just one "canonical" one. Typing is graded character by character: a correct form you did not list is marked wrong and drops the card into relearning. So list everything you would accept yourself:

  • politeness and who is addressed: {{успокойтесь|успокойся}};
  • gender and number when the prompt does not fix them: {{оба|обе}}, {{рад|рада}};
  • aspect where both fit: {{остыть|остывать}};
  • equally good translations: {{till|until}};
  • senses of a polysemous word the prompt does not tell apart;
  • a function word that may be dropped: {{go for a walk|to go for a walk}}.

Letter case, ё/е, the flavour of a quote and trailing punctuation are not answers — the app levels those itself, so do not spell such spellings out.

The same rule holds for the typed answer of the card itself: back holds one canonical form and accept lists the others (back: Успокойтесь / accept: Успокойся; back: to go for a walk / accept: go for a walk). For the front side it is front-accept.

When the correct answer is "no word belongs here" — the zero article, the zero preposition — the blank is empty and back is empty too, consistently in every fact of the case. Never invent a stand-in token (, 0, no article): the app renders the empty answer with its own label, so the learner leaves the field empty in typed modes and picks a "no word" option in choice modes.

front: article with most country names (France, Russia)
back:
wrong: a | an | the
cloze: She lives in {{}} France.

Its sibling cases (back: the for the UK, back: a for a doctor) carry "" among their wrong options for the same reason: "no article" has to stay a live option everywhere, or the learner picks the right article by elimination.

Answers and options must not contain the | character — it separates alternatives and list items.

deck: English basics — sample
description: A tiny sample deck showing every key.
front-language: ru
back-language: en
modes: Flip | ReverseFlip | Match | Type | ReverseType | Choice | ReverseChoice | ClozeType | ClozeChoice
---
front: яблоко
back: apple
wrong: banana | orange | grape
cloze: I eat an {{apple}} every day.
---
front: язык
back: tongue
context: орган
front-wrong: зуб | нос | ухо
---
title: Phrasal verb
front: идти на прогулку
back: to go for a walk
accept: go for a walk
cloze: After dinner we often {{go for a walk|to go for a walk}} in the park.
---
note: till и until взаимозаменяемы; from задаёт начало интервала.
front: с … до …
back: from … till …
cloze: The shop is open {{from}} 9 a.m. {{till|until}} 6 p.m.
cloze-wrong: at | on | in
---
note: be – was/were – been.
front: быть (3 формы)
back: be – was/were – been
cloze: {{be}}, {{was|were}}, {{been}}
case:
front: он усталый (Present Simple, to be)
back: he is tired
front-accept: он устал

The JSON format (machine contract)

The older, fully explicit form: every case lists its modes with their data. The "Import deck" dialog and every paste box still accept it, and it is what exports and the API speak. Served to machines at /prompts/v1/card-format.

Deck JSON contract. The complete deck object — what the "Import deck" dialog and POST /api/decks/import-json accept. Cards carry no deckIds: the deck itself is created by the import.

{
  "title": "string",                  // deck name (required)
  "description": "string | null",
  "frontLanguage": "ru",              // language of the question side (front) — the learner's native language (optional)
  "backLanguage": "en",               // language of the studied side (back) — drives pronunciation (optional; null when not applicable)
  "isPublic": false,
  "cards": [
    {
      "title": "string | null",       // optional label; never copy the front — set it only when it adds information (see the hint rules)
      "explanation": "string | null", // post-answer note (rule recap / mnemonic); MAY reference the answer
      "contentFormat": "PlainText",   // or "Markdown"
      "cases": [
        {
          "front": "string",          // question side (usually the native language)
          "back": "string",           // answer side (usually the studied language)
          "context": "string | null", // cue shown WITH the question; set ONLY when several answers would be correct without it; never hints the answer or the tested rule
          "backAudio": null,          // pronunciation mp3 URL for the back word — ALWAYS null (see the backAudio rule)
          "frontImage": null,         // picture shown WITH the question — ALWAYS null (see the images rule)
          "backImage": null,          // picture revealed after the answer — ALWAYS null (see the images rule)
          "modes": [
            { "type": "Flip", "data": null }   // "type": a mode name; "data": object or null per the mode table below
          ]
        }
      ]
    }
  ]
}

type is one of: Flip, ReverseFlip, Choice, ReverseChoice, Match, ClozeType, ClozeChoice, Type, ReverseType.

The import dialog also accepts a bare array of cards ([ { "cases": … }, … ]) — the deck title is then taken from the dialog's name field. A single card (with deckIds) can be pasted into the JSON tab of the card form.

data by mode:

Mode data Meaning
Flip, ReverseFlip, Match null no extra data
Type { "answers": [[ ... ]] } (optional) one slot — accepted forms of back
ReverseType { "answers": [[ ... ]] } (optional) one slot — accepted forms of front
Choice { "distractors": [ 3 items ] } wrong options in the back language
ReverseChoice { "distractors": [ 3 items ] } wrong options in the front language
ClozeType { "sentence": "... {{answer}} ...", "answers": [[ ... ]] } blanks + answer slots
ClozeChoice { "sentence": "...", "answers": [[ ... ]], "distractors": [ ... ] } blanks + slots + wrong options

Generation rules (Lexical):

  • L1. Write every blank/answer in the form it takes in the sentence (drop the dictionary "to", conjugate for the subject, drop an article the sentence already provides) — per the grammar of the language in question. When the form the sentence takes is no word at all (zero article, zero preposition), write the empty string, never a stand-in token.
  • L2. When the in-context form differs from the source word, include both, the in-context form first.
  • L3. Synonyms/variants are separate slot elements — never joined with commas inside one element.
  • L4. A discontinuous expression gets one blank/slot per part.
  • L5. Distractors are plausible but wrong, the same kind of word as the answer, and never duplicate any accepted variant.
  • L6. The sentence is natural and grammatical.

backAudio (pronunciation). Audio voices the answer word (back) and appears as a ▶ button next to it in every mode. Never invent the URL: dictionary URLs (e.g. api.dictionaryapi.dev) follow no predictable pattern, so a guessed link is almost always broken. Always output backAudio: null (or omit the field) — the real link is attached by the server, which queries a dictionary API. Audio only makes sense for single words of the studied language; phrases and sentences have none.

frontImage / backImage (pictures). frontImage is shown with the question (the picture is part of the prompt); backImage is revealed only after the answer, exactly like pronunciation. Do not invent links: an image URL cannot be derived from a name — a made-up one is almost always broken, and there is no source to substitute a working one from. Always set frontImage: null and backImage: null (or omit the fields) — the deck owner uploads pictures themselves in the card form. The one exception: the user gave you a direct https link to a specific image, which you may then pass through as-is.

Intent (intent) — determines the framing:

intent When front / back Profile
translation learning words/expressions/grammar of another language native ↔ studied Lexical / translation
definition term ↔ meaning in one language (biology, law, terminology) term ↔ definition Lexical / translation
fact question ↔ fact (road rules, history, formulas) question/concept ↔ fact/value Fact (+ Choice/Match when plausible distractors exist)

Knowledge types → card shape (decide this BEFORE writing any card):

A card is a unit of knowledge, not a single question. First classify what is being learned, then shape the card from the type. Never emit one card per example sentence: cluster the material by the underlying rule / word / contrast and put the examples into the cases of one card — a random case is shown on each review, so the learner masters the pattern instead of memorizing one string.

Knowledge type Example Card shape Core modes Distractors
Rule / pattern — a form choice (do/does, article, verb form, ending) questions with does 1 rule = 1 card, 6–12 cases: different sentences applying the same rule ClozeChoice + ClozeType, blank at the decision point; optional Flip minimal pairs: do/does/did, work/works
Word order / position usually before the main verb 1 pattern = 1 card, 5–8 cases Choice (whole sentences differing only in order), Flip same words, wrong order
Confusable set (interference) speak vs learn vs study 1 set = 1 card; front/back = the member + its meaning; cases alternate which member is correct ClozeChoice with the other members as distractors, ClozeType, Flip/Match; a context cue when the sentence alone is ambiguous the other members of the set — that is the point of the card
Word / collocation develop a service 1 word = 1 card, 2–5 cases: the same word in different sentences Flip/ReverseFlip/Type/Match (the word only), ClozeType per context near-synonyms that are wrong here
Spelling study, not stady 1 word = 1 card Type/ClozeType — typing the word IS the check not needed
Fact / definition capital of X; term ↔ meaning 1 fact = 1 card, 1 case Flip/ReverseFlip; Choice/Match only when plausible wrong facts of the same kind exist; Cloze/Type usually unnecessary plausible facts of the same kind
  • Test one decision per prompt. Typing a whole sentence checks five things at once and blurs the error signal; a cloze blank at the exact decision point isolates what is being trained.
  • Every case and every mode tests the card's one decision. A do/does card never blanks the main verb in one of its modes — a different decision belongs on a different card.
  • A polysemous word is one card with a case per sense. fair = «справедливый» and «ярмарка» are not two cards: they share one reverse prompt, and apart they turn the reverse modes into a guessing game. Keep the senses in one card and list them all in the answers slot of its reverse modes (E18).
  • Word cards keep front/back to the word itself (word ↔ meaning), never a sentence; the context sentences live in the ClozeChoice/ClozeType data. That keeps Flip clean and unlocks Match — the fastest mode to drill many word cards in one go.
  • Letter case can only be tested by choice. Typed answers are graded case-insensitively, so a capitalization rule (English, not english) needs Choice/ClozeChoice with case-variant distractors (English vs english) — a Type/ClozeType check would silently accept the lowercase form.
  • Production beats recognition. Choice/ClozeChoice are stepping stones — pair them with a typed form (ClozeType/Type) so the knowledge is eventually produced, not just recognized.
  • Rule cards need fresh examples. Vary subjects, verbs and topics beyond the sentences the learner already saw — otherwise the card tests memory of the lesson, not the rule.
  • Plain vocabulary (translation intent) keeps the classic base set: Flip, ReverseFlip, Type, Choice, ClozeType (optionally ReverseChoice, ClozeChoice, ReverseType, Match).
  • Simplify by default. No heavy markup when it adds no value: for 3-form irregular verbs, back: "go, went, gone" + Flip/ReverseFlip/Type is enough.

Validity checklist:

  • E1. Every case has a front and at least one mode (back may be empty — see E16).
  • E2. The number of {{answer}} blanks in sentence equals the number of slots in answers.
  • E3. Every slot is a non-empty array of strings, the in-context form first. A string in it may be empty — that is the answer "no word belongs here" (E16).
  • E4. Synonyms are separate slot elements — never "a, b" as one string.
  • E5. The in-context form is grammatical in its sentence (no "we often to go", no "is be keen on").
  • E6. Distractors are wrong and never coincide with any accepted variant.
  • E7. Self-assessment cards (only Flip/ReverseFlip) carry no distractors/sentences in data.
  • E8. Answer texts contain no | character (it is a reserved separator).
  • E9. Typed answers (Type/ReverseType, cloze slots) are a word or short phrase — never a whole sentence. To test a decision inside a sentence, use ClozeType/ClozeChoice with the blank at that exact point.
  • E10. A rule/pattern card carries several cases (aim for 6+), each a different example sentence; one rule is never split into one card per sentence.
  • E11. Choice/ClozeChoice distractors are minimal pairs of the tested decision (do/does/did) — wrong here, yet plausibly confusable; never random unrelated words.
  • E12. A distinction typed grading cannot see — letter case alone (English vs english) or ё/е alone (всё vs все) — is tested with Choice/ClozeChoice, never with Type/ClozeType: typed answers are graded case-insensitively and with ё folded to е, so the wrong form would be accepted.
  • E13. Every case and every mode of a card tests the card's one decision. A do/does card never blanks the main verb in one of its modes — a different decision is a different card.
  • E14. Word cards keep front/back to the word itself (word ↔ meaning), never a whole sentence; the context sentences go into cloze data. That keeps Flip clean and unlocks Match. And to one form, not a list: "upside down; inverted; wrong way up" reaches the learner as an enumeration in Match and in the ReverseChoice options, and in typed modes it would have to be typed out in full, semicolons and all. Equally good wordings are variants of the slot (E17); different senses are different cases with a context (E15).
  • E15. context is set only when the front admits more than one correct answer; it picks the intended reading and never hints at the answer or the rule being drilled (rule recaps live in explanation).
  • E16. When the correct answer is the absence of a word (zero article, zero preposition), it is written as the empty string — in back and in the answer slot alike, consistently across every mode of the case. Never a stand-in token (, 0, no article): the app supplies its own label.
  • E17. Every form the author would accept is its own variant of the slot: politeness (успокойтесь/успокойся), gender and number (оба/обе), equally good synonyms (till/until). Listing them inside one string ("оба, обе") does not work — the learner would have to type that list verbatim, comma and all. Letter case, ё/е and edge punctuation need no listing. The converse holds too: an answer the learner owes in full ("red, green, blue") and a single slashed term (and/or) are one variant and must not be split.
  • E18. One question, one set of right answers. Two cases of a card (or two cards of a deck) must not answer the same prompt differently — the learner would be guessing which one is being asked. On the forward side (same front, different back) a distinct context per case settles it (E15). On the reverse side (same back, different front — a polysemous word) context cannot: reverse modes never render it. There the ReverseType of each such case lists all senses in its slot (its own first), and ReverseChoice never takes a sibling sense as a distractor. When neither is done, leave those cases with direct modes only.
  • E19. Never invent a picture link. frontImage/backImage take either a /media/card/… url the site itself issued on upload, or an https url the user handed you — nothing else. A guessed url is a broken picture, and a broken picture is worse than none.

Creating cards with AI

You do not have to author cards by hand — there are three paths:

  • Basic AI — the "Create with AI" button on the decks page: describe the deck in free text, edit the plan and get ready cards.
  • Your own AI — the same dialog assembles a ready prompt: copy it into any chatbot (ChatGPT, Claude, Gemini) and paste the answer back — the ```cards block it prints, or JSON if it insists. Field enrichment in the card form and in bulk edit works the same way.
  • An external chat after a lesson — if you have just studied a topic with an AI chat, give it the /prompts/v2/deck-builder link: it will ask a couple of clarifying questions about your weak spots, build a deck and hand you the text to import.

Importing

  1. Open the decks page and press "Import deck" (or follow /decks?import=1 — the dialog opens by itself).
  2. Paste the text: the dialog reads a ```cards block, a deck JSON object { "title", …, "cards": [ … ] }, a bare card array [ { "cases": … }, … ] or one front — back pair per line — the title is taken from the text when it names one, else from the dialog's name field.
  3. Read the preview — how many cards were found and, card by card, anything that could not be read — and confirm: the deck and all its cards are created in one step.

A single card can be pasted into the JSON tab of the card form.

Complete deck example

A valid sample deck where every mode appears at least once — you can paste it into the "Import deck" dialog as is:

{
  "title": "English basics — sample",
  "description": "A tiny sample deck showing every mode and field.",
  "isPublic": false,
  "frontLanguage": "ru",
  "backLanguage": "en",
  "cards": [
    {
      "cases": [
        {
          "front": "яблоко",
          "back": "apple",
          "backAudio": null,
          "modes": [
            { "type": "Flip" },
            { "type": "ReverseFlip" },
            { "type": "Match" },
            { "type": "Type" },
            { "type": "Choice", "data": { "distractors": ["banana", "orange", "grape"] } },
            { "type": "ClozeType", "data": { "sentence": "I eat an {{answer}} every day.", "answers": [["apple"]] } }
          ]
        }
      ]
    },
    {
      "cases": [
        {
          "front": "язык",
          "back": "tongue",
          "context": "орган",
          "modes": [
            { "type": "Flip" },
            { "type": "Type" },
            { "type": "ReverseChoice", "data": { "distractors": ["зуб", "нос", "ухо"] } }
          ]
        }
      ]
    },
    {
      "title": "Phrasal verb",
      "cases": [
        {
          "front": "идти на прогулку",
          "back": "to go for a walk",
          "modes": [
            { "type": "Type", "data": { "answers": [["to go for a walk", "go for a walk"]] } },
            { "type": "ClozeType", "data": { "sentence": "After dinner we often {{answer}} in the park.", "answers": [["go for a walk", "to go for a walk"]] } }
          ]
        }
      ]
    },
    {
      "explanation": "till и until взаимозаменяемы; from задаёт начало интервала.",
      "cases": [
        {
          "front": "с … до …",
          "back": "from … till …",
          "modes": [
            { "type": "ClozeChoice", "data": { "sentence": "The shop is open {{answer}} 9 a.m. {{answer}} 6 p.m.", "answers": [["from"], ["till", "until"]], "distractors": ["at", "on", "in"] } }
          ]
        }
      ]
    },
    {
      "explanation": "be – was/were – been.",
      "cases": [
        {
          "front": "быть (3 формы)",
          "back": "be – was/were – been",
          "modes": [
            { "type": "Flip" },
            { "type": "ClozeType", "data": { "sentence": "{{answer}}, {{answer}}, {{answer}}", "answers": [["be"], ["was", "were"], ["been"]] } }
          ]
        },
        {
          "front": "он усталый (Present Simple, to be)",
          "back": "he is tired",
          "modes": [
            { "type": "ReverseType", "data": { "answers": [["он усталый", "он устал"]] } }
          ]
        }
      ]
    }
  ]
}