*This is a draft. I'm working on designing a new mnemonic medium for the web.* # Introduction Mnemonic markdown is an extension of CommonMark markdown that allows you to specify memory prompts for spaced recall practice directly inline with the document and provides additional extensions to enable the authoring of mnemonic texts. ## What is mnemonic markdown? Mnemonic markdown is an extension of markdown that allows you to specify memory prompts for spaced recall practice directly inline with the document. This makes it conceptually different from markdown, which renders to HTML. Mnemonic markdown renders to HTML and JavaScript, but additionally describes *intent* not only for static display, but also for interactivity. So while markdown is really about typesetting for the web, mnemonic markdown is about interactive typesetting. This presents a challenge in specifying the format. When specifying markdown, the creators of CommonMark, for example, could list the html that would result from some specific syntax. When specifying the extensions that mnemonic markdown provides, we need to specify not only the document rendered for reading, but also the retrieval prompts created. Mnemonic markdown presents a further opportunity. While markdown was specified in the context of creating a simple and elegant way to write rich text as plain text. With Mnemonic markdown we want to create a {{medium}} ^'362c for thinking with a computer, both as an individual, and with others. For this reason, we will incorporate additional syntax for citation, links, references, special list formatting, etc... as inspired by pandoc. Mathematics is obviously essential. And we will strive for excellent math support with single and double dollar sign syntax as well as the ability to number of reference functions. Obsidian has contributed several improvements that we would like to incorporate as well. This document will eventually grow to be a formal specification of Mnemonic Markdown, but at first it will be an informal specification during alpha development, while the syntax is still in flux. # Planned Ecosystem ## Workflow Cycle ```mermaid ``` - Authoring - Publishing - Mnemonic Markdown is designed to be published to the web or to a web view embedded inside an application. - All published mnemonic markdown (Mnemonic Hypertext) is - Mnemonic Markdown also supports the creation of manuscripts (export) for print and e-books and the generation of flashcard decks for Anki and Mochi Cards. - Reading, Annotating, Note Taking ## Technologies - Mnemonic Markdown - Mnemonic.js: A javascript library that adds the appropriate interactivity - Mnemonic Hypertext ## Affordances of the Mnemonic Markdown Ecosystem - Write mnemonic markdown in any editor. It's just a plain text file. - Create Vaults (i.e. project directories) of mnemonic markdown with coherent internal links to facilitate site generation --- --- # Initial Thoughts *This is an AI summary of a conversation wtih Claude 4.5 where I described my ideas for a mnemonic syntax* Since we don't have a content aware scheduler, you're going to need a review history for each card. --- ## Overview A lightweight, Markdown-native syntax for creating spaced repetition flashcards using cloze deletion. Designed for Obsidian, this system keeps your study materials integrated with your notes while providing powerful card creation capabilities. ## Core Principles - **Simple**: Everything uses `{{...}}` syntax - **Markdown-native**: Works with standard Markdown formatting - **Context-aware**: Cards display surrounding content - **Flexible**: Supports simple clozes, grouped blanks, sequences, and custom Q&A ## Card Scope **Card scope** determines which clozes are grouped together and what context appears on cards. ### Definition A card scope is a contiguous block of text separated by blank lines (2 or more newlines). **Exception**: A list and its immediately preceding paragraph form one card scope, even if there's a blank line between them. ### Examples **Separate scopes:** ```markdown This is one scope {{1>foo}}. This is another scope {{1>bar}}. ``` Result: Two separate cards (blank line creates new scope). **Same scope (no blank line):** ```markdown Regular paragraph {{1>foo}}. Another paragraph {{1>bar}}. ``` Result: One card with two blanks. **List with intro (merged scope):** ```markdown Introduction to my list: 1. {{1>first item}} 2. {{1>second item}} ``` Result: One card with two blanks. "Introduction to my list:" appears as context on the card. ## Syntax Elements ### 1. Basic Cloze Deletion **Syntax**: `{{text}}` Creates a single flashcard with the text hidden as a blank. **Example:** ```markdown The capital of France is {{Paris}}. ``` **Card displays:** - Front: "The capital of France is ___." - Back: "The capital of France is Paris." ### 1.2 Hints Syntax: `{{clozed thing|hint goes here}}` The cloze will display the hint on the front size of the card with special formatting to make it clear it is a hint. --- ### 2. Grouped Cloze Deletion **Syntax**: `{{N>text}}` where N is any positive integer Multiple clozes with the same number within the same card scope appear as blanks on a single card. **Scope**: Numbers are scoped to the card scope level. Same number in different scopes = different cards. **Example:** ```markdown The {{1>mitochondria}} is the {{1>powerhouse}} of the cell. ``` **Card displays:** - Front: "The ___ is the ___ of the cell." - Back: "The mitochondria is the powerhouse of the cell." **Cross-scope behavior:** ```markdown Paragraph one has {{1>foo}}. Paragraph two has {{1>bar}}. ``` Result: Two separate cards (different card scopes, even though both use `1>`). --- ### 3. Sequence Cloze Deletion **Syntax**: `{{N.>text}}` where N is any positive integer Creates multiple cards that reveal answers progressively in document source order. **Display**: Each card shows all previous answers filled in, current answer as blank, and future answers as "???". **Scope**: Sequences are scoped to the card scope level. **Example:** ```markdown Steps in the Krebs cycle: 1. {{1.1>Acetyl-CoA combines with oxaloacetate}} 2. {{1.2>Citrate is formed}} 3. {{1.3>Isocitrate is oxidized}} ``` Max came up with this great idea of using 1.1 1.2 1.3 instead of 1. 1. 1. which was less useful and expressive!!! **Cards display:** - Card 1: "1. ___ / 2. ??? / 3. ???" - Card 2: "1. Acetyl-CoA combines with oxaloacetate / 2. ___ / 3. ???" - Card 3: "1. Acetyl-CoA combines with oxaloacetate / 2. Citrate is formed / 3. ___" **Order note**: "Text order" means document source character order, regardless of list numbers or formatting. **Non-list sequences:** ```markdown First {{1.>Napoleon}} was born, then he became {{1.>Emperor}}, then he was {{1.>exiled}}. ``` Creates three progressive cards in order. --- ### 4. Cloze with Extra Content **Syntax**: `{{text<extra content}}` The extra content appears on the card back/reveal side only. **With literal text:** ```markdown The heart has {{four chambers<two atria and two ventricles}}. ``` **Card displays:** - Front: "The heart has ___." - Back: "four chambers" + "two atria and two ventricles" **With reference injection:** ```markdown The ACL connects the {{femur<(^acl-detail)}} to the tibia. [^acl-detail]: Prevents anterior translation of the tibia {.card-only} ``` **With multiple references:** ```markdown Napoleon was born in {{Corsica<(^corsica-info) See also: (^napoleon-timeline)}}. [^corsica-info]: Island in the Mediterranean {.card-only} [^napoleon-timeline]: Born 1769, died 1821 {.card-only} ``` --- ### 5. Content Injection (Card Front) **Syntax**: `(^ref)` Injects content from a reference definition onto the card front as context. **Example:** ```markdown (^heart-diagram) This structure is the {{left ventricle}}. [^heart-diagram]: ![Heart anatomy](heart.png){#heart-diagram .card-only} ``` **Card displays:** - Front: [Heart diagram image] + "This structure is ___." - Back: "left ventricle" **Multiple injections on front:** ```markdown (^diagram1) (^diagram2) What process is shown? {{Mitosis}} [^diagram1]: ![Cell division](mitosis1.png){.card-only} [^diagram2]: ![Chromosomes](mitosis2.png){.card-only} ``` --- ### 6. Reference Definitions **Syntax**: Standard Pandoc footnote syntax with optional attributes ```markdown [^ref-name]: content [^ref-name]: content {.card-only} ``` **Behavior:** - **Without `.card-only`**: Renders as normal footnote in reading view AND available for card injection - **With `.card-only`**: Hidden in reading view, only appears on cards that reference it **Content types**: Text, images, or any Markdown content. **Error handling:** - Duplicate definitions: Warning issued, first definition used - Undefined reference: Error - Same ref on front and back: Allowed (content appears in both places) **Text reference example:** ```markdown The patient needs {{intubation<(^intubation-criteria)}}. [^intubation-criteria]: When ventilatory failure is not easily reversible or persistent hypoxemia despite maximal O2 {.card-only} ``` **Image reference example:** ```markdown [^ecg-normal]: ![Normal ECG](ecg.png){#ecg .card-only} (^ecg-normal) What rhythm is this? {{Normal sinus rhythm}} ``` --- ### 7. Images **Standard image**: `![alt](url)` **With reference ID**: `![alt](url){#ref-id}` **Card-only images**: `![alt](url){#ref-id .card-only}` **Display rules:** - Standard images display normally in document - Images with `{#ref-id}` can be referenced via `(^ref-id)` for card injection - Images with `.card-only` are hidden in reading view, only appear on cards - Images do NOT automatically appear from context window - Images only appear on cards when explicitly injected via `(^ref)` **Example:** ```markdown ![ACL anatomy](acl.png){#acl-diagram .card-only} (^acl-diagram) What ligament prevents anterior tibial translation? {{ACL<(^acl-function)}} [^acl-function]: Anterior Cruciate Ligament - most commonly injured knee ligament {.card-only} ``` **Image on both document and cards:** ```markdown ![Heart diagram](heart.png){#heart-img} The heart has (^heart-img) {{four chambers}}. ``` Result: Image shows in document normally AND on the flashcard. --- ### 8. Custom Q&A Format You can write explicit question-answer pairs using blockquotes for visual separation. Here, the block quote is purely sylistic and has no speical meaning for the parser. **Example:** ```markdown #### Heart Anatomy The heart pumps blood through the {{circulatory system}}. > What are the four chambers called? > {{Two atria and two ventricles}} > Why do ventricles have thicker walls? > {{They pump blood further distances<(^ventricle-pressure)>}} [^ventricle-pressure]: Left ventricle pressure: 120mmHg systolic {.card-only} ``` Note: The `>` blockquote is purely stylistic - it's just regular Markdown. The `{{cloze}}` syntax works the same anywhere. #### Special quote block If you want to define a card scope, you can use a > ? to state, this entire quote block will be presented as a card. > ? > My question > > {{ > My answer > | hint goes here... > < > My extra goes here > }} --- ### 9. Nesting **Syntax**: `{{outer {{nested}} content}}` Nested clozes are supported. **Example:** ```markdown {{The equation {{E=mc²}} relates energy and mass}}. ``` Creates separate cards: 1. "The equation ___ relates energy and mass" → "E=mc²" 2. "The equation ___ relates energy and mass" → "The equation E=mc² relates energy and mass" --- ### 10. Escape Sequences **Use backslashes to write literal cloze syntax:** ```markdown To create a cloze, write \{\{text\}\}. ``` Displays: "To create a cloze, write {{text}}." **Alternative for code (add spaces):** ```markdown In JavaScript, use { { destructuring } } for objects. ``` --- ## Context Display Cards automatically show surrounding context from their card scope: ### Regular Text ~5-10 lines above and below the cloze with fade effect (opacity gradually decreases). ### Lists The preceding paragraph (if merged into scope) + faded context within the list. **Example:** ```markdown Three types of muscle tissue: 1. {{Skeletal}} - voluntary control 2. {{Cardiac}} - heart muscle 3. {{Smooth}} - involuntary, found in organs ``` All three cards show "Three types of muscle tissue:" as context. ### Code Blocks Full code block with fade to either end if too long. Context is scrollable while maintaining syntax highlighting. **Example:** ````markdown Python list comprehension: ```python squares = [{{x**2}} for x in range(10)] print(squares) ```` ```` Card shows the complete code block with syntax highlighting. --- ## Complete Examples ### Example 1: Medical Study Material ```markdown #### Indications for Intubation Failure of ventilation or oxygenation is a {{1>primary}} indication for {{1>intubation}}. Assessment includes evaluation of: 1. {{eval>Patient's general status}} 2. {{eval>Oxygen saturation by pulse oximetry}} 3. {{eval>Ventilatory pattern}} Arterial blood gases are {{not required<(^abg-note)}} to determine intubation need. [^abg-note]: ABGs may be misleading and cause false sense of security - can delay intubation in deteriorating patient {.card-only} ```` **Cards created:** 1. One card: "Failure of ventilation or oxygenation is a ___ indication for ___." 2. One card: Three blanks for assessment items 3. One card: "ABGs are ___ to determine..." with extra note on back --- ### Example 2: Programming Concepts ````markdown ![React component diagram](react-diagram.png){#react-img .card-only} (^react-img) The {{useState}} hook allows {{functional components}} to have state. Syntax: ```javascript const [{{state}}, {{setState}}] = useState({{initialValue}}); ```` The setter function {{setState<(^rerender-note)}} triggers a re-render. [^rerender-note]: React compares old and new state, only re-renders if different {.card-only} ```` --- ### Example 3: Historical Timeline ```markdown Key events in Napoleon's life: - {{1.>Born in Corsica}} (1769) - {{1.>Became First Consul}} (1799) - {{1.>Crowned Emperor}} (1804) - {{1.>Invaded Russia}} (1812) - {{1.>Exiled to Elba}} (1814) - {{1.>Defeated at Waterloo}} (1815) - {{1.>Died on Saint Helena}} (1821) ```` Creates 7 progressive cards revealing events in chronological order. --- ### Example 4: Anatomy with Images ```markdown [^anterior-view]: ![Knee anterior view](knee-front.png){.card-only} [^lateral-view]: ![Knee lateral view](knee-side.png){.card-only} #### Knee Ligaments (^anterior-view) The {{ACL<(^acl-detail)}} prevents anterior translation. (^lateral-view) The {{MCL<(^mcl-detail)}} prevents valgus stress. [^acl-detail]: Most commonly torn during pivoting sports {.card-only} [^mcl-detail]: Broad, flat ligament - more stable than ACL {.card-only} ``` --- ## Edge Cases & Special Behaviors ### Empty Clozes `{{}}`, `{{<extra>}}`, `{{1>}}` are ignored (no card created). ### Special Characters in References Reference names support letters, numbers, hyphens, and underscores (standard Pandoc footnote format). ### Code Blocks Clozes work inside code blocks. Context scope is the entire code block. ### Same Reference Multiple Times A reference can be used on multiple cards and on both front and back of the same card. ### Cross-Scope Sequences Sequence clozes in different card scopes are separate sequences, even if they use the same number. ```markdown First paragraph: {{1.>a}} then {{1.>b}}. Second paragraph: {{1.>x}} then {{1.>y}}. ``` Creates two separate 2-card sequences. --- # Block IDs for Card Stability ## Overview Block IDs provide stable identity for cards across edits to the source markdown. They are automatically generated and allow the spaced repetition system to track review history even as you refine and improve your notes. ## Syntax **Basic pattern**: `{{cloze}} ^block-id` The block ID is placed immediately after the closing `}}` of a cloze. **Format**: `^` followed by alphanumeric characters (typically 6-8 characters) **Example**: ```markdown The capital of France is {{Paris}} ^c4f2a9. ``` ## Behavior ### Auto-Generation Block IDs are **automatically added** the first time a cloze is reviewed. You don't need to manually create them. **Before first review**: ```markdown The mitochondria is the {{powerhouse}} of the cell. ``` **After first review (auto-generated)**: ```markdown The mitochondria is the {{powerhouse}} ^a7k3m9 of the cell. ``` ### Multiple Clozes Each cloze gets its own block ID: ```markdown The {{mitochondria}} ^abc123 is the {{powerhouse}} ^def456 of the cell. ``` ### Grouped Clozes For grouped clozes (multiple blanks on one card), only **one block ID is required** for the entire group: ```markdown The {{1>mitochondria}} is the {{1>powerhouse}} ^card-001 of the cell. ``` The block ID can be placed after any cloze in the group. ### Sequence Clozes Each card in a sequence gets its own block ID since they are separate cards: ```markdown Napoleon's life: 1. {{1.>Born in Corsica}} ^seq-001 2. {{1.>Became Emperor}} ^seq-002 3. {{1.>Exiled to Elba}} ^seq-003 ``` ## Editing Rules ### Rule 1: Same Block ID = Same Card If the block ID is preserved, the card is updated with new content but **all review history is kept**. ```markdown # Original A {{patent}} ^c4f2a9 airway is essential. # After edit A {{patent and unobstructed}} ^c4f2a9 airway is critical. ``` **Result**: Card content updates, review history preserved. ### Rule 2: Deleting Block ID = Deleting Card To delete a card, delete its block ID. ```markdown # Original A {{patent}} ^c4f2a9 airway is essential. # Delete the card (remove block ID) A {{patent}} airway is essential. ``` **Result**: - Old card archived in database - New block ID auto-generated on next review: `A {{patent}} ^x9k2m7 airway is essential.` - New card created (fresh review history) ### Rule 3: Edit Freely, Keep Block ID You can change anything about the cloze - the answer, the context, the surrounding text - as long as the block ID stays, it's the same card. ```markdown # Original The capital is {{Paris}} ^geo-001. # Change answer The largest city is {{Paris}} ^geo-001. # Change context completely {{Paris}} ^geo-001 is a major European city. ``` All three are treated as the **same card** (same `^geo-001`), review history preserved. ## Visual Display Block IDs are part of your markdown but can be visually de-emphasized: ### In Editor (CSS) ```css /* Fade out block IDs */ .cm-blockid { opacity: 0.25; font-size: 0.75em; color: var(--text-faint); } /* Optional: Hide completely */ .hide-block-ids .cm-blockid { display: none; } ``` ### In Reading View Block IDs are typically hidden completely in reading view since they're metadata for the review system. ## Database Relationship ```sql CREATE TABLE cards ( id TEXT PRIMARY KEY, -- Same as block_id block_id TEXT UNIQUE NOT NULL, -- The ^abc123 from markdown file_path TEXT, -- Card content (cached from markdown) question TEXT, answer TEXT, context TEXT, -- FSRS scheduling data stability REAL, difficulty REAL, state INTEGER, due TEXT, -- ... etc -- Change detection content_hash TEXT, modified_at TEXT ); CREATE TABLE archived_cards ( -- Same schema as cards -- Cards moved here when block ID is deleted archived_at TEXT ); ``` The `block_id` is the **stable link** between markdown source and review database. ## Complete Example ```markdown #### Intubation Criteria The decision to intubate is based on three criteria: 1. {{Failure to maintain or protect the airway}} ^intub-01 2. {{Failure of ventilation or oxygenation}} ^intub-02 3. {{Anticipated clinical deterioration}} ^intub-03 A {{patent}} ^patent-01 airway is essential. Patency should be established using {{airway maneuvers such as repositioning, chin lift, jaw thrust, or insertion of an oral or nasal airway}} ^maneuvers-01. The gag reflex is {{not reliable}} ^gag-01 for assessing airway protection because it is {{absent in 12-25% of normal adults}} ^gag-02. ``` **Cards created:** - 7 separate cards - Each with stable block ID - Edit text freely → card updates, history preserved - Delete block ID → card archived, new card created ## Benefits ✅ **Simple rule**: Same ID = same card, always ✅ **Edit freely** - Change anything, keep block ID, history preserved ✅ **Explicit deletion** - Remove block ID to delete card ✅ **No prompts** - System never asks for confirmation ✅ **Obsidian-native** - Uses existing block reference syntax (`^block-id`) ✅ **Future-proof** - Can link to cards using `[[note#^block-id]]` ## Edge Cases ### Duplicate Block IDs If two clozes share the same block ID (user error), the system auto-generates new unique IDs for the duplicates. ### Block IDs on Non-Clozes Block IDs placed elsewhere in markdown (not after a cloze) are ignored by the card system. ### Moving Cards Between Files ```markdown # file1.md The capital is {{Paris}} ^geo-001. # Move to file2.md (copy-paste with block ID) The capital is {{Paris}} ^geo-001. ``` Same block ID → same card. The database updates `file_path` to track the new location. ### Special Characters Block IDs support: letters (a-z, A-Z), numbers (0-9), hyphens (-), underscores (_) Invalid characters are stripped during auto-generation. --- ## Design Philosophy 1. **Write naturally**: The syntax shouldn't interrupt your writing flow 2. **Context matters**: Cards stay connected to their source material 3. **Flexibility**: Support simple clozes and complex multi-part cards 4. **No lock-in**: It's just Markdown - your notes remain portable 5. **Progressive disclosure**: Start simple with `{{cloze}}`, add features as needed #tft #softwaredesign