Skip to main content

Product tours

AfriAnnotate inherits a product-tour backend from upstream: an API that tracks, per user and per tour, whether a short guided walkthrough is ready, completed, or skipped, and serves the tour's steps from a YAML file.

What's not there: the web app doesn't call this API or render tours. Nothing pops up for users on first visit, there's no "Skip tour" control in the UI, and no tour ever fires. Treat this page as a description of the plumbing, useful if you plan to build a tour overlay on top of it — not as a feature your annotators will see today.

What exists​

The API​

GET /api/current-user/product-tour?name=<tour> (signed-in users only) returns the caller's state for that tour. If the user has no record yet, one is created on the spot in the ready state. The response carries:

  • state — ready, completed, or skipped
  • steps — the step list read from the tour's YAML file
  • awaiting — true when the YAML lists dependencies (other tour names) that this user hasn't completed yet
  • interaction_data — free-form JSON the client may store (index, action, type, status, additional_data)

PATCH on the same URL updates state and interaction_data. The endpoint is hidden from the generated OpenAPI schema.

The YAML configs​

Tour content is YAML, not code. Files live at:

label_studio/users/product_tours/configs/
├── create_prompt.yml
├── prompts_page.yml
├── show_ask_ai.yml
└── show_autolabel_button.yml

A tour's name is its file stem. Each file holds:

  • steps — a list of entries with target (CSS selector), placement, title, and content (HTML strings), plus whatever extra per-step options the rendering library would accept
  • dependencies — optional list of tour names that must be completed first

The four shipped configs describe upstream's Prompts / Ask-AI screens, which AfriAnnotate doesn't expose, so they don't match any page in the app.

Files are read from disk on each request — adding or editing a .yml needs no restart and no registration step. A request for a name with no matching file is rejected with the list of available tours.

Per-user state​

State lives in the UserProductTour table (one row per user per tour: name, state, interaction_data, timestamps). It isn't registered in the Django admin, and there's no user-facing or platform-settings control to reset or disable tours; resetting means deleting rows directly.

If you want tours in the app​

You'd add a client that, on the relevant page, fetches the tour by name, renders steps with an overlay library, and PATCHes state=completed / skipped when the user finishes or dismisses. Until then, onboarding relies on these docs and the persona-based onboarding flows.

What's next​