700 lines
28 KiB
JSON
700 lines
28 KiB
JSON
{
|
|
"project": "WebVNWrite",
|
|
"branchName": "ralph/vn-flowchart-editor",
|
|
"description": "Visual Novel Flowchart Editor - A web-based tool for authoring visual novels with drag-and-drop nodes, branching connections, user authentication, and Ren'Py JSON export",
|
|
"userStories": [
|
|
{
|
|
"id": "US-001",
|
|
"title": "Project scaffolding and configuration",
|
|
"description": "As a developer, I need the project set up with Next.js, TailwindCSS, and Supabase so that I can build the application.",
|
|
"acceptanceCriteria": [
|
|
"Initialize Next.js project with TypeScript and App Router",
|
|
"Install and configure TailwindCSS",
|
|
"Install Supabase client library (@supabase/supabase-js)",
|
|
"Create .env.example with NEXT_PUBLIC_SUPABASE_URL and NEXT_PUBLIC_SUPABASE_ANON_KEY",
|
|
"Basic folder structure: app/, components/, lib/, types/",
|
|
"Typecheck passes"
|
|
],
|
|
"priority": 1,
|
|
"passes": true,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-002",
|
|
"title": "Define TypeScript types for flowchart data",
|
|
"description": "As a developer, I need TypeScript types for nodes, connections, and conditions.",
|
|
"acceptanceCriteria": [
|
|
"Create types/flowchart.ts file",
|
|
"DialogueNode type: id, type='dialogue', position: {x,y}, data: { speaker?: string, text: string }",
|
|
"ChoiceNode type: id, type='choice', position: {x,y}, data: { prompt: string, options: { id: string, label: string }[] }",
|
|
"VariableNode type: id, type='variable', position: {x,y}, data: { variableName: string, operation: 'set'|'add'|'subtract', value: number }",
|
|
"Condition type: { variableName: string, operator: '>'|'<'|'=='|'>='|'<='|'!=', value: number }",
|
|
"FlowchartEdge type: id, source, sourceHandle?, target, targetHandle?, data?: { condition?: Condition }",
|
|
"FlowchartData type: { nodes: (DialogueNode|ChoiceNode|VariableNode)[], edges: FlowchartEdge[] }",
|
|
"All types exported from types/flowchart.ts",
|
|
"Typecheck passes"
|
|
],
|
|
"priority": 2,
|
|
"passes": true,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-003",
|
|
"title": "Supabase schema for users and projects",
|
|
"description": "As a developer, I need database tables to store users and their projects.",
|
|
"acceptanceCriteria": [
|
|
"Create supabase/migrations/ directory",
|
|
"Create SQL migration file with profiles table: id (uuid, references auth.users), email (text), display_name (text), is_admin (boolean default false), created_at (timestamptz)",
|
|
"Create projects table: id (uuid), user_id (uuid, foreign key to profiles.id), name (text), flowchart_data (jsonb), created_at (timestamptz), updated_at (timestamptz)",
|
|
"Add RLS policy: users can SELECT/INSERT/UPDATE/DELETE their own projects (user_id = auth.uid())",
|
|
"Add RLS policy: users can SELECT their own profile",
|
|
"Add RLS policy: admin users (is_admin=true) can SELECT all profiles",
|
|
"Typecheck passes"
|
|
],
|
|
"priority": 3,
|
|
"passes": true,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-004",
|
|
"title": "Supabase client configuration",
|
|
"description": "As a developer, I need Supabase client utilities for auth and database access.",
|
|
"acceptanceCriteria": [
|
|
"Create lib/supabase/client.ts with browser client (createBrowserClient)",
|
|
"Create lib/supabase/server.ts with server client (createServerClient for App Router)",
|
|
"Create lib/supabase/middleware.ts with middleware client helper",
|
|
"Export typed database client using generated types or manual types",
|
|
"Typecheck passes"
|
|
],
|
|
"priority": 4,
|
|
"passes": true,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-005",
|
|
"title": "Protected routes middleware",
|
|
"description": "As a developer, I need authentication middleware so that only logged-in users can access the app.",
|
|
"acceptanceCriteria": [
|
|
"Create middleware.ts at project root",
|
|
"Middleware checks Supabase session on each request",
|
|
"Unauthenticated users accessing /dashboard or /editor/* are redirected to /login",
|
|
"Authenticated users accessing /login or /signup are redirected to /dashboard",
|
|
"Public routes allowed without auth: /login, /signup, /forgot-password, /reset-password",
|
|
"Typecheck passes"
|
|
],
|
|
"priority": 5,
|
|
"passes": true,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-006",
|
|
"title": "Login page",
|
|
"description": "As a user, I want to log in with my email and password so that I can access my projects.",
|
|
"acceptanceCriteria": [
|
|
"Create app/login/page.tsx",
|
|
"Form with email and password input fields",
|
|
"Submit button calls Supabase signInWithPassword",
|
|
"Show error message for invalid credentials",
|
|
"On success, redirect to /dashboard",
|
|
"Link to /forgot-password page",
|
|
"Styled with TailwindCSS",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 6,
|
|
"passes": true,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-007",
|
|
"title": "Sign up page (invite-only)",
|
|
"description": "As an invited user, I want to complete my account setup so that I can access the tool.",
|
|
"acceptanceCriteria": [
|
|
"Create app/signup/page.tsx",
|
|
"Form with email (pre-filled if from invite link), password, and confirm password fields",
|
|
"Validate passwords match before submission",
|
|
"Handle Supabase invite token from URL (type=invite or type=signup)",
|
|
"On success, create profile record in profiles table and redirect to /dashboard",
|
|
"Show error message if signup fails",
|
|
"Styled with TailwindCSS",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 7,
|
|
"passes": true,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-008",
|
|
"title": "Logout functionality",
|
|
"description": "As a user, I want to log out so that I can secure my session.",
|
|
"acceptanceCriteria": [
|
|
"Create components/LogoutButton.tsx component",
|
|
"Button calls Supabase signOut",
|
|
"On success, redirect to /login",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 8,
|
|
"passes": true,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-009",
|
|
"title": "Password reset - forgot password page",
|
|
"description": "As a user, I want to request a password reset if I forget my password.",
|
|
"acceptanceCriteria": [
|
|
"Create app/forgot-password/page.tsx",
|
|
"Form with email input field",
|
|
"Submit button calls Supabase resetPasswordForEmail",
|
|
"Show confirmation message after sending (check your email)",
|
|
"Link back to /login",
|
|
"Styled with TailwindCSS",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 9,
|
|
"passes": true,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-010",
|
|
"title": "Password reset - set new password page",
|
|
"description": "As a user, I want to set a new password after clicking the reset link.",
|
|
"acceptanceCriteria": [
|
|
"Create app/reset-password/page.tsx",
|
|
"Form with new password and confirm password fields",
|
|
"Handle Supabase recovery token from URL",
|
|
"Submit calls Supabase updateUser with new password",
|
|
"On success, redirect to /login with success message",
|
|
"Show error if token invalid or expired",
|
|
"Styled with TailwindCSS",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 10,
|
|
"passes": true,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-011",
|
|
"title": "Dashboard layout with navbar",
|
|
"description": "As a user, I want a consistent layout with navigation so that I can move around the app.",
|
|
"acceptanceCriteria": [
|
|
"Create app/dashboard/layout.tsx",
|
|
"Navbar component with app title/logo",
|
|
"Navbar shows current user email",
|
|
"Navbar includes LogoutButton",
|
|
"Main content area below navbar",
|
|
"Styled with TailwindCSS",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 11,
|
|
"passes": true,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-012",
|
|
"title": "Dashboard - list projects",
|
|
"description": "As a user, I want to see all my projects so that I can choose which one to edit.",
|
|
"acceptanceCriteria": [
|
|
"Create app/dashboard/page.tsx",
|
|
"Fetch projects from Supabase for current user",
|
|
"Display projects as cards in a grid",
|
|
"Each card shows: project name, last updated date (formatted)",
|
|
"Click card navigates to /editor/[projectId]",
|
|
"Empty state with message when no projects exist",
|
|
"Loading state while fetching",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 12,
|
|
"passes": true,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-013",
|
|
"title": "Create new project",
|
|
"description": "As a user, I want to create a new project so that I can start a new flowchart.",
|
|
"acceptanceCriteria": [
|
|
"Add 'New Project' button on dashboard",
|
|
"Clicking opens modal with project name input",
|
|
"Submit creates project in Supabase with empty flowchart_data: { nodes: [], edges: [] }",
|
|
"On success, redirect to /editor/[newProjectId]",
|
|
"Show error if creation fails",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 13,
|
|
"passes": true,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-014",
|
|
"title": "Delete project",
|
|
"description": "As a user, I want to delete a project I no longer need.",
|
|
"acceptanceCriteria": [
|
|
"Add delete icon/button on each project card",
|
|
"Clicking shows confirmation dialog (Are you sure?)",
|
|
"Confirm deletes project from Supabase",
|
|
"Project removed from dashboard list without page reload",
|
|
"Show success toast after deletion",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 14,
|
|
"passes": true,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-015",
|
|
"title": "Rename project",
|
|
"description": "As a user, I want to rename a project to keep my work organized.",
|
|
"acceptanceCriteria": [
|
|
"Add edit/rename icon on project card",
|
|
"Clicking opens modal or enables inline edit for project name",
|
|
"Submit updates project name in Supabase",
|
|
"UI updates immediately without page reload",
|
|
"Show error if rename fails",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 15,
|
|
"passes": true,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-016",
|
|
"title": "Admin - invite new user",
|
|
"description": "As an admin, I want to invite new users so that collaborators can access the tool.",
|
|
"acceptanceCriteria": [
|
|
"Create app/admin/invite/page.tsx",
|
|
"Only accessible by users with is_admin=true (redirect others to /dashboard)",
|
|
"Form with email address input",
|
|
"Submit calls Supabase admin inviteUserByEmail (requires service role key in server action)",
|
|
"Show success message with invite sent confirmation",
|
|
"Show error if invite fails",
|
|
"Link to this page visible in navbar only for admins",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 16,
|
|
"passes": true,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-017",
|
|
"title": "Editor page with React Flow canvas",
|
|
"description": "As a user, I want an editor page with a canvas where I can build my flowchart.",
|
|
"acceptanceCriteria": [
|
|
"Install reactflow package",
|
|
"Create app/editor/[projectId]/page.tsx",
|
|
"Fetch project from Supabase by ID",
|
|
"Show error if project not found or user unauthorized",
|
|
"Show loading state while fetching",
|
|
"Render React Flow canvas filling the editor area",
|
|
"Canvas has grid background (React Flow Background component)",
|
|
"Header shows project name with back link to /dashboard",
|
|
"Initialize React Flow with nodes and edges from flowchart_data",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 17,
|
|
"passes": true,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-018",
|
|
"title": "Canvas pan and zoom controls",
|
|
"description": "As a user, I want to pan and zoom the canvas to navigate large flowcharts.",
|
|
"acceptanceCriteria": [
|
|
"Canvas supports click-and-drag panning (React Flow default)",
|
|
"Mouse wheel zooms in/out (React Flow default)",
|
|
"Add React Flow Controls component with zoom +/- buttons",
|
|
"Add fitView button to show all nodes",
|
|
"Controls positioned in bottom-right corner",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 18,
|
|
"passes": true,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-019",
|
|
"title": "Editor toolbar",
|
|
"description": "As a user, I want a toolbar with actions for adding nodes and saving/exporting.",
|
|
"acceptanceCriteria": [
|
|
"Create components/editor/Toolbar.tsx",
|
|
"Toolbar positioned at top of editor below header",
|
|
"Buttons: Add Dialogue, Add Choice, Add Variable (no functionality yet)",
|
|
"Buttons: Save, Export, Import (no functionality yet)",
|
|
"Buttons styled with TailwindCSS, icons optional",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 19,
|
|
"passes": false,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-020",
|
|
"title": "Create custom dialogue node component",
|
|
"description": "As a user, I want dialogue nodes to display and edit character speech.",
|
|
"acceptanceCriteria": [
|
|
"Create components/editor/nodes/DialogueNode.tsx",
|
|
"Node styled with blue background/border",
|
|
"Displays editable input for speaker name (placeholder: 'Speaker')",
|
|
"Displays editable textarea for dialogue text (placeholder: 'Dialogue text...')",
|
|
"Has one Handle at top (type='target', id='input')",
|
|
"Has one Handle at bottom (type='source', id='output')",
|
|
"Register as custom node type in React Flow",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 20,
|
|
"passes": false,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-021",
|
|
"title": "Add dialogue node from toolbar",
|
|
"description": "As a user, I want to add dialogue nodes by clicking the toolbar button.",
|
|
"acceptanceCriteria": [
|
|
"Clicking 'Add Dialogue' in toolbar creates new DialogueNode",
|
|
"Node appears at center of current viewport",
|
|
"Node has unique ID (use nanoid or uuid)",
|
|
"Node added to React Flow nodes state",
|
|
"Node can be dragged to reposition",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 21,
|
|
"passes": false,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-022",
|
|
"title": "Create custom choice node component",
|
|
"description": "As a user, I want choice nodes to display branching decisions.",
|
|
"acceptanceCriteria": [
|
|
"Create components/editor/nodes/ChoiceNode.tsx",
|
|
"Node styled with green background/border",
|
|
"Displays editable input for prompt text (placeholder: 'What do you choose?')",
|
|
"Displays 2 default options, each with editable label input",
|
|
"Has one Handle at top (type='target', id='input')",
|
|
"Each option has its own Handle at bottom (type='source', id='option-0', 'option-1', etc.)",
|
|
"Register as custom node type in React Flow",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 22,
|
|
"passes": false,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-023",
|
|
"title": "Add choice node from toolbar",
|
|
"description": "As a user, I want to add choice nodes by clicking the toolbar button.",
|
|
"acceptanceCriteria": [
|
|
"Clicking 'Add Choice' in toolbar creates new ChoiceNode",
|
|
"Node appears at center of current viewport",
|
|
"Node has unique ID",
|
|
"Node initialized with 2 options (each with unique id and empty label)",
|
|
"Node added to React Flow nodes state",
|
|
"Node can be dragged to reposition",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 23,
|
|
"passes": false,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-024",
|
|
"title": "Add/remove choice options",
|
|
"description": "As a user, I want to add or remove choice options (2-6 options supported).",
|
|
"acceptanceCriteria": [
|
|
"ChoiceNode has '+' button to add new option",
|
|
"Maximum 6 options (button disabled or hidden at max)",
|
|
"Each option has 'x' button to remove it",
|
|
"Minimum 2 options (remove button disabled or hidden at min)",
|
|
"Adding option creates new output Handle dynamically",
|
|
"Removing option removes its Handle",
|
|
"Node data updates in React Flow state",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 24,
|
|
"passes": false,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-025",
|
|
"title": "Create custom variable node component",
|
|
"description": "As a user, I want variable nodes to set or modify story variables.",
|
|
"acceptanceCriteria": [
|
|
"Create components/editor/nodes/VariableNode.tsx",
|
|
"Node styled with orange background/border",
|
|
"Displays editable input for variable name (placeholder: 'variableName')",
|
|
"Displays dropdown/select for operation: set, add, subtract",
|
|
"Displays editable number input for value (default: 0)",
|
|
"Has one Handle at top (type='target', id='input')",
|
|
"Has one Handle at bottom (type='source', id='output')",
|
|
"Register as custom node type in React Flow",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 25,
|
|
"passes": false,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-026",
|
|
"title": "Add variable node from toolbar",
|
|
"description": "As a user, I want to add variable nodes by clicking the toolbar button.",
|
|
"acceptanceCriteria": [
|
|
"Clicking 'Add Variable' in toolbar creates new VariableNode",
|
|
"Node appears at center of current viewport",
|
|
"Node has unique ID",
|
|
"Node initialized with empty variableName, operation='set', value=0",
|
|
"Node added to React Flow nodes state",
|
|
"Node can be dragged to reposition",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 26,
|
|
"passes": false,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-027",
|
|
"title": "Connect nodes with edges",
|
|
"description": "As a user, I want to connect nodes with arrows to define story flow.",
|
|
"acceptanceCriteria": [
|
|
"Dragging from source Handle to target Handle creates edge (React Flow default)",
|
|
"Edges render as smooth bezier curves (default edge type or smoothstep)",
|
|
"Edges show arrow marker indicating direction (markerEnd)",
|
|
"Edges update position when nodes are moved",
|
|
"Cannot connect source-to-source or target-to-target (React Flow handles this)",
|
|
"New edges added to React Flow edges state",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 27,
|
|
"passes": false,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-028",
|
|
"title": "Select and delete nodes",
|
|
"description": "As a user, I want to delete nodes to revise my flowchart.",
|
|
"acceptanceCriteria": [
|
|
"Clicking a node selects it (visual highlight via React Flow)",
|
|
"Pressing Delete or Backspace key removes selected node(s)",
|
|
"Deleting node also removes all connected edges",
|
|
"Use onNodesDelete callback to handle deletion",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 28,
|
|
"passes": false,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-029",
|
|
"title": "Select and delete edges",
|
|
"description": "As a user, I want to delete connections between nodes.",
|
|
"acceptanceCriteria": [
|
|
"Clicking an edge selects it (visual highlight via React Flow)",
|
|
"Pressing Delete or Backspace key removes selected edge(s)",
|
|
"Use onEdgesDelete callback to handle deletion",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 29,
|
|
"passes": false,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-030",
|
|
"title": "Right-click context menu",
|
|
"description": "As a user, I want a context menu for quick actions.",
|
|
"acceptanceCriteria": [
|
|
"Create components/editor/ContextMenu.tsx",
|
|
"Right-click on canvas shows menu: Add Dialogue, Add Choice, Add Variable",
|
|
"New node created at click position",
|
|
"Right-click on node shows menu: Delete",
|
|
"Right-click on edge shows menu: Delete, Add Condition",
|
|
"Clicking elsewhere or pressing Escape closes menu",
|
|
"Menu styled with TailwindCSS",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 30,
|
|
"passes": false,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-031",
|
|
"title": "Condition editor modal",
|
|
"description": "As a user, I want to add conditions to edges so branches depend on variables.",
|
|
"acceptanceCriteria": [
|
|
"Create components/editor/ConditionEditor.tsx modal/popover",
|
|
"Opens on double-click edge or via context menu 'Add Condition'",
|
|
"Form fields: variable name input, operator dropdown (>, <, ==, >=, <=, !=), value number input",
|
|
"Pre-fill fields if edge already has condition",
|
|
"Save button applies condition to edge data",
|
|
"Clear/Remove button removes condition from edge",
|
|
"Cancel button closes without saving",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 31,
|
|
"passes": false,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-032",
|
|
"title": "Display conditions on edges",
|
|
"description": "As a user, I want to see conditions displayed on edges.",
|
|
"acceptanceCriteria": [
|
|
"Create custom edge component or use edge labels",
|
|
"Edges with conditions render as dashed lines (strokeDasharray)",
|
|
"Condition label displayed on edge (e.g., 'score > 5')",
|
|
"Unconditional edges remain solid lines",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 32,
|
|
"passes": false,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-033",
|
|
"title": "Auto-save to LocalStorage",
|
|
"description": "As a user, I want my work auto-saved locally so I don't lose progress if the browser crashes.",
|
|
"acceptanceCriteria": [
|
|
"Save flowchart state (nodes + edges) to LocalStorage on every change",
|
|
"Debounce saves (e.g., 1 second delay after last change)",
|
|
"LocalStorage key format: 'vnwrite-draft-{projectId}'",
|
|
"On editor load, check LocalStorage for saved draft",
|
|
"If local draft exists and differs from database, show prompt to restore or discard",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 33,
|
|
"passes": false,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-034",
|
|
"title": "Save project to database",
|
|
"description": "As a user, I want to save my project to the database manually.",
|
|
"acceptanceCriteria": [
|
|
"Clicking 'Save' in toolbar saves current nodes/edges to Supabase",
|
|
"Update project's flowchart_data and updated_at fields",
|
|
"Show saving indicator/spinner while in progress",
|
|
"Show success toast on completion",
|
|
"Clear LocalStorage draft after successful save",
|
|
"Show error toast if save fails",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 34,
|
|
"passes": false,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-035",
|
|
"title": "Export project as .vnflow file",
|
|
"description": "As a user, I want to export my project as a JSON file for backup or sharing.",
|
|
"acceptanceCriteria": [
|
|
"Clicking 'Export' in toolbar triggers file download",
|
|
"File named '[project-name].vnflow'",
|
|
"File contains JSON with nodes and edges arrays",
|
|
"JSON is pretty-printed (2-space indent) for readability",
|
|
"Uses browser download API (create blob, trigger download)",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 35,
|
|
"passes": false,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-036",
|
|
"title": "Import project from .vnflow file",
|
|
"description": "As a user, I want to import a .vnflow file to restore or share projects.",
|
|
"acceptanceCriteria": [
|
|
"Clicking 'Import' in toolbar opens file picker",
|
|
"Accept .vnflow and .json file extensions",
|
|
"If current project has unsaved changes, show confirmation dialog",
|
|
"Validate imported file has nodes and edges arrays",
|
|
"Show error toast if file is invalid",
|
|
"Load valid data into React Flow state (replaces current flowchart)",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 36,
|
|
"passes": false,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-037",
|
|
"title": "Export to Ren'Py JSON format",
|
|
"description": "As a user, I want to export my flowchart to Ren'Py-compatible JSON for use in my game.",
|
|
"acceptanceCriteria": [
|
|
"Add 'Export to Ren'Py' option (button or dropdown item)",
|
|
"File named '[project-name]-renpy.json'",
|
|
"Dialogue nodes export as: { type: 'dialogue', speaker: '...', text: '...' }",
|
|
"Choice nodes export as: { type: 'menu', prompt: '...', choices: [{ label: '...', next: '...' }] }",
|
|
"Variable nodes export as: { type: 'variable', name: '...', operation: '...', value: ... }",
|
|
"Edges with conditions include condition object on the choice/jump",
|
|
"Organize nodes into labeled sections based on flow (traverse from first node)",
|
|
"Include metadata: projectName, exportedAt timestamp",
|
|
"Output JSON is valid (test with JSON.parse)",
|
|
"Typecheck passes"
|
|
],
|
|
"priority": 37,
|
|
"passes": false,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-038",
|
|
"title": "Unsaved changes warning",
|
|
"description": "As a user, I want a warning before losing unsaved work.",
|
|
"acceptanceCriteria": [
|
|
"Track dirty state: true when flowchart modified after last save",
|
|
"Set dirty=true on node/edge add, delete, or modify",
|
|
"Set dirty=false after successful save",
|
|
"Browser beforeunload event shows warning if dirty",
|
|
"Navigating to dashboard shows confirmation modal if dirty",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 38,
|
|
"passes": false,
|
|
"notes": ""
|
|
},
|
|
{
|
|
"id": "US-039",
|
|
"title": "Loading and error states",
|
|
"description": "As a user, I want clear feedback when things are loading or when errors occur.",
|
|
"acceptanceCriteria": [
|
|
"Loading spinner component for async operations",
|
|
"Editor shows loading spinner while fetching project",
|
|
"Error message displayed if project fails to load (with back to dashboard link)",
|
|
"Toast notification system for success/error messages",
|
|
"Save error shows toast with retry option",
|
|
"Typecheck passes",
|
|
"Verify in browser using dev-browser skill"
|
|
],
|
|
"priority": 39,
|
|
"passes": false,
|
|
"notes": ""
|
|
}
|
|
]
|
|
}
|