The tutorial file
Ce contenu n’est pas encore disponible dans votre langue.
A tutorial is a single YAML file in .ondaclip/tutorials/. Its file name is
its id: tutorials/track-orders.yaml contains id: track-orders.
A complete example
Section titled “A complete example”id: track-orders # = the file nameaccount: client # the role of a demo accounttitle: { en-US: Track your orders, es-MX: Dar seguimiento a sus pedidos }voice: { name: Charon } # optional; chosen from the id otherwiseclock: "09:30" # fixed clock (default); "real" keeps it live
hide: # blurred on every screen - { id: hub-manager-email }
writes: # API writes allowed (read-only otherwise) - "^/commands/orders$"
setup: [] # actions before the first step, not filmedsteps: - id: find-order title: { en-US: Find an order, es-MX: Encontrar un pedido } start: /orders # optional; otherwise go on from the current screen shots: - say: en-US: To find an order, type a word from its name in the search box. es-MX: Para encontrar un pedido, escriba una palabra de su nombre en el cuadro de búsqueda. type: { target: { id: orders-search-input }, text: brunch }cleanup: [] # always runs, even after a failureFile keys
Section titled “File keys”| Key | Required | What it does |
|---|---|---|
id |
yes | The id, equal to the file name. |
account |
yes | The role of the demo account that signs in (configured in the studio). |
title |
yes | The title, in every language. |
steps |
yes | The video’s chapters. Each has an id, a title, an optional start path and its shots. |
voice |
no | { name: <voice> }. See voices and languages. |
clock |
no | The time the app shows: "09:30" by default, or "real" to keep it live. Dates stay the same from one shoot to the next. |
locales |
no | This tutorial’s languages, a subset of the product’s: [en-US] to ship a new feature in one language first. Your page shows this version in the other languages. Default: every language of the product. |
hide |
no | Elements blurred on every screen: { id } (its data-ondaclip-id or data-testid) or { css }. Applies to every match, even ones that appear later. Also works per step. |
before |
no | Values set before the app code runs, for example localStorage: { theme: dark }. |
writes |
no | API paths the tutorial is allowed to write to (regular expressions). Without it, the tutorial is read-only. |
frozenResponses |
no | { url: "<regex>", delay: <ms> }: AI or external responses recorded once and then replayed, so every shoot shows the same response. |
microphone |
no | { say: { <locale>: <sentence> }, style? }: the browser hears this sentence through its microphone, for voice-driven apps. style is the style prompt for that voice. |
neverShow |
no | Text this tutorial must never show, added to the neverShow list in config.yaml. If one is visible and not hidden, the shoot stops. |
replace |
no | { file: team.json }: fictitious identities on the page (see below). |
singleShoot |
no | true keeps the captures between renders, for tutorials that write data. |
setup |
no | Actions before the first step, not filmed. |
cleanup |
no | Actions after the last step. They always run, even after a failure, to undo what the tutorial wrote. Required when the tutorial writes, unless config.yaml defines how your team resets its demo data (demoData.reset). |
quiz |
no | Questions after the video: question, choices (per language) and answer (index). |
A shot is one sentence and one action. The sentence (say) sets the length
of the shot, and the action is what happens on screen while it’s spoken.
shots: - say: { en-US: Your orders are here. } show: { id: orders-table } - say: { en-US: Open the first one. } click: { id: orders-row-1 }For every action and every way to target an element, see actions and targets.
Fictitious identities
Section titled “Fictitious identities”When the demo workspace shows real people (your team), replace gives them
fictitious names in the video without changing your data:
setup: - run: node scripts/demo-team.cjs # writes team.json in TUTORIAL_OUTPUTreplace: { file: team.json }The file is a list, written at shoot time and never committed:
[{ "email": "real@example.com", "name": "Real Name", "initials": "RN", "fake": { "email": "alex@example.com", "name": "Alex Martin", "initials": "AM" } }]Every page shows the fictitious identity, in text as well as titles and labels, each time the page changes. Profile photos aren’t loaded. If a real name or email is still visible on a filmed screen, the shoot stops.
For names that must never appear and that you don’t want in your
repository, config.yaml can read a private list at shoot time:
neverShow: { secret: sm://<project>/<secret> } (a JSON list, or one entry
per line; your infrastructure only). It’s never logged or written to the
outputs.
- Every text viewers read or hear must exist in every language of the product.
- Emails typed in a tutorial must match
safeEmail(fictitious addresses only). - Keep videos short: 50 seconds at most per clip. Split long tasks into steps or into several tutorials.
Check a file before you commit it, with tutorial.schema.json or validate_tutorial in the MCP server. For the whole folder, see the .ondaclip folder.