FAQ
Q: Can I write tutorials in Markdown?
The content field of a step is plain text. The renderer does NOT parse Markdown — it shows the raw string. Use plain prose. For links, embed full URLs (they're not auto-linkified either; consider using the image_url field for visual aids instead).
Q: How many steps should a tutorial have?
The seeder convention is 5-7 steps. Anything beyond 7 is usually two tutorials. The panel scrolls fine with more, but operator attention fades fast.
Q: Can I show different tutorials to different operator roles?
Not directly. Tutorials are per-(page_key, language), not per-role. The workaround is the RequirePrivilege middleware on the page itself — if a role can't see the page, they never trigger the tutorial. But once a page is visible, every operator sees the same tutorial content.
Q: Can a tutorial reference another tutorial?
Only via prose. You can write "see the Help Tutorial for Vendor Moderation" in a step's content; the operator has to navigate manually. There is no in-app cross-link.
Q: I edited a default tutorial. Will re-seed overwrite my edit?
No. POST /admin/help-tutorials/seed uses ON CONFLICT (page_key, language) DO NOTHING. Your edit is preserved. The seed only fills MISSING rows.
Q: How do I force a row to use the latest default content?
Edit the row in the admin UI — copy the new content from defaultTutorialsEN() in backend/internal/core/admin/help_tutorials.go and paste it in. There's no "reset to default" endpoint.
Q: My tutorial doesn't appear after I save it.
Three likely causes:
- Page Key mismatch. Open the page, check what
getPageKey(pathname)returns (you can console-log it fromfrontend/src/lib/help-tutorials.ts). The DB row'spage_keymust match exactly. - Language mismatch. Your tutorial exists only in a language that isn't your admin session's language, and there is no
enrow to fall back to. Add the missing locale or anenrow. - is_active = false. Re-check the toggle — Draft tutorials are skipped.
Q: Can I version tutorials?
No. Each (page_key, language) has exactly one row. To preserve history, copy the body to your changelog before editing.
Q: How are video embeds handled?
The panel's getEmbedUrl() recognises YouTube watch URLs (youtube.com/watch?v=XXXX, youtube.com/embed/XXXX, youtu.be/XXXX) and Vimeo (vimeo.com/XXXXX). For anything else (Loom, Wistia, Bunny, S3 mp4), the panel renders an external-link button instead of an embed. To use Loom, host the same video on YouTube unlisted as a workaround.
Q: What if my YouTube link is age-restricted or unlisted?
Unlisted works (the embed loads). Age-restricted YouTube videos require a signed-in viewer; the iframe will show YouTube's restriction prompt. Don't gate operator help behind sign-in walls.
Q: Can operators search tutorials?
Yes — the admin list at /admin/help-tutorials has a search box and a backend search query parameter that matches against title and page_key (case-insensitive ILIKE). But the runtime help panel itself has no search — operators get the tutorial for the page they're on, not a directory.
Q: How do I export all tutorials for backup?
There is no dedicated export endpoint in the MVP. The list endpoint paginates; you can script:
for page in $(seq 1 N); do
curl -s -H "Authorization: Bearer $TOKEN" \
"$API/api/v1/admin/help-tutorials/?language=all&page=$page&per_page=100"
done | jq -s '.'
For richer exports, query the DB directly (the table is plain Postgres + JSONB).
Q: Can I disable just the auto-open without disabling the module?
Per-user: localStorage.setItem("help-tutorials-auto-open", "false") in the operator's browser.
Platform-wide: there is no admin setting. You'd need to fork <HelpButton> and remove the auto-open useEffect, or set the localStorage key on first login via a custom shell script.
Q: Why does the help icon sometimes blink green even after I clicked "Got it"?
Most often: cross-device drift (you marked read on desktop, mobile localStorage is fresh) OR the server-side mark POST failed silently (network blip on click). Re-click "Got it" — the localStorage write is synchronous and won't fail.
Q: Can the seed defaults be filtered to specific modules?
No. POST /admin/help-tutorials/seed iterates the entire defaultTutorialsEN() slice. If you want to seed only a subset, edit the code OR insert specific rows directly:
INSERT INTO help_tutorials (page_key, language, title, ...)
VALUES (...)
ON CONFLICT (page_key, language) DO NOTHING;
