Feature Owner: scorevi (Sean Patrick Caintic)
Module: Design
Priority: P0
Sprint #12: Fully Implemented
Date: 2026-06-29
EXECUTIVE SUMMARY
What is this feature?
A Zod-validated canvas metadata schema (canvasMetadataSchema) that defines the structure for React Flow visual canvas state, persisted in a Supabase JSONB column on the quests table. Includes bidirectional sync between the visual canvas and the form-based editor.
Why does it matter?
The visual canvas editor is the core differentiator for WyzQuests — creators design quest flows visually. Without a strict schema, the canvas state could become corrupted, causing the React Flow editor to crash or lose work.
What's the MVP scope?
Zod schemas (canvasNodeSchema, canvasEdgeSchema, canvasMetadataSchema) in shared/schemas/questSchema.ts. Database migration with JSONB column, CHECK constraint, and GIN index. Canvas-to-form and form-to-canvas sync utilities in lib/canvas-sync/. AI curriculum-to-canvas converter and deterministic layout engine.
1. USER PAIN POINT & SOLUTION
Current State (Without Feature)
Quest creators have no visual way to design branching quest paths. All quest structure is linear and form-driven, making complex branching learning paths impossible to visualize or author.
Pain Point
Emotional: Frustration and overwhelm when designing multi-path learning experiences through form fields alone.
Functional: Cannot visualize decision points, branching paths, or quest flow. Prone to logical errors in quest structure.
Business Impact: Limits the platform to simple linear quests, reducing appeal for sophisticated instructional designers.
Future State (With Feature)
Creators use a React Flow visual canvas with draggable nodes and connectable edges. The canvas state is validated at every save and bidirectional sync keeps the form editor and canvas consistent.
Marketing Hook
"Design quests the way learners experience them — visually."
2. 4D FRAMEWORK MAPPING
Diagnose
N/A — schema/infrastructure concern.
Design
Core enabler of the Design phase. Creators visually lay out quest flow, add branching logic, and connect nodes. The canvas schema validates every save.
Develop
The canvasToForm.ts utility extracts content cards from canvas nodes so the Develop phase (activity authoring) has structured data.
Deliver
Canvas metadata includes quest structure for SCORM/xAPI export — branching paths are preserved.
3. USER FLOWS
Entry Point
Creator opens the dual editor (Form + Canvas). The canvas loads existing canvas_metadata from the database.
Success Criteria
Nodes and edges are rendered in React Flow. Saving persists validated canvas state to Supabase. Switching between Form and Canvas views shows consistent data.
Main Flow (Happy Path)
Creator enters the dual editor for a quest.
React Flow renders nodes and edges from
canvas_metadata.nodesandcanvas_metadata.edges.Creator drags nodes, creates edges, adds branching logic.
On save,
canvasMetadataSchemavalidates the payload.Valid canvas state is stored in
quests.canvas_metadataJSONB column.
Edge Cases
Empty canvas: Defaults to
{ nodes: [], edges: [], quest_mode: "exploration", title: "" }.Invalid JSON in DB: CHECK constraint rejects writes where
nodesoredgesis not an array.Zod validation failure: API returns
ApiResponseHelper.validationError()with 400 status.Linear mode: Canvas is disabled; only the form editor is active.
Decision Points
IF
quest_mode === "linear"→ Canvas view hidden, only form editor shown.ELSE (
quest_mode === "exploration") → Dual editor with Canvas enabled.
4. INFORMATION ARCHITECTURE
Primary Information (Always visible)
canvasMetadataSchema:{ nodes: CanvasNode[], edges: CanvasEdge[], quest_mode: "linear" | "exploration", title: string }CanvasNode:{ id: string, x: number, y: number, type: string, data?: Record<string, unknown> }CanvasEdge:{ id?: string, source: string, target: string, sourceHandle?: string | null, targetHandle?: string | null, label?: string, logic?: string, edgeType?: string }
Secondary Information
Edge
logicfield for conditional branching.Edge
edgeTypefor differentiated edge styling.
Actions
Primary CTA: Save Canvas — persists to Supabase via PUT /api/creator/update-quest-canvas with updateCanvasSchema.
Secondary Actions: Reset Canvas, Import from AI Curriculum.
5. WIREFRAMES
[Excluded — existing UI]
6. WIREFLOWS
Excluded.
7. PROTOTYPE
[Excluded — existing implementation]
8. BACKEND SCHEMA
Database Tables
-- Migration: 001_add_canvas_metadata.sqlALTER TABLE questsADD COLUMN IF NOT EXISTS canvas_metadata JSONB NOT NULL DEFAULT '{"nodes": [], "edges": []}'::jsonb; -- CHECK constraint: nodes and edges must be arraysALTER TABLE questsADD CONSTRAINT canvas_metadata_structure_check CHECK ( canvas_metadata IS NOT NULL AND canvas_metadata ? 'nodes' AND canvas_metadata ? 'edges' AND jsonb_typeof(canvas_metadata->'nodes') = 'array' AND jsonb_typeof(canvas_metadata->'edges') = 'array' ); -- GIN index for JSONB queriesCREATE INDEX IF NOT EXISTS idx_quests_canvas_metadata ON quests USING GIN (canvas_metadata);
Note: The quest_mode field is NOT in this migration — it is validated by Zod at the application layer.
9. API ENDPOINTS
Method | Endpoint | Auth | Schema | Response |
|---|---|---|---|---|
PUT |
| Creator |
|
|
10. DATA REQUIREMENTS
Frontend Needs
CanvasMetadatatype for React Flow state management.CanvasNodeandCanvasEdgetypes for node/edge components.questModeSchemafor toggling canvas visibility.
API Calls Frontend Will Make
PUT /api/creator/update-quest-canvaswith{ quest_id, canvas_metadata }.
Caching Strategy
Canvas state is persisted on explicit save. In-memory during editing via React Flow's internal state.
11. PERFORMANCE CONSIDERATIONS
Database Optimization
GIN index on
canvas_metadatafor future JSONB path queries.CHECK constraint prevents invalid writes at DB level.
API Response Time
JSONB write is lightweight; typical payload is <100 nodes/edges.
No query-time overhead beyond standard Supabase row write.
Who can access this feature?
Quest creators with a quest in draft or in-progress status. RLS on quests table enforces creator_id ownership.
RLS:
creator_id = auth.uid()on thequeststable.API route validates via
authenticateRole('CREATOR')orauthenticateAnyRole(['CREATOR', 'ADMIN']).
Data Validation
Zod
canvasMetadataSchemavalidates on every API write.updateCanvasSchemaensuresquest_idis a valid UUID.PostgreSQL CHECK constraint as defense-in-depth.
13. ERROR HANDLING
Error | Response |
|---|---|
Invalid | 400 |
| 400 |
CHECK constraint violation | 500 (should never reach DB if Zod passes) |
Unauthorized (not quest owner) | 403 RLS rejection or |
14. TESTING CHECKLIST
Happy Path
□ Create nodes and edges via React Flow, save, reload — state persists.
□ Switch between Form and Canvas views — data is consistent in both directions.
□ Empty canvas renders without errors (default empty arrays).
□ QUEST_MODE linear hides canvas; exploration shows it.
Edge Cases
□ Save malformed JSON (missing nodes array) — Zod rejects before DB write.
□ Save duplicate node IDs — handled by React Flow (id uniqueness enforced).
□ Very large canvas (>1000 nodes) — test render performance.
□ Concurrency: two tabs editing same canvas — last write wins.
15. OPEN QUESTIONS
Should the CHECK constraint be extended to validate node shape (id, x, y, type fields)?
Should
quest_modebe added to the CHECK constraint or a separate DB column?
16. OUT OF SCOPE (v1.1+)
Real-time collaborative canvas editing (WebSocket / Supabase Realtime).
Canvas version history / undo beyond browser session.
Canvas node templates (pre-built branching patterns).
17. SUCCESS METRICS
Zero canvas data corruption events.
100% of canvas saves validated by Zod before DB write.
Canvas-to-form sync produces no data loss.
18. DEPENDENCIES
This feature depends on:
React Flow (
@xyflow/react) for canvas rendering.Zod for schema validation.
Supabase JSONB for persistence.
lib/canvas-sync/canvasToForm.ts(259 lines) for canvas-to-card extraction.lib/canvas-sync/formToCanvas.tsfor form-to-canvas conversion.lib/utils/curriculum-to-canvas.tsfor AI curriculum import.lib/ai/canvas-layout.service.ts(268 lines) for deterministic initial layout.
These features depend on this:
Visual Canvas Editor (React Flow integration).
AI Quest Generation (outputs to canvas).
SCORM/xAPI Export (reads canvas structure).
19. TIMELINE & OWNERSHIP
Implemented: W1.5 milestone.
Owner: scorevi
Document Version
1.0 - Initial version - 2026-06-29 08:27 UTC
1.1 - Added Document Version section and update author to have full name - 2026-06-29 08:52 UTC