Agent skill
onboarding-architect
Expert assistant for the onboarding system in Raamattu Nyt. Two tour modes: showcase (fullscreen modal with images) and guided (spotlight + tooltip on DOM targets). Use when (1) adding new onboarding tours, (2) modifying tour steps, images, or placement, (3) working with the admin panel at /ohjaamo/onboarding, (4) adding tour trigger points (URL params, UserMenu, buttons), (5) managing Supabase Storage onboarding-images bucket, (6) editing i18n keys for onboarding texts.
Install this agent skill to your Project
npx add-skill https://github.com/Spectaculous-Code/raamattu-nyt/tree/main/.claude/skills/onboarding-architect
SKILL.md
Onboarding Architect
Architecture
packages/shared-onboarding/ # Reusable engine (no app imports)
├── src/
│ ├── types.ts # Tour, OnboardingStep, Placement, Align
│ ├── OnboardingProvider.tsx # React context: useReducer state machine
│ ├── useOnboarding.ts # Consumer hook: startTour, nextStep, etc.
│ ├── ShowcaseModal.tsx # Fullscreen modal (lazy-loaded)
│ ├── GuidedOverlay.tsx # Spotlight overlay (lazy-loaded)
│ ├── GuidedTooltip.tsx # Radix Popover tooltip (side, align, sideOffset)
│ ├── storage.ts # localStorage: markTourCompleted, isTourCompleted
│ └── index.ts # Public exports
apps/raamattu-nyt/src/onboarding/ # App-level tour definitions
├── tours/
│ ├── showcaseHome.ts # Showcase tour (7 steps, i18n keys + CTA)
│ ├── searchBasics.ts # Guided tour: search basics (4 steps)
│ ├── searchQuestionsTab.ts # Guided tour: Q&A tab (4 steps)
│ └── index.ts # useAllTours() hook: resolves i18n + images + overrides
apps/raamattu-nyt/src/hooks/
└── useOnboardingImages.ts # Fetches images + guided overrides from app_config
apps/raamattu-nyt/src/pages/
└── AdminOnboardingPage.tsx # Admin: tour list, image upload, guided placement
Tour Modes
| Mode | Component | Behavior |
|---|---|---|
showcase |
ShowcaseModal | Fullscreen modal, image per step, CTA buttons, keyboard/touch nav |
guided |
GuidedOverlay + GuidedTooltip | Spotlight on [data-onboard="..."] target, Radix Popover tooltip |
Adding a New Showcase Tour
- Create
apps/raamattu-nyt/src/onboarding/tours/myTour.ts:
import type { Tour } from "@shared-onboarding";
interface ShowcaseStepDef {
id: string;
titleKey: string;
descriptionKey: string;
ctaKey?: string;
ctaHref?: string;
}
const myTourDef: ShowcaseStepDef[] = [
{
id: "step1",
titleKey: "onboarding.showcase.myTour.step1.title",
descriptionKey: "onboarding.showcase.myTour.step1.description",
},
];
export function createMyTour(
images?: Record<string, string>,
t?: (key: string) => string,
): Tour {
const tr = t ?? ((key: string) => key);
return {
id: "my-tour",
mode: "showcase",
steps: myTourDef.map((def) => ({
id: def.id,
title: tr(def.titleKey),
description: tr(def.descriptionKey),
image: images?.[def.id],
cta: def.ctaKey ? { label: tr(def.ctaKey), href: def.ctaHref } : undefined,
})),
};
}
export const myTour: Tour = createMyTour();
- Add i18n keys to
public/locales/fi/common.jsonandpublic/locales/en/common.json - Register in
tours/index.ts— import, add touseAllTours()return array - Upload images via admin panel or set in
app_configkeyonboarding_showcase_images
Adding a New Guided Tour
- Create step definitions with
GuidedStepDef:
import type { GuidedStepDef } from "./searchBasics";
export const myGuidedDef: { id: string; mode: "guided"; steps: GuidedStepDef[] } = {
id: "my-guided-tour",
mode: "guided",
steps: [
{
id: "first-element",
titleKey: "onboarding.guided.myTour.first.title",
descriptionKey: "onboarding.guided.myTour.first.description",
target: '[data-onboard="my-first-element"]',
placement: "bottom",
align: "center",
sideOffset: 12,
},
],
};
- Add
data-onboard="my-first-element"attribute to target DOM elements - Add i18n keys to locale files
- Register in
tours/index.ts:- Import def into
guidedTourDefsarray - Add static fallback to
allToursarray
- Import def into
Trigger Points
| Trigger | How it works |
|---|---|
startTour(tourId) |
Direct call via useOnboarding() hook |
URL param ?tour=tourId |
SearchPage detects param in useEffect, calls startTour with 500ms delay |
| UserMenu dropdown | Items in "Tutustu ominaisuuksiin" section call startTour or navigate |
| Button/link | Navigate to page with ?tour=tourId query param |
To add a URL-triggered tour to any page:
const [searchParams] = useSearchParams();
const { startTour } = useOnboarding();
const tourTriggered = useRef(false);
useEffect(() => {
const tourId = searchParams.get("tour");
if (tourId && !tourTriggered.current) {
tourTriggered.current = true;
setTimeout(() => startTour(tourId), 500);
}
}, []);
Admin Overrides (app_config)
Two app_config keys control dynamic behavior:
| Key | Shape | Purpose |
|---|---|---|
onboarding_showcase_images |
{ "tour-id": { "step-id": "https://url" } } |
Showcase step images |
onboarding_guided_overrides |
{ "tour-id": { "step-id": { placement?, align?, sideOffset? } } } |
Guided tooltip positioning |
Admin panel at /ohjaamo/onboarding provides UI for both.
Supabase Storage
Bucket: onboarding-images (public read, authenticated write)
Path pattern: onboarding/{tourId}/{stepId}.webp
Key Types
// packages/shared-onboarding/src/types.ts
type TourMode = "showcase" | "guided";
type Placement = "top" | "bottom" | "left" | "right";
type Align = "start" | "center" | "end";
interface OnboardingStep {
id: string;
title: string;
description: string;
image?: string; // Showcase only
target?: string; // Guided only: CSS selector
placement?: Placement; // Guided only
align?: Align; // Guided only
sideOffset?: number; // Guided only (default 12)
cta?: { label: string; href?: string; action?: () => void };
beforeStep?: () => void | Promise<void>;
}
interface Tour { id: string; mode: TourMode; steps: OnboardingStep[] }
Resolution Pipeline
useAllTours() in tours/index.ts resolves tours at runtime:
- i18n: Translation keys resolved via
useTranslation("common") - Images:
useOnboardingImages(tourId)mergesapp_configimages into showcase steps - Overrides:
useGuidedOverrides()mergesapp_configplacement/align/sideOffset into guided steps
Code defaults are always fallback — admin overrides win when present.
State Machine
idle → START(tourId) → active { tourId, stepIndex: 0 }
→ NEXT → stepIndex++ (or COMPLETE if last)
→ PREV → stepIndex-- (min 0)
→ SKIP/COMPLETE → completed { tourId } → idle
Completion persisted to localStorage: onboarding_completed:{tourId}.
References
- architecture.md — Complete file map, data flow, existing tours, React Query keys
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
docs-updater
Expert assistant for keeping documentation synchronized with code changes in the KR92 Bible Voice project. Use when updating API docs, maintaining architecture diagrams, syncing README, updating CLAUDE.MD, or generating documentation from code.
ai-prompt-manager
Expert assistant for managing AI prompts, features, and configuration in the KR92 Bible Voice AI system. Use when creating AI prompts, configuring AI features, managing prompt versions, setting up AI bindings, or working with AI pricing and models.
performance-auditor
Expert assistant for monitoring and optimizing performance in the KR92 Bible Voice project. Use when analyzing query performance, optimizing database indexes, reviewing React Query caching, monitoring AI call costs, or identifying N+1 queries.
edge-function-generator
Expert assistant for creating and maintaining Supabase Edge Functions for the KR92 Bible Voice project. Use when creating Edge Functions, setting up CORS, integrating shared modules, adding JWT validation, or configuring environment variables.
admin-panel-builder
Expert assistant for creating and maintaining admin panel pages in the KR92 Bible Voice project. Use when creating admin pages, building admin components, integrating with admin navigation, or adding admin features.
lint-fixer
Expert assistant for analyzing and fixing linting and formatting issues in the KR92 Bible Voice project using Biome and TypeScript. Use when fixing lint errors, resolving TypeScript issues, applying code formatting, or reviewing code quality.
Didn't find tool you were looking for?