Skip to content

Astro installation

The quiz components have no hard dependency on Starlight: the Starlight-specific code lives only in the plugin (starlight-quiz) and is never imported by starlight-quiz/components. So you can use <Quiz> and friends in any Astro project.

The trade-off is that the Starlight plugin does a lot of wiring for you. Without it, you do that wiring yourself. Here is the whole list, and the rest of this page walks through each one.

The Starlight plugin… Without it, you…
Injects the theme CSS import the stylesheet once yourself
Injects 13 locales and picks one per page pass label props (or get English)
Adds the progress widget to the table of contents and page footer place <QuizProgress /> where you want it
Applies site-wide quizDefaults via middleware set props per component (or add your own middleware)
Emits the quiz manifest and validates quizzes at build time don’t get these — they are plugin-only

Install the package, then import the stylesheet once (for example in a shared layout) so every quiz is styled:

Terminal window
npm install starlight-quiz
src/layouts/Layout.astro
---
import 'starlight-quiz/styles';
---

The theme follows CSS variables that fall back to sensible light/dark defaults when Starlight’s colour tokens aren’t present, so quizzes look right on a plain Astro site too.

Quizzes are written as markdown (a task list, [[blanks]], blockquote feedback). That markdown only renders in .md / .mdx files, not in a plain .astro file, so author your quizzes on an MDX page:

src/pages/quiz.mdx
---
layout: ../layouts/Layout.astro
---
import { Quiz } from 'starlight-quiz/components';
<Quiz submitLabel="Check answer">
Is the sky blue?
- [x] Yes
- [ ] No
</Quiz>

Under Starlight, the progress widget is injected into the table of contents and the page footer automatically. There is no equivalent to hook into here, so drop <QuizProgress /> wherever you want it. It hides itself on pages with no quizzes:

src/pages/quiz.mdx
import { Quiz, QuizProgress, QuizResults } from 'starlight-quiz/components';
<QuizProgress />
<Quiz></Quiz>
<Quiz></Quiz>
<QuizResults />

<QuizResults> (the score panel) and <QuizIntro> work the same way, with no Starlight needed.

With Starlight, every label is translated automatically through Starlight’s i18n. Without it there is no translation function, so each label falls back to its bundled English default unless you pass a prop:

<Quiz submitLabel="Vérifier" resetLabel="Recommencer" correctLabel="Correct !" incorrectLabel="Pas tout à fait…">
</Quiz>

The precedence is: an explicit prop wins, then Starlight’s translation (absent here), then the bundled English default. Every overridable label is listed in Configuration, and Translations explains the full resolution order.

The plugin’s quizDefaults option (turn confetti off everywhere, switch to manual submit, and so on) is delivered to the components through Astro.locals. In a plain Astro project the simplest approach is to set the relevant prop on each component. If you want true site-wide defaults, add a small middleware that publishes them, and every quiz will pick them up:

src/middleware.ts
import { defineMiddleware } from 'astro:middleware';
export const onRequest = defineMiddleware((context, next) => {
context.locals.starlightQuiz = { defaults: { confetti: false, autoSubmit: false } };
return next();
});

An explicit prop on a component still overrides these.

The quiz manifest and build-time validation are wired up by the Starlight plugin’s build integration, so they are not available in a plain Astro project. That means the terminal runner and QTI export, which read the manifest, need the plugin (or a manifest produced some other way).

Everything else, including view transitions, works without Starlight: the components are self-initialising custom elements that re-initialise on navigation.