AnkiWeb
- Rating
- 5 (π 5 Β· π 0)
- Updated
- 2025-01-06
- Anki versions
- 24.06.3~
- Description language
- en
AnkiWeb addon 868678030
Converts Google Docs, Notion, and Obsidian notes into Anki flashcards using customizable YAML workflows and multiple LLMs via OpenRouter.
Open on AnkiWeb GitHub Ask about alternatives
active
| Min Anki | Max Anki | Updated |
|---|---|---|
| 2.1.49 | 24.06.3+ | 2025-01-06 |
Loadingβ¦
Syncs Notion notes directly into Anki flashcards, converting toggle lists and tables into cards, mirroring nested pages as decks, and supporting cloze deletions, completely free.
Syncs Notion pages, databases, rich blocks, images, and sub-pages into nested Anki decks with reversed toggles, image occlusions, and fast background operation.
Imports Notion toggles as Anki questions via the official Notion API, supporting multiple pages, decks, recursion, rich content, GUI configuration, and background syncing.
Syncs structured Notion notes into Anki as clean, updated cards, supporting basic, reversed, input, cloze, and image occlusion workflows.
Creates Anki flashcards from Google Docs tables, preserving text formatting and embedded images, with remote syncing for updates.
Creates Anki flashcards from Google Docs using bullet points instead of tables, supporting embedded images, formatting, syncing, and ignored # comments.
AI-powered application to organize online notes (Google Doc, Notion, Obsidian) and convert them into Anki flashcards.

Note: The addon has been tested on the following versions of Anki:
868678030
docker-compose up
output/notes2flash.ankiaddonnotes2flash.ankiaddon fileconfig.json of the notes2flash addon:
"openrouter_api_key"Note on Pricing: You don't have to add any credit card details to use it but you'll be limited to free models which there are many to choose from such as meta-llama/llama-3.1-70b-instruct:free. Go to the openrouter.ai website to browse all possible models. To use paid models you have to do a minimum top-up of at least $5 USD, recommended for optimal performance. Using openai/gpt-4o-mini is a good performance/value model, processing 1 page (β 500 words β 25 flashcards) costs approximately $0.0024.
Note: notes2flash has no affiliation with openrouter.ai, and no money is made by notes2flash
Some models on OpenRouter require data sharing to be enabled in your privacy settings. If you encounter a 404 error like:
404 Client Error: Not Found for url: https://openrouter.ai/api/v1/chat/completions
This typically means the model you're trying to use requires you to allow data usage in your OpenRouter privacy settings.
To fix this:

This setting allows certain models (typically those with stricter licensing) to process your requests. Models that require this setting will indicate so on the OpenRouter model browser.
service_account.json in the addon directory, typically located at ~/.local/share/Anki2/addons21Compatibility with Obsidian is limited due to the lack of free native public access cloud storage. Scraping is done via the Obsius addon Obsius addon (shoutout to the developer!):
Hereβs a simple example of a yaml workflow configuration:
workflow_name: "barebone notes2flash workflow config example"
user_inputs: [notes_url]
# 1) **scrape notes from online docs (google docs, notion, obsius)**
scrape_notes:
- url: "{notes_url}"
output: scraped_notes_output # the output name for the scraped notes
# 2) **process notes into flashcards**
process_notes_to_cards:
- step: "organize notes and create flashcards"
model: "meta-llama/llama-3.1-70b-instruct:free"
chunk_size: 4000 # maximum chars per chunk (roughly 4 * token limit for english, 1*token_limit for mandarin)
input:
- scraped_notes_output # input is the notes content from scrape_notes stage
attach_format_reminder: true # if true will append a format reminder to the prompt ensuring api outputs correct format
output: flashcards # the output will always be a list of dictionaries with the following fields:
output_fields:
- question
- answer
prompt: |
organize the following notes into flashcards:
{scraped_notes_output}
# 3) **add cards to anki**
add_cards_to_anki:
flashcards_data: flashcards # input is the list of flashcards
deck_name: "example_deckname"
card_template:
template_name: "Notes2flash Basic Note Type" # 'notes2flash basic note type' is a default note type included in addon found in ./included_note_types/
front: "{question}" # the front of the card will show the question
back: "{answer}" # the back of the card will show the answer
The workflow is divided into three main stages:
Scrape Notes: In this stage, the scrape_notes key is used to specify the source URL from which to scrape the content. The output for the scraped notes is user configurable and defined as scraped_notes_output here. This name can be referenced in later stages, allowing you to easily manage and utilize the scraped content in the processing steps.
Process Notes into Flashcards: This stage takes the output from the scrape_notes stage as input. You must specify the output name (scraped_notes_output in this case) in the input section to ensure the correct data is processed. The model specified will organize the scraped notes and generate flashcards. The output will be a list of dictionaries containing the fields defined in output_fields, such as question and answer.
Additionally, if attach_format_reminder is set to True, a structured reminder will be appended to the end of the prompt. This reminder ensures that the API outputs the data in the expected format for the third stage, which is a list of dictionaries where each dictionary represents a flashcard with the specified output_fields.
The reminder that would be generated for the above example workflow config would be like the following:
**IMPORTANT**
Format the output as a list of dictionaries, where each dictionary represents a flashcard.
Each dictionary must contain exactly these keys: question, answer.
Strictly adhere to this structure. Any deviation from this format will not be accepted.
Example output:
[
{
"question": "example_question_1",
"answer": "example_answer_1"
},
{
"question": "example_question_2",
"answer": "example_answer_2"
},
...
]
Add Cards to Anki: In the final stage, the generated flashcards are added to Anki. The flashcards_data key takes the output from the previous stage, and you must specify the output name (flashcards) to ensure the correct data is added. The card template defines how each flashcard will be structured in Anki.
Save your custom workflow configurations in the addon/workflow_configs directory with a .yml extension.
The user_inputs key in the config allows you to customize variables that are specified by the user at time before runtime, for example if we add some alterations to the first workflow config by adding some variables to speicify the output anki deckname and also the topic of the notes to give the AI model some context which we can put in the prompt:
workflow_name: "barebone notes2flash workflow config example w/ more inputs"
user_inputs: [notes_url, notes_topic, deckname]
# 1) **scrape notes from online docs (google docs, notion, obsius)**
scrape_notes:
- url: "{notes_url}"
output: scraped_notes_output # the output name for the scraped notes
# 2) **process notes into flashcards**
process_notes_to_cards:
- step: "organize notes and create flashcards"
model: "meta-llama/llama-3.1-70b-instruct:free"
chunk_size: 4000 # maximum chars per chunk (roughly 4 * token limit for english, 1*token_limit for mandarin)
input:
- scraped_notes_output # input is the notes content from scrape_notes stage
- notes_topic # ***NEW INPUT, user input to be added to prompt to give AI context on notes contents
attach_format_reminder: true # if true will append a format reminder to the prompt ensuring api outputs correct format
output: flashcards # the output will always be a list of dictionaries with the following fields:
output_fields:
- question
- answer
prompt: |
organize the following notes of the topic {notes_topic} into flashcards:
{scraped_notes_output}
# 3) **add cards to anki**
add_cards_to_anki:
flashcards_data: flashcards # input is the list of flashcards
deck_name: "{deckname}" #***NEW INPUT, allowing the user to choose outputed deckname
card_template:
template_name: "Notes2flash Basic Note Type" # 'notes2flash basic note type' is a default note type included in addon found in ./included_note_types/
front: "{question}" # the front of the card will show the question
back: "{answer}" # the back of the card will show the answer
The second stage process_notes_to_cards also allows prompt chaining via addition steps. See below for an example workflow that uses two steps/prompts to extract Mandarin vocabulary and then generate example sentences.
β οΈ Note on Multi-step Workflows: Multi-step workflows are now considered largely redundant due to how quickly AI models have advanced since this tool was first developed. Modern models are capable of handling complex tasks in a single step. Complex workflows that previously required chaining multiple prompts can now typically be accomplished with a single, well-crafted prompt to a more capable model. Multi-step workflows add unnecessary complexity and are not recommended for new configurations.
workflow_name: "Vocabulary Extraction and Multi-step Processing"
user_inputs: [notes_url, deckname]
# 1) Scrape Notes from Online Docs
scrape_notes:
- url: "{notes_url}"
output: scraped_notes_output # The raw notes from the provided URL
# 2) Process Notes to Extract Vocabulary and Generate Flashcards
process_notes_to_cards:
- step: "Extract vocabulary and phrases"
model: "meta-llama/llama-3.1-70b-instruct:free"
chunk_size: 400
input:
- scraped_notes_output
output: extracted_vocabulary # Consistent naming for intermediate vocabulary output
prompt: |
Extract vocabulary and phrases from the following document. The document contains Mandarin keywords or short phrases. For each item, provide:
- The Mandarin word or phrase.
- Its pinyin representation.
- Its English translation.
Ignore irrelevant content and remove duplicates. If there are multiple valid translations, select the most commonly used one. Ensure the output strictly follows this JSON format:
[
{"mandarin": "word1", "pinyin": "pinyin1", "translation": "translation1"},
{"mandarin": "word2", "pinyin": "pinyin2", "translation": "translation2"},
...
]
Document:
{scraped_notes_output}
- step: "Generate example sentences and flashcards"
model: "meta-llama/llama-3.1-70b-instruct:free"
input:
- extracted_vocabulary
attach_format_reminder: false
output: flashcards
output_fields:
- sentence
- translation
- keywords
prompt: |
Use the vocabulary below to generate example sentences in Mandarin. Each sentence should:
- Naturally incorporate one or more keywords.
- Include additional context or keywords if necessary for clarity (only if not commonly known by an upper-intermediate learner).
For each sentence, provide:
- The Mandarin sentence.
- Its English translation.
- A list of keywords in the format "keyword pinyin translation" separated by `<br>` for multiple keywords.
Ensure the output strictly follows this JSON format:
[
{"sentence": "Example sentence in Mandarin.", "translation": "English translation of the sentence.", "keywords": "keyword1 pinyin1 translation1<br>keyword2 pinyin2 translation2"},
{"sentence": "Another example sentence in Mandarin.", "translation": "English translation of this sentence.", "keywords": "keywordA pinyinA translationA<br>keywordB pinyinB translationB"},
...
]
Keywords:
{extracted_vocabulary}
# 3) Add Cards to Anki
add_cards_to_anki:
flashcards_data: flashcards
deck_name: "{deckname}"
card_template:
template_name: "Notes2flash Basic Note Type"
front: "{sentence}"
back: "{translation}<br><br>{keywords}"
Only the final step needs to output the 'flashcards_data'-like format ie a list of dicts with keys for the output fields. The outputs corresponding to the intermediate processing steps will be passed into the later steps simply as a string. As such the intermediate steps dont need to specify the keys for output_fields or attach_format_reminder. Notice for the final step in this example I have attach_format_reminder: false, this is because my output field keywords has a more complex structure and so it is better to specify the exact structure I want myself.
notes2flash.log file in the addon directory for error messages and execution logs.output_fields.notes2flash.log to reset the logging, and tracked_docs.json to reset document tracking.When processing large documents, there is no progress bar in the UI. To verify that the addon is working correctly:
notes2flash.log file in the addon directory (typically ~/.local/share/Anki2/addons21/notes2flash/)tail -f notes2flash.log (on Linux/Mac) or open the file periodically to check for updatesThis is particularly useful for confirming the addon hasn't frozen during long-running operations.
[
{"key1": "value1", "key2": "value2"},
{"key1": "value3", "key2": "value4"}
]
Do not use square brackets [] in your workflow prompt content. The YAML parser may misinterpret square brackets as array syntax, causing parsing errors or unexpected behavior.
Incorrect:
prompt: |
Extract vocabulary [words and phrases] from the notes
Correct:
prompt: |
Extract vocabulary (words and phrases) from the notes
Use parentheses () or other punctuation instead of square brackets in your prompt text.
The addon provides detailed error messages and logging. If you encounter issues:
notes2flash.log file for more information.For more detailed information on creating and customizing workflows, troubleshooting, and advanced features, please refer to the documentation in the docs folder.
We welcome contributions, whether it's reporting bugs on GitHub, adding code or useful workflows that you think others would benefit from !!!
This project consists of several key files and directories that work together to convert notes into Anki flashcards:
output/notes2flash.ankiaddonNote Extraction:
Processing Pipeline:
Anki Integration:
Error Handling and Logging:
notes2flash.logThe tracking of document changes is managed through the tracked_docs.json file. This file is structured as a JSON dictionary where each key corresponds to a document ID that is being tracked.
Each entry in the JSON file contains the following fields:
If you wish to reset your tracking, you can simply delete the tracked_docs.json file. This will remove all tracking information.
If you would like to delete tracking for a specific document, you can find the corresponding entry in the tracked_docs.json file and remove that entry. This allows you to selectively manage which documents are being tracked without affecting others.