How to author flashcards — the RepeatMe guide
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/backpair. One case = a regular card. Several cases = a "rule card" (e.g. the conjugation ofto 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/Matchwhen 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/fronthold 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:
contextis 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 istongue, notlanguage. 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,contextMUST stay null — null is the default.contextclarifies 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 inexplanation. A learner who does not know the rule must learn nothing fromcontext.contextis shown only when the prompt is thefrontside (direct modes:Flip,Type,Choice,ClozeType,ClozeChoice); reverse modes andMatchdo not display it. Socontextcannot resolve ambiguity on the reverse side: when onebackanswers several different fronts (a polysemous word), the senses are listed in theanswersof the reverse modes — see E18. Keep the cue incontextonly — never bake it intofrontitself (front"высокий", context"о росте"— NOT front"высокий (о росте)"): anything insidefrontbecomes part of the term in reverse modes, choice options, typed answers and term listings.frontholds the clean term only.explanationis 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 theanswersof 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 secondfront: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.
- Lists —
wrong,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,{{ }}insidecloze. - 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) |
Type → answers |
| case | front-accept |
other typed forms of the front | ReverseType → answers |
| case | wrong |
three wrong options in the back language | Choice → distractors |
| case | front-wrong |
three wrong options in the front language | ReverseChoice → distractors |
| case | cloze |
one sentence with the answer inside {{ }} — see the blanks rules |
sentence + answers |
| case | cloze-wrong |
three wrong options for the blank | ClozeChoice → distractors |
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 theanswersslot of its reverse modes (E18). - Word cards keep
front/backto the word itself (word ↔ meaning), never a sentence; the context sentences live in theClozeChoice/ClozeTypedata. That keepsFlipclean and unlocksMatch— 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/ClozeChoicewith case-variant distractors (Englishvsenglish) — aType/ClozeTypecheck would silently accept the lowercase form. - Production beats recognition.
Choice/ClozeChoiceare 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 (
translationintent) keeps the classic base set:Flip,ReverseFlip,Type,Choice,ClozeType(optionallyReverseChoice,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/Typeis enough.
Validity checklist:
- E1. Every case has a
frontand at least one mode (backmay be empty — see E16). - E2. The number of
{{answer}}blanks insentenceequals the number of slots inanswers. - 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 indata. - 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, useClozeType/ClozeChoicewith 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/ClozeChoicedistractors 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 (
Englishvsenglish) orё/еalone (всёvsвсе) — is tested withChoice/ClozeChoice, never withType/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/backto the word itself (word ↔ meaning), never a whole sentence; the context sentences go into clozedata. That keepsFlipclean and unlocksMatch. And to one form, not a list:"upside down; inverted; wrong way up"reaches the learner as an enumeration inMatchand in theReverseChoiceoptions, 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 acontext(E15). - E15.
contextis 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 inexplanation). - E16. When the correct answer is the absence of a word (zero article, zero preposition), it is
written as the empty string — in
backand 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, differentback) a distinctcontextper case settles it (E15). On the reverse side (sameback, differentfront— a polysemous word)contextcannot: reverse modes never render it. There theReverseTypeof each such case lists all senses in its slot (its own first), andReverseChoicenever 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/backImagetake either a/media/card/…url the site itself issued on upload, or anhttpsurl 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-builderlink: it will ask a couple of clarifying questions about your weak spots, build a deck and hand you the text to import.
Importing
- Open the decks page and press "Import deck" (or follow
/decks?import=1— the dialog opens by itself). - Paste the text: the dialog reads a ```cards block, a deck JSON object
{ "title", …, "cards": [ … ] }, a bare card array[ { "cases": … }, … ]or onefront — backpair per line — the title is taken from the text when it names one, else from the dialog's name field. - 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": [["он усталый", "он устал"]] } }
]
}
]
}
]
}