9.2 KiB
AI Agent Context Guide: Respellion Learning Platform
Welcome, fellow AI agent! If you are reading this, you are tasked with maintaining or extending the Respellion Learning Platform. This document provides the critical context, architectural patterns, and design standards you need to successfully work on this codebase.
1. Architectural Overview
This is a single-page React application built with Vite, backed by PocketBase as the database and auth layer.
- Frontend: React, React Router, Tailwind CSS.
- Backend: PocketBase (self-hosted). All data is stored in PocketBase collections, not localStorage.
- Animations: Framer Motion (used extensively for page transitions, podium effects, and gamification feedback).
- Icons: Lucide React.
- Visualizations: D3.js (used strictly for the Admin Knowledge Graph).
2. State Management & Storage (Critical)
All persistent data lives in PocketBase. The data access layer is in src/lib/db.js, which wraps the PocketBase SDK client from src/lib/pb.js.
PocketBase Collections:
topics— Knowledge graph nodes (id,label,type,description).relations— Knowledge graph edges (source,target,type).content— AI-generated learning modules per topic (topic_id,data).quiz_banks— Banks of AI-generated questions per topic (topic_id,questions[]).quiz_results— User test scores (user_id,week_number,score,total,percentage, etc.).quiz_cache— Cached weekly quiz for a user (user_id,week_number,questions[],meta).learn_progress— Whether a user completed the weekly learning session (user_id,week_number,done).leaderboard— Points ledger (user_id,name,points,tests_completed).team_members— Registered users with PIN auth (name,role,pin).sources— Uploaded source documents and their extraction status (name,status,error).settings— Key/value store for app-wide settings (key,value).
localStorage is only used for admin browser settings (not user data):
respellion:admin:anthropic_key— Anthropic API key.respellion:admin:model— Model override.respellion:admin:use_simulation— Simulation mode toggle.kb:suggestions— Pending/approved/rejected graph deltas proposed by R42. Always mutated viakbStore(see §8).quiz:active:{userId}— Boolean flag set while the user is mid-quiz. R42's FAB is hidden when this is true (quiz-integrity rule).chat:thread:{userId}— Persisted R42 conversation, capped at 50 messages.
Session: User login is PIN-based. The logged-in user's ID is stored in sessionStorage under respellion_session and resolved against team_members on app load (see src/store/AppContext.jsx).
Important: All db.js functions are async. Always await them — omitting await will silently pass a Promise where data is expected.
Auto-Cancellation: The PocketBase JS SDK has auto-cancellation enabled by default. This causes concurrent identical requests (like db.getTopics() during React StrictMode renders or concurrent Promise.all) to abort with ClientResponseError 0. This feature is globally disabled in src/lib/pb.js via pb.autoCancellation(false) to prevent UI crashes during concurrent fetching.
3. The AI Integration (Anthropic)
The application calls the Anthropic API via a proxy to avoid CORS issues.
- Location:
src/lib/api.js. - Proxy: In Docker,
/api/anthropicis proxied via Nginx to the Anthropic API endpoint. In local dev, configurevite.config.jsto proxy the same path. - JSON Enforcement: Prompts must strictly enforce that Claude returns only raw JSON. Do not let the AI wrap the response in markdown blocks — a regex strip via
.match(/\{[\s\S]*\}/)is already applied in all service files.
4. Design System & Aesthetics
Respellion relies on a premium, modern aesthetic.
- CSS Variables: Rely heavily on the variables defined in
src/index.css.- Colors:
var(--color-bg),var(--color-paper),var(--color-teal),var(--color-accent). - Radii:
var(--r-sm),var(--r-lg),var(--r-org)(an organic, pill-like shape used for badges and podiums).
- Colors:
- Tailwind: Tailwind is mapped to these CSS variables. Avoid hardcoding random hex codes. Use the existing Tailwind classes like
bg-teal,text-fg-muted, andborder-bg-warm. - Components: Always reuse the UI primitives in
src/components/ui/(Card.jsx,Button.jsx,Tag.jsx,Input.jsx).
5. Gamification Rules
If you are extending the Gamification system (src/pages/Leaderboard.jsx):
- Tests grant +2 points per correct answer (handled in
testService.js → saveTestResult). - A 100% score grants the Perfectionist badge (computed at render time in
Leaderboard.jsx). - Completing 1 test grants First Steps, completing 5 grants Veteran.
- Points are accumulated in the
leaderboardcollection viadb.upsertLeaderboardEntry.
6. Docker & Deployment
The app is fully containerized. PocketBase runs as a sidecar service.
- Build:
docker build -t respellion-app:latest . - Run:
docker compose up -d(seedocker-compose.yml). - Nginx: Ensures any frontend route not matching a static file falls back to
index.html(SPA support). The/api/anthropicpath is proxied to the Anthropic API. The/pbpath is proxied to the PocketBase service. - PocketBase URL: Resolved from
VITE_PB_URLenv var, or falls back towindow.location.origin + '/pb'(seesrc/lib/pb.js).
8. R42 Chatbot
The platform ships a global chatbot avatar called R42, rendered as the Respellion { r } brand mark in three states (idle / typing / error).
- Mark component:
src/components/ui/Mark.jsx. Pure SVG; renders the brand mark withstate,size,theme,showFrame,brace,letterprops. Requires theBallPillfont (loaded via@font-faceinsrc/index.css, served frompublic/fonts/BallPill-light.otf). Falls back to JetBrains Mono (already loaded). - Chat module:
src/components/chat/.ChatLauncher.jsx— global FAB; auto-hides whenquiz:active:{userId}is set. Listens to therespellion:quiz-statewindow event for fast updates.ChatWindow.jsx— 380×480 chat panel; Esc closes; renders messages fromuseChat.useChat.js— owns the message list, persists tochat:thread:{userId}, callsanthropicApi.chat().buildKbContextis async (PocketBase), sosend()is fully async.prompts.js— system prompt, greeting, and thepropose_graph_deltatool spec.rag.js— fetcheskb:topics+kb:relationsfrom PocketBase; lazy-loadskb:content:{id}only when a topic is mentioned. Returns{ context, topics }sovalidateDeltacan reuse the fetched topics without a second round-trip.
- Multi-turn API:
anthropicApi.chat(systemPrompt, messages, { tools })insrc/lib/api.js. Returns the raw Anthropic response ({ content: [...], stop_reason }) so callers can read both text blocks andtool_useblocks. No API key header — Caddy proxy injects it server-side, matching the existinggenerateContentpattern. - Quiz-integrity rule:
src/pages/Testen.jsxsetsquiz:active:{userId}=trueon start and clears it on every non-quiz phase + unmount, plus dispatches arespellion:quiz-stateevent. Never bypass this — letting users ask R42 mid-quiz would break scoring. - Graph refinement: when R42's
tool_useblock proposes apropose_graph_delta,rag.jsvalidates (no duplicate ids, no orphan relations, caps 3 topics / 5 relations) and surfaces a confirmation chip inline.- Admin user clicks Ja —
kbStore.applyDeltawrites to PocketBase viadb.upsertTopic/db.addRelationimmediately. - Non-admin clicks Ja —
kbStore.appendSuggestionqueues an entry inkb:suggestionslocalStorage (statuspending).
- Admin user clicks Ja —
- Admin approval UI:
src/components/admin/SuggestionsQueue.jsx, mounted at the top of the Knowledge Graph admin panel. Approve callskbStore.approveSuggestion(id)which runs the sameapplyDeltamerge (async, PocketBase) and flips status toapproved. Reject flips torejectedfor audit. - kbStore:
src/lib/kbStore.jsis the single source of truth for KB mutations from the chatbot path. Topics/relations go to PocketBase; suggestions queue goes to localStorage. Dispatchesrespellion:kb-updatedafter any write so the D3 graph and the queue panel refresh without a reload.
9. How to Add New Features
- Define Schema: Add a new PocketBase collection via the Admin UI or the init script (
scripts/setup-pb-collections.mjs). - Add DB Helpers: Add async CRUD functions in
src/lib/db.js. - Build UI: Create components using
Card,Button, andframer-motionfor smooth entry (animate-in fade-in slide-in-from-bottom-4). - Wire Logic: Connect to
src/store/AppContext.jsxif it requires global user context, otherwise manage state locally. - Test: Run the Docker stack (
docker compose up) to ensure no build errors exist.
Good luck! You are building a platform that empowers continuous learning. Keep it fast, keep it beautiful, and keep the user engaged.