Skip to main content
Canonical format, version 1. The resolver and evaluation shapes below match src/core/course/resolve-binding.ts and the exercise types.
A learner app does three things: resolve bindings to values, render each fragment by its role, and grade the response against the exercise’s evaluation.

Resolving bindings

Build a resolver from the loaded course (a map of records and assets), then resolve any binding to a ResolvedValue. Resolution never throws: an unresolved reference returns { kind: "missing", reason } so a broken reference degrades instead of crashing.
How each binding resolves:

Rendering fragments

A RenderFragment pairs a binding with a role (primary, supporting-text, visual, audio, translation, and so on). Resolve the binding, then render by role and value kind: text values as text, asset values by asset kind (image, audio player, video), and a record value with its presentation. Roles are open strings; render the ones you know and fall back sensibly for the rest.

Grading

Every exercise carries one evaluation. Grade against stable IDs or accepted-value bindings, never against displayed text.

Accepted values and normalization

Typed grading resolves accepted bindings (usually a field such as field_alternate_answers) and compares under normalization, so “a cat” and “cats” pass without duplicating text in the exercise.
speaking grades only in the learner app: it needs a microphone and on-device speech recognition. The exercise authors the target phrase and strictness; nothing is recorded or uploaded by Studio. If you build a learner app, you own the recognition and scoring for this type.

Localized authored text

Titles, instructions, and literal text fragments may be a plain string or a map of locale tag to string. Resolve against the course’s defaultLocale, or against the learner’s language if you offer one: try an exact tag, then the base language (pt-BR to pt), then any available entry.
Taught content is not localized this way. It lives in records, where each language is its own field and list items carry their own locale.

Media playback

An asset resolution gives you the Asset record. Load the binary from the asset’s own directory using its file (when availability is ready); a placeholder asset has no file yet. Use mimeType to choose the player.