SRS Anywhere
SRS Anywhere is a free, browser-based flash card application using the Free Spaced Repetition Scheduler (FSRS) algorithm. It is similar to Anki, except that it is entirely contained within static files and can therefore be used anywhere a web browser is available. No server is necessary.
The most recent stable release of SRS Anywhere is hosted at https://jakob.space/dist/srs-anywhere.html. The card editor is also available at https://jakob.space/dist/deck-editor.html.
SRS Anywhere is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. SRS Anywhere is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with SRS Anywhere. If not, see https://www.gnu.org/licenses/..
Building
Just run make.
The build process is very simple, it just tangles the CSS and JavaScript code into an HTML template using sed.
Usage
Open srs-anywhere.html in a web browser and press the "Browse..." button in the top right-hand corner to load a deck of cards.
The "?" button will display the available keyboard shortcuts.
When the review is complete, you will be prompted to download a JSON file.
This contains the deck of cards updated with new scheduling parameters for your next review.
SRS Anywhere comes with a simple editor for adding, editing, and removing cards from a deck.
Open deck-editor.html and press the "Browse..." button in the top right-hand corner to load a deck of cards.
The page will populate with one or more tables, each corresponding to a specific type of card, and input fields for part of the card.
The button labeled with a plus sign (+) will add a card of that type to the deck, with an automatically-generated ID.
Press the "Download JSON" button in the top right-hand corner to download the modified deck.
Format for Cards
The cards.json file is an array of objects containing at least the keys id, front, and back.
The only requirement for id is that it's unique across the deck: it could be a UUID, but it could also be something more descriptive.
front and back are HTML fragments that are injected into the page when the card is shown.
Additional keys are permissible.
Keys generated and modified by SRS Anywhere are prefixed by the _ character.
Example
[
{
"id": "cca013c4-450a-41a1-abed-28abdc73413a",
"front": "What is the capital of Virginia?",
"back": "Richmond."
},
{
"id": "a8fc5101-2d22-4b20-b475-1db00f120654",
"front": "What is accomplished by Article II of the United States Constitution?",
"back": "Article II of the United States Constitution establishes the executive branch of the federal government, which carries out and enforces federal laws."
}
]
Custom Cards
Custom card types can be defined in a srs-anywhere-custom-card-types.js file.
To register a new card type, add it as a new entry to the CARD_TYPES object, where the key is the the name of the card type.
A card type should be an object containing at least the following keys: validate, front, and back.
validate takes the card and throws an Error if it is malformed.
front returns the desired HTML code for the front of the card.
back returns the desired HTML code for the back of the card.
Optionally, showFront and showBack are functions that are evaluted when the front or back of the card are shown, respectively.
For example, to define a card type for a cloze deletion test:
const CLOZE_REGEX = /\[.*?\]/ig;
CARD_TYPES["clozeAll"] = {
"validate": function (card) {
if (typeof card.back !== "string") {
throw new Error(`malformed card ${card.id}: invalid back (should be string)`)
}
if (!CLOZE_REGEX.test(card.back)) {
throw new Error(`malformed card ${card.id}: contains no cloze;
please enclose deletion in brackets (e.g., [...])`)
}
},
"front": (card) => card.back.replaceAll(CLOZE_REGEX, '[...]'),
"back": (card) => card.back
};
The type key in the cards JSON file associates an entry with the custom card type.
{
"id": "cca013c4-450a-41a1-abed-28abdc73413a",
"type": "clozeAll",
"back": "This is a card containing a [cloze deletion]!"
}