Progress tracking
Every quiz records whether it has been answered and whether the answer was correct. That progress is saved to the
browser’s localStorage, so it survives reloads and revisits.
How it is stored
Section titled “How it is stored”- Progress is keyed by the page path plus each quiz’s id.
- A quiz’s id comes from its
idprop, falling back to a stable hash of itstitle. Because the key is stable rather than positional, progress survives reordering quizzes and rebuilding the site. - The whole page’s progress is stored under a single key, validated on load, and discarded if it is ever corrupted or unexpectedly large. A bad write can never break a page.
Try it
Section titled “Try it”Answer this quiz, then reload the page, and your answer is restored automatically:
Will this answer still be here after a reload?
- Yes
- No
It is saved to local storage and restored when the page loads.
<Quiz>Will this answer still be here after a reload?
- [x] Yes- [ ] No
It is saved to local storage and restored when the page loads.</Quiz>Aggregate progress
Section titled “Aggregate progress”When used as a Starlight plugin, a compact progress widget appears in the table of contents (right sidebar on desktop,
and the mobile ToC), showing how many quizzes on the page are answered and how many are correct. On narrow screens
(where there is no right sidebar) a full-width version with a reset link is rendered at the foot of the page instead.
The widget hides itself on pages without quizzes, and you can turn it off with the
progressTracker plugin option. To place it somewhere specific
(or to use it without Starlight), import and drop in the
<QuizProgress /> component yourself.
A <QuizResults> panel shows the same progress in-page and lets the reader
reset every quiz at once. Both read from a central tracker that also broadcasts window events, so you can build your own
progress UI on top of it.
Build your own progress UI
Section titled “Build your own progress UI”The tracker dispatches two events on window whenever progress changes:
| Event | Detail |
|---|---|
starlight-quiz:progress |
{ total, answered, correct, percentage, score } (counts plus 0–100 %) |
starlight-quiz:reset-all |
(none), fired when every quiz on the page is reset |
percentage is answered / total; score is correct / total. Both events are typed on WindowEventMap, so
TypeScript knows event.detail in editors. Listen for them to drive a custom widget:
window.addEventListener('starlight-quiz:progress', (event) => { const { answered, total, correct, percentage, score } = event.detail; console.log(`Answered ${answered}/${total} (${percentage}%), score ${score}%`); document.querySelector('#my-progress')?.style.setProperty('--done', String(percentage));});
window.addEventListener('starlight-quiz:reset-all', () => { console.log('All quizzes on this page were reset');});The progress event fires whenever progress changes, including as each quiz registers on load (restoring saved
answers), so a listener gets the current totals without special-casing the initial render.
answered: 0 / 0 (0%)