Brain Brew is an open-source flashcard manipulation tool designed to allow users to convert their Anki flashcards to/from many different formats to suit their own needs. The goal is to facilitate collaboration and maximize user choice, with a powerful tool that minimizes effort. CrowdAnki Exports and Csv(s) are the only supported file types as of now, but there will be more to come.
Anki Ultimate Geography is currently the best working example of a Flashcard repo using Brain Brew 🎉 See there for inspiration!
Install the latest version of Brain Brew on PyPi.org
with pip install brain-brew
. Virtual environment using pipenv
is recommended!
❗ See the Brain Brew Starter Project for a working clone-able Git repo. From this repo you can now create a functional Brain Brew setup automatically, with your own flashcards! Simply by running
brainbrew init [Your CrowdAnki Export Folder]
This will generate the entire working repo for you, including the recipe files, source files, and build folder. For bi-directional sync: Anki <-> Source!
See the starter repo for a step-by-step guide for all of this.
Brain Brew runs from the command line and takes a Recipe.yaml file to run.
brainbrew run source_to_anki.yaml
Full usage help text:
Brain Brew vx.y.z
usage: brainbrew [-h] {run,init} ...
Manage Flashcards by transforming them to various types.
positional arguments:
{run,init} Commands that can be run
run Run a recipe file. This will convert some data to another format, based on the instructions in the recipe file.
init Initialise a Brain Brew repository, using a CrowdAnki export as the base data.
optional arguments:
-h, --help show this help message and exit
These are the instructions for how Brain Brew will build brew your data into another format.
What's YAML? See the current spec here.
Run a recipe with --verify
or -v
to confirm your recipe is valid, without actually running it.
A dry run of sorts.
A recipe is made of many individual tasks, which do specific functions.
Full detailed list coming soon™️, but see the Yamale recipe schema
(local file: brain_brew/schemas/recipe.yaml
) in the meantime 👍
Brain Brew was made in an effort to solve some of the following issues with current collaboration of Anki Flashcards:
Have some personal notes on your cards? Used some images randomly taken from the internet? That usually means you cannot share your deck entirely, without having to go to the effort of removing the offending material and/or managing two separate copies.
Putting your cards into a source control system brings a lot of benefits. You can see any changes that occur, go back in time should an mistake be discovered, and collaborate with others.
However the current tools for managing Anki cards in source control (such as Anki-DM, GenAnki, and Remote Decks) are only one way. You generate cards from a csv into a file that can only be imported into Anki. There is no way to export them back, meaning a user must manually copy their changes over, or simple not edit their cards anywhere other than in source control.
This robs the user of two important work flows:
- Editing/fixing cards in Anki as you review them (on desktop or mobile)
- The plethora of Anki add-ons that already exist that are amazingly useful. E.g: Image Occlusion, Morphman, AwesomeTTS.
A user should not have to pick between these fantastic work flows and the usage of source control to structure, manage, and share their cards.
Csvs are great for editing data, but can only go so far by themselves. Having all the data inside one csv leaves a lot to be desired and can result in eventual problems. When one gets as many columns as this (from Ultimate Geography) then it becomes a nightmare to manage:
guid | Country | Country:de | Country:es | Country:fr | Country:nb | "Country info" | "Country info:de" | "Country info:es" | "Country info:fr" | "Country info:nb" | Capital | Capital:de | Capital:es | Capital:fr | Capital:nb | "Capital info" | "Capital info:de" | "Capital info:es" | "Capital info:fr" | "Capital info:nb" | "Capital hint" | "Capital hint:de" | "Capital hint:es" | "Capital hint:fr" | "Capital hint:nb" | Flag | "Flag similarity" | "Flag similarity:de" | "Flag similarity:es" | "Flag similarity:fr" | "Flag similarity:nb" | Map | tags |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
crr.AfnVRi | England | England | Inglaterra | Angleterre | England | "Constituent country of the United Kingdom." | "Landesteil des Vereinigten Königreichs." | "Nación constitutiva del Reino Unido." | "Nation constitutive du Royaume-Uni." | "Land som utgjør en del av Storbritannia." | London | London | Londres | Londres | London | "Not a sovereign country" | "Kein souveräner Staat" | "No es un país soberano" | "Pas une nation souveraine" | "Ikke selvstendig land" | "<img src=""ug-flag-england.svg"" />" | "<img src=""ug-map-england.png"" />" | UG::Europe | ||||||||||
"h<B?Kff,?3" | "Ivory Coast" | Elfenbeinküste | "Costa de Marfil" | "Côte d’Ivoire" | Elfenbenskysten | "Officially Côte d'Ivoire." | "Offiziell Côte d'Ivoire." | "Oficialmente Côte d'Ivoire." | Yamoussoukro | Yamoussoukro | Yamusukro | Yamoussoukro | Yamoussoukro | "While Yamoussoukro is the official capital, Abidjan is the de facto seat of government." | "Yamoussoukro ist die offizielle Hauptstadt, aber Abidjan ist der Regierungssitz." | "Aunque Yamusukro es la capital oficial, Abiyán es la capital de facto." | "Bien que Yamoussoukro soit la capitale officielle, Abidjan est le siège du gouvernement." | "Yamoussoukro er offisiell hovedstad, mens Abidjan er de facto regjeringssete." | "<img src=""ug-flag-ivory_coast.svg"" />" | "Ireland (orange and green flipped, wider)" | "Irland (Orange und Grün vertauscht, breiter)" | "Irlanda (naranja y verde intercambiados, más ancha)" | "Irlande (orange et vert inversés, plus large)" | "Ireland (byttet plass på oransje og grønt, bredere)" | "<img src=""ug-map-ivory_coast.png"" />" | "UG::Africa UG::Sovereign_State UG::West_Africa" |
Then there's having too many rows in one csv for it to be properly managed.
Make changes in your source file and sync those into your Anki collection.
Make changes inside Anki and pull those back into the source.
Any user of your shared deck can make a change inside Anki and at some later point export their deck (or just part of it) using CrowdAnki. Then the source file can be updated with their changes and a new CrowdAnki Export for all users to import can be generated with one run of Brain Brew.
Yaml config files are what drive the conversion of Brain Brew, allowing users to easily change the functionality as they wish.
- generate_guids_in_csv:
source: src/data/words.csv
columns: [ guid ]
- build_parts:
- note_model_from_yaml_part:
part_id: LL Word
file: src/note_models/LL Word.yaml
- headers_from_yaml_part:
part_id: default header
file: src/headers/default.yaml
override: # Optional
deck_description_html_file: src/headers/desc.html
- media_group_from_folder:
part_id: all_media
source: src/media
recursive: true # Optional
- notes_from_csvs:
part_id: english-to-danish
note_model_mappings:
- note_models:
- LL Word
columns_to_fields: # Optional
guid: guid
tags: tags
english: English
danish: Word
picture: Picture
danish audio: Pronunciation (Recording and/or IPA)
file_mappings:
- file: src/data/words.csv
note_model: LL Word
sort_by_columns: [english] # Optional
reverse_sort: no # Optional
Deck managers can set specific fields to be "Personal", meaning they will not overwrite an existing value on import.
Working version currently exists, but full PR coming soon to CrowdAnki!
Free for all to use, modify, or sell this product.
Further source types are relatively easy to add due to the flexible nature of the backend Instead of creating a Csv <-> CrowdAnki converter Brain Brew first goes through a middle layer called "Deck Parts". These consist of Notes, Headers, Note Models, and Media files.
Each new source type to be added to Brain Brew (such as Markdown) need only be able to convert from Deck Parts <-> itself, and suddenly it can convert to and from all existing source types!
Csvs only update the rows which have changed. Meaning a user can import a subset of their cards which have changed and still update the source file without deleting the cards they did not include.
Split data into multiple csvs so that your data is neatly organised however you like.
The two following csv files contain information about England, but split into different csv files:
guid | country | flag | map | tags |
---|---|---|---|---|
"e+/O]%*qfk | England | <img src=""ug-flag-england.svg"" /> | <img src=""ug-map-england.png"" /> | UG::Europe |
country | capital | capital de | capital es | capital fr | capital nb |
---|---|---|---|---|---|
England | London | London | Londres | Londres | London |
Brain Brew can be told that data-capital
is a derivative of data-main
in the build config file as such:
- file: src/data/data-main.csv # <---- Main
note_model: Ultimate Geography
derivatives:
- file: src/data/data-country.csv
- file: src/data/data-country-info.csv
- file: src/data/data-capital.csv # <---- Capital
- file: src/data/data-capital-info.csv
- file: src/data/data-capital-hint.csv
# note_model: different_note_model
# derivatives:
# - file: derivative-of-a-derivative.csv
# derivatives:
# - file: infinite-nesting.csv
- file: src/data/data-flag-similarity.csv
When run Brain Brew will perform the following steps for each derivative:
- Finds which columns in the derivative csv match the main (only
country
in this case) - Go through each row in the derivative and find the row with matching values in the main file
- Add in the extra columns (
capital
in each language) to that matching row in the main file
guid | country | flag | map | tags | capital | capital de | capital es | capital fr | capital nb |
---|---|---|---|---|---|---|---|---|---|
"e+/O]%*qfk | England | <img src=""ug-flag-england.svg"" /> | <img src=""ug-map-england.png"" /> | UG::Europe | London | London | Londres | Londres | London |
-
Derivatives can also have derivatives.
-
Csv splitting works in both directions, to and from csv.
-
Derivatives can be given a Note Model, which overrides their parent's note model for all the matched rows.
See the Brain Brew Starter Project for an example of Csv Derivatives working.