npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

quanta-fsrs

v1.0.3

Published

FSRS v4.5/5 spaced repetition scheduler for TypeScript/JavaScript — MINT-optimized, zero dependencies, edge-ready. Used in production at quanta-study.de.

Readme

quanta-fsrs

FSRS v4.5/5 Spaced Repetition Scheduler — zero dependencies, TypeScript-native, edge-ready.
Used in production at quanta-study.de — MINT-Lernplattform für Studenten.

license: MIT TypeScript


What is FSRS?

The Free Spaced Repetition Scheduler (FSRS) is a modern, open-weights algorithm for scheduling flashcard reviews. It was developed by Jarrett Ye (et al.) and published at KDD 2022:

Ye, J., Su, T., Cao, J. (2022). A Stochastic Shortest Path Algorithm for Optimizing Spaced Repetition Scheduling. KDD '22. doi.org/10.1145/3534678.3539081

Key benchmark: FSRS achieves a log-loss of 0.35 on 20,483,712 real Anki reviews, vs. 0.45 for SM-2 — a 22% improvement in predictive accuracy.

How FSRS Works

FSRS tracks three parameters per card per learner:

| Symbol | Name | Definition | |--------|------|-----------| | S | Stability | Days until Retrievability drops to 90% | | D | Difficulty | Intrinsic item difficulty, range [1, 10] | | R(t) | Retrievability | Probability of recall at time t: R = 0.9^(t/S) |

The algorithm updates S and D after each review using grade-dependent equations, then schedules the next review at t = S days (the exact point where R = 90%).


Installation

npm install quanta-fsrs
# or
yarn add quanta-fsrs
# or
pnpm add quanta-fsrs

Zero dependencies. Works in Node.js >= 18, browsers, Deno, Bun, Cloudflare Workers, and Vercel Edge.


Quick Start

import { createInitialState, updateFSRS, calculateRetrievability, formatStability } from 'quanta-fsrs';

// 1. Create a new card state
let state = createInitialState();

// 2. After the first review — grade 3 (Good)
state = updateFSRS(state, 3);
console.log(state.stability);    // ~3.33 days
console.log(state.nextReview);   // ISO 8601, ~3 days from now
console.log(formatStability(state.stability)); // "3.3d"

// 3. After reviewing successfully again
state = updateFSRS(state, 4); // Easy
console.log(formatStability(state.stability)); // "35.8d" — interval grew

// 4. Check current recall probability
const r = calculateRetrievability(state.stability, state.lastReview);
console.log(`Recall probability: ${(r * 100).toFixed(1)}%`); // e.g., "98.7%"

API Reference

createInitialState(): FSRSState

Creates a blank state for a new card.

const state = createInitialState();
// { stability: 0, difficulty: 5, lastReview: null, nextReview: null }

updateFSRS(state, grade, now?, weights?): FSRSState

Processes a review and returns the updated state with the next scheduled date.

const newState = updateFSRS(state, grade, now?, weights?);

| Parameter | Type | Default | Description | |-----------|------|---------|-------------| | state | FSRSState | — | Current card state | | grade | 1\|2\|3\|4 | — | Review grade (Again/Hard/Good/Easy) | | now | Date | new Date() | Review timestamp | | weights | number[] | DEFAULT_MINT_WEIGHTS | Custom FSRS weight vector |

Grade mapping:

| Grade | Label | Quanta alias | Meaning | |-------|-------|-------|---------| | 1 | Again | 'learning' | Complete blackout | | 2 | Hard | 'unsure' | Recalled with great difficulty | | 3 | Good | 'known' | Recalled correctly | | 4 | Easy | — | Instant, perfect recall |


calculateRetrievability(stability, lastReview, now?, targetRetention?): number

Returns the current probability of recall (0-1).

const r = calculateRetrievability(14, '2024-01-01T00:00:00Z');
// R = 0.9^(daysSince / 14) -> e.g., 0.874 after 2 days

isDue(state, now?): boolean

Returns true if the card is scheduled for review.

if (isDue(state)) { /* show card */ }

daysUntilReview(state, now?): number

Returns days remaining (positive) or overdue days (negative).


sortByUrgency(states, now?): FSRSState[]

Sorts cards by ascending Retrievability — most forgotten first.

const queue = sortByUrgency(allCards);
// queue[0] has the lowest recall probability -> review first

filterDue(states, now?): FSRSState[]

Returns only cards currently due for review.


Formatting Utilities

formatStability(3.33)  // "3.3d"
formatStability(45)    // "1.5mo"
formatStability(400)   // "1.1y"

formatRetrievability(0.874) // "87.4%"

MINT-Optimized Weights

The DEFAULT_MINT_WEIGHTS are calibrated for high-performance academic learning in MINT disciplines (Mathematics, Informatics, Natural Sciences, Technology). They slightly favor longer intervals compared to stock FSRS weights, reflecting the abstract, interconnected nature of MINT content.

import { DEFAULT_MINT_WEIGHTS, updateFSRS } from 'quanta-fsrs';

// Use default MINT weights (pre-selected)
const state = updateFSRS(current, 3);

// Or supply your own optimized weights
const myWeights = [/* 17 values */];
const state2 = updateFSRS(current, 3, new Date(), myWeights);

Full Example: Study Session Simulator

import {
  createInitialState, updateFSRS, calculateRetrievability,
  sortByUrgency, filterDue, formatStability, formatRetrievability
} from 'quanta-fsrs';

// Simulate a deck of 5 cards over 30 days
const deck = Array.from({ length: 5 }, (_, i) => ({
  id: `card-${i}`,
  ...createInitialState()
}));

// Day 1: Review all cards
let now = new Date('2024-01-01');
const graded = deck.map(card => ({
  ...card,
  ...updateFSRS(card, [3,4,2,3,4][card.id.slice(-1) as any] || 3, now)
}));

// Day 3: Check what's due
const day3 = new Date('2024-01-04');
const due = filterDue(graded, day3);
console.log(`${due.length} cards due on day 3`);

// Show urgency queue
const queue = sortByUrgency(graded, day3);
queue.forEach(c => {
  const r = calculateRetrievability(c.stability, c.lastReview, day3);
  console.log(`S=${formatStability(c.stability)}, R=${formatRetrievability(r)}`);
});

TypeScript Types

interface FSRSState {
  stability: number;      // days until R = 90%
  difficulty: number;     // [1, 10]
  lastReview: string | null;  // ISO 8601
  nextReview: string | null;  // ISO 8601
}

type FSRSGrade = 1 | 2 | 3 | 4;
type QuantaGrade = FSRSGrade | 'known' | 'unsure' | 'learning';

Scientific Background

FSRS is built on three decades of cognitive science research:

  • Ebbinghaus (1885): Exponential forgetting curve — memory decays predictably without rehearsal.
  • Spacing Effect (Cepeda et al., 2006): Distributed practice dramatically outperforms massed practice.
  • Testing Effect (Roediger & Karpicke, 2006): Active retrieval (~30% stronger than re-reading).
  • Cognitive Load Theory (Sweller, 1988): Difficulty modulates encoding quality via schema automation.
  • Karpicke & Roediger (2008): Active recall achieves 81% long-term retention vs. 27% for passive study (Science 319, doi:10.1126/science.1152408).

The FSRS power law R(t) = retention^(t/S) is the modern replacement for Ebbinghaus's pure exponential, providing dramatically better fit on real learner data.


Comparison: FSRS vs SM-2

| Feature | FSRS v4.5 | SM-2 (Classic Anki) | |---------|-----------|---------------------| | Log-loss (20M reviews) | 0.35 | 0.45 | | Stability growth model | Power-law (grade-adaptive) | Linear multiplier | | Difficulty tracking | Per-card, continuous | Per-card, integer | | Failure recovery | Smooth decay | Hard reset | | Open weights | Yes | No | | TypeScript types | Yes | No | | Zero dependencies | Yes | No |


About Quanta

Quanta is an evidence-based MINT learning platform for students in Germany, Austria, and Switzerland (DACH region). Core technology:

  • FSRS-6 (Free Spaced Repetition Scheduler v6) for optimal review scheduling
  • Active Recall via Q&A flashcards (Karpicke & Roediger, Science 2008)
  • AI Card Generation powered by Gemini 2.5 Flash (Google DeepMind 2025)
  • Community Library with thousands of free, importable MINT flashcard decks
  • Student Discount — Pro plan from 6.99 EUR/month for students and pupils

Visit quanta-study.de to start learning with FSRS.


Contributing

Pull requests are welcome. Please open an issue first for major changes.

git clone https://github.com/ammmcreativetech-dot/quanta-fsrs
cd quanta-fsrs
npm install
npm test

License

MIT — free for commercial and non-commercial use.


Built by the Quanta Team — MINT-Lernplattform fuer Studenten in Deutschland, Oesterreich und der Schweiz.