Techical Notes

Fresh Cards: under the hood

This page is all about how Fresh Cards works behind the scenes.

Card and lesson storage

Card and lesson info are stored in the app’s Documents folder. (On iOS, it’s stored in the data folder, which is the parent folder of the Documents folder.) The info about all decks is stored in one SQLite database and each deck gets a separate folder, with its own SQLite database and folders for storing resources and sync data.

More details coming soon. Let me know if you are interested.

Freshpack file format

When you export a deck to Freshpack, a .freshpack file is created. This file is actually just a zip archive. You can use the built-in macOS Archive Utility to unarchive the file. Simply control-click on the .freshpack file and select Open With/Archive Utility. This will unarchive it to a new folder.

Within the folder is a cards.sqlite file and a resources folder. The cards.sqlite file is simply a SQLite database. I recommend using DB Browser for SQLite to view it. There are two tables in the database, a cards table, which is all the cards that were exported. The identifier field is a unique identifier used to look up the card. The resources table contains an entry for each resource that is referenced by a card. Resources are images and audio files.

The resources folder contains all of the image and audio resources. The filename corresponds to the resource entry in the database.

More notes on the DB schema coming soon.

Text file format

Another great option for import is to use a simple text file. If you create a file with the file extension .txt and enter your front and back contents in an alternating format, Fresh Cards will be able to import it just as it does with freshpacks, i.e. you’ll be able to import to a new deck or to an existing deck.

Here’s an example of a short german deck in the front/back alternating format. Note that this format means that each front and back text must not have any newlines. Be sure to leave a space between each front/back combo.

the fall (season)
der Herbst

the season
die Jahreszeit

September
der September

the camp
das Zeltlager

the daughter
die Tochter

to wake
aufwachen

Keep in mind the file you save to must end in .txt for this to work. The back text is actually optional, so feel free to create front content only if you are okay with a blank back card or you are using cloze deletions.

This is front text and no back text.

Apollo 11 landed on the moon in [1969].

You can mix and match cards.

This one has back text as well as front text.

To actually import this file, just drag and drop as you see in the diagram here.

Open Flashcard Format

Fresh Cards also supports a more complex text file format, called Open Flashcard. This file format allows you to specify all the details of a flashcard, including references to image and audio files. The contents can also be zipped up in an archive for easy sharing with others.

As before, to actually import the contents of the text (or zip) file, just drag and drop as you see in the diagram here.

Attributes

Like the simple text file format, create a file with the file extension .txt. This format is backwards compatible with simple text format but you may optionally use the following attributes on each card:

To use an attribute, simply start a line in the text file with the attribute name followed by a colon.

front-text: Auf wiedersehen
front-resources: auf-wiedersehen.wav
back-text: Goodbye

front-resources: saturn.jpg
Saturn
tags: space planets

All of the attributes above are optional. However, it’s recommended that if you plan to share this content with others that you assign an id to all your cards. This will make it easier for Fresh Cards to detect duplicates. (If possible, also name your resource files with a UUID naming scheme. More below.)

Okay, so let’s see more examples:

id: 44723FA2-F278-4190-ABFD-99090849DC50
Apollo 11 landed on the moon on this date
July 20, 1969

Who is this man?
front-resources: neil-armstrong.jpeg
Neil Armstrong

# You can even comment out lines using the # character
# This is another comment


# This example has an image in front and text on the back. If you only have resources on
# the front card, you must use back-text otherwise Fresh Cards will think the text
# is for the front card.
front-resources: gene-kranz.jpeg
back-text: Gene Kranz


# You can specify multiple tags. You do not need to use hashtags here.
This is the fourth planet from the sun.
Mars
tags: astronomy planets space


# Cloze deletions work as they did before.
ich habe [Hunger]


# It is highly recommended that if you are creating many cards and are planning on
# sharing and updating this deck, that you use an id for each card and each resource.
id: 3B074CF6-5A45-4B0C-9164-E0ED8422F324
This card has text and resources with uuid filenames
front-resources: 033ACA23-E7BA-423E-A2D5-03FEF3BD4643.jpeg 246E0785-A246-450E-8169-F99E160E8C5F.wav
back-text: Note that this card has both an image and an audio file


# Here's a common example you might use. It specifies an audio file for the front 
# card and a translation on the back
front-resources: auf-wiedersehen.wav
back-text: Goodbye!

# You can specify a level, this can start at 0 (the default). Cards with lower 
# get pulled into lessons before cards with higher levels. This is great if you
# have hundreds of cards that you wish to learn and want to make sure you focus
# on the easier ones first.
This is an easy card.
level: 0

This is a harder card.
level: 10

Resources

Resources referenced by the text must be put in a folder called resources. For instance, in the following example, a file called image.jpeg must be in a resources folder that is a sibling to the text file you are dragging in.

This is some front text.
front-resources: image.jpeg

If you drag a .txt file for import and it references any resources, the app will launch a File Open dialog on the resources folder. Click ‘Open’ to allow it access to the resources folder. If any resources are not found, Fresh Cards will pop up a friendly error dialog to let you know which ones were not found.

New lines

You may use “\n” in the text to indicate a new line should be started.

This is a front card\nwith multiple\n\nlines\nof\ntext
And a back card with text is just very long and will end up wrapping

This space mission failed to land on the moon but was safely returned to earth.
Apollo 13\nLaunched April 11, 1970

Why use identifiers?

If you are planning on sharing your deck with others, adding the id attribute to each card will help make it easier for others to import your deck again and again should you decide to make udpates to it. At the moment, Fresh Cards does a best guess attempt at finding duplicates of cards if you don’t specify an id attribute, but for perfomrnace reasons, it’s not able to do card comparisons when there are images or audio in the cards, unless the cards themselves have an id and the image and audio files have them as well.

To assign ids to resources, simply name them using a UUID, but maintain the file extension. For instance, you might rename a file named sayonara.wav to 457325D0-CBF4-4808-80FC-8943F48275BC.wav. Don’t worry about the file name, users of the card won’t see it anyway.

Errors

Fresh Cards will validate the import file as soon as you drag it into the app and will let you know which lines have errors. It won’t let you import until all errors are fixed.

Zipping up the contents

To make it easier to share a deck with others, you can archive the the text file and the resources folder into a .zip file. If you drag and drop the .zip file into the app, it will automatically extract the contents and do a validation. The nice thing about this is it won’t need to ask you for permission to open the resources folder.

If you plan to share your text file and resources in a .zip file, you must name the text file flashcards.txt. If the flashcards.txt file is not found in the .zip file you drag into the app, it won’t know it’s an Open Flashcard archive.

Journal sync format

Fresh Cards uses a journal system for syncing data across devices. What this means is that whenever you do anything to cards or lessons in the app, it gets recorded as an action in a journal for that specific device. For instance, when you finish a lesson, each card’s lesson score is stored as a journal entry. This entry is used to make changes to the data storage for the deck. What future features are you planning?