# Design Document v001 # Voice Recording App with AI-Powered Summarization and Automatic App Generation # Created: 2024-12-19T06:00:00Z workflow_version: "v001" feature: "Voice recording app with AI-powered summarization and automatic app generation" created_at: "2024-12-19T06:00:00Z" updated_at: "2024-12-19T06:00:00Z" approved_at: null status: draft revision: 1 revision_notes: "Initial design document" # ============================================================================ # EXTERNAL DEPENDENCIES (Pre-existing entities) # ============================================================================ external_dependencies: models: [] api_endpoints: [] components: [] # ============================================================================ # LAYER 1: DATA MODELS # ============================================================================ data_models: # USER MODEL - id: model_user name: User description: "Application user account with email/password authentication" table_name: users fields: - name: id type: uuid constraints: [primary_key] description: "Unique user identifier" - name: email type: string constraints: [unique, not_null, indexed] description: "User email address for login" - name: name type: string constraints: [not_null] description: "User's display name" - name: password_hash type: string constraints: [not_null] description: "Bcrypt hashed password" relations: [] indexes: - fields: [email] unique: true name: idx_users_email timestamps: true soft_delete: false validations: - field: email rule: email message: "Invalid email format" - field: name rule: "min:1" message: "Name is required" - field: password_hash rule: "min:60" message: "Invalid password hash" # RECORDING MODEL - id: model_recording name: Recording description: "Voice recording with transcript and summary" table_name: recordings fields: - name: id type: uuid constraints: [primary_key] description: "Unique recording identifier" - name: user_id type: uuid constraints: [foreign_key, not_null, indexed] description: "Owner of this recording" - name: title type: string constraints: [not_null] description: "Recording title (auto-generated or user-edited)" - name: audio_file_path type: string constraints: [not_null] description: "Path to audio file in MinIO/S3" - name: duration type: integer constraints: [not_null] description: "Recording duration in seconds" - name: transcript type: text constraints: [] description: "Full transcript from Whisper STT" - name: summary type: text constraints: [] description: "AI-generated summary from Gemini" - name: is_transcribing type: boolean constraints: [not_null, default] default: false description: "Whether currently transcribing" relations: - type: belongs_to target: model_user foreign_key: user_id on_delete: cascade indexes: - fields: [user_id, created_at] unique: false name: idx_recordings_user_created timestamps: true soft_delete: false validations: - field: duration rule: "min:1" message: "Duration must be at least 1 second" # GENERATED APP MODEL - id: model_generated_app name: GeneratedApp description: "AI-generated application from recording content" table_name: generated_apps fields: - name: id type: uuid constraints: [primary_key] description: "Unique app identifier" - name: user_id type: uuid constraints: [foreign_key, not_null, indexed] description: "Owner of this app" - name: recording_id type: uuid constraints: [foreign_key, not_null, indexed] description: "Source recording that triggered generation" - name: title type: string constraints: [not_null] description: "App title from AI analysis" - name: description type: text constraints: [] description: "App description" - name: html_content type: text constraints: [not_null] description: "Complete HTML/CSS/JS for iframe rendering" - name: prd_content type: text constraints: [] description: "Product Requirements Document (PRD) generated by AI" - name: ui_ux_design type: text constraints: [] description: "UI/UX design notes from AI" - name: app_type type: string constraints: [] description: "Type of app determined by AI (e.g., todo, calculator, form)" - name: status type: enum enum_values: [generating, completed, failed] constraints: [not_null, default] default: generating description: "Generation status" relations: - type: belongs_to target: model_user foreign_key: user_id on_delete: cascade - type: belongs_to target: model_recording foreign_key: recording_id on_delete: cascade indexes: - fields: [user_id, created_at] unique: false name: idx_apps_user_created - fields: [recording_id] unique: false name: idx_apps_recording timestamps: true soft_delete: false validations: [] # ============================================================================ # LAYER 2: API ENDPOINTS # ============================================================================ api_endpoints: # ======================================== # AUTHENTICATION ENDPOINTS # ======================================== - id: api_register_user method: POST path: /api/auth/register summary: "Register a new user" description: "Create a new user account with email and password" tags: [auth] path_params: [] query_params: [] request_body: content_type: application/json schema: type: object properties: - name: email type: string required: true validations: [email] description: "User email address" - name: name type: string required: true validations: ["min:1", "max:100"] description: "User display name" - name: password type: string required: true validations: ["min:8"] description: "Password (min 8 characters)" example: email: "user@example.com" name: "John Doe" password: "securepass123" responses: - status: 201 description: "User created successfully" schema: type: object properties: - name: id type: uuid - name: email type: string - name: name type: string - name: created_at type: datetime example: id: "550e8400-e29b-41d4-a716-446655440000" email: "user@example.com" name: "John Doe" created_at: "2024-12-19T06:00:00Z" - status: 400 description: "Validation error" schema: type: object properties: - name: error type: string example: error: "Invalid email or password too short" - status: 409 description: "Email already exists" schema: type: object properties: - name: error type: string example: error: "Email already registered" depends_on_models: [model_user] depends_on_apis: [] auth: required: false roles: [] rate_limit: requests: 10 window: "1h" - id: api_login_user method: POST path: /api/auth/login summary: "Login user" description: "Authenticate user with email and password, return session token" tags: [auth] path_params: [] query_params: [] request_body: content_type: application/json schema: type: object properties: - name: email type: string required: true validations: [email] description: "User email" - name: password type: string required: true description: "User password" example: email: "user@example.com" password: "securepass123" responses: - status: 200 description: "Login successful" schema: type: object properties: - name: user type: object - name: token type: string example: user: id: "550e8400-e29b-41d4-a716-446655440000" email: "user@example.com" name: "John Doe" token: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." - status: 401 description: "Invalid credentials" schema: type: object properties: - name: error type: string example: error: "Invalid email or password" depends_on_models: [model_user] depends_on_apis: [] auth: required: false roles: [] rate_limit: requests: 20 window: "1h" - id: api_logout_user method: POST path: /api/auth/logout summary: "Logout user" description: "Invalidate current session token" tags: [auth] path_params: [] query_params: [] request_body: content_type: application/json schema: type: object properties: [] responses: - status: 200 description: "Logout successful" schema: type: object properties: - name: success type: boolean example: success: true depends_on_models: [] depends_on_apis: [] auth: required: true roles: [] - id: api_get_current_user method: GET path: /api/auth/me summary: "Get current user" description: "Get currently authenticated user information" tags: [auth] path_params: [] query_params: [] request_body: content_type: application/json schema: type: object properties: [] responses: - status: 200 description: "User data" schema: type: object properties: - name: id type: uuid - name: email type: string - name: name type: string - name: created_at type: datetime example: id: "550e8400-e29b-41d4-a716-446655440000" email: "user@example.com" name: "John Doe" created_at: "2024-12-19T06:00:00Z" - status: 401 description: "Not authenticated" schema: type: object properties: - name: error type: string example: error: "Not authenticated" depends_on_models: [model_user] depends_on_apis: [] auth: required: true roles: [] # ======================================== # RECORDING ENDPOINTS # ======================================== - id: api_list_recordings method: GET path: /api/recordings summary: "List user recordings" description: "Get all recordings for authenticated user, sorted by creation date" tags: [recordings] path_params: [] query_params: - name: limit type: integer required: false default: 50 description: "Maximum number of recordings to return" - name: offset type: integer required: false default: 0 description: "Number of recordings to skip" request_body: content_type: application/json schema: type: object properties: [] responses: - status: 200 description: "Recordings list" schema: type: object properties: - name: recordings type: array - name: total type: integer example: recordings: - id: "rec-123" title: "Meeting Notes" duration: 180 created_at: "2024-12-19T06:00:00Z" total: 42 depends_on_models: [model_recording] depends_on_apis: [] auth: required: true roles: [] - id: api_create_recording method: POST path: /api/recordings summary: "Create new recording" description: "Upload audio file and create recording metadata" tags: [recordings] path_params: [] query_params: [] request_body: content_type: multipart/form-data schema: type: object properties: - name: audio type: file required: true description: "Audio file (webm, mp3, wav)" - name: title type: string required: false description: "Recording title (auto-generated if not provided)" - name: duration type: integer required: true description: "Duration in seconds" responses: - status: 201 description: "Recording created" schema: type: object properties: - name: id type: uuid - name: title type: string - name: audio_file_path type: string - name: duration type: integer - name: created_at type: datetime example: id: "rec-123" title: "Recording 2024-12-19" audio_file_path: "recordings/user-123/rec-123.webm" duration: 180 created_at: "2024-12-19T06:00:00Z" - status: 400 description: "Invalid audio file" schema: type: object properties: - name: error type: string example: error: "Invalid audio format" depends_on_models: [model_recording] depends_on_apis: [] auth: required: true roles: [] - id: api_get_recording method: GET path: /api/recordings/[id] summary: "Get single recording" description: "Get recording details including transcript and summary" tags: [recordings] path_params: - name: id type: uuid description: "Recording ID" query_params: [] request_body: content_type: application/json schema: type: object properties: [] responses: - status: 200 description: "Recording details" schema: type: object properties: - name: id type: uuid - name: title type: string - name: audio_file_path type: string - name: duration type: integer - name: transcript type: string - name: summary type: string - name: is_transcribing type: boolean - name: created_at type: datetime - status: 404 description: "Recording not found" schema: type: object properties: - name: error type: string example: error: "Recording not found" depends_on_models: [model_recording] depends_on_apis: [] auth: required: true roles: [] - id: api_delete_recording method: DELETE path: /api/recordings/[id] summary: "Delete recording" description: "Delete recording and associated audio file" tags: [recordings] path_params: - name: id type: uuid description: "Recording ID" query_params: [] request_body: content_type: application/json schema: type: object properties: [] responses: - status: 200 description: "Recording deleted" schema: type: object properties: - name: success type: boolean example: success: true - status: 404 description: "Recording not found" schema: type: object properties: - name: error type: string example: error: "Recording not found" depends_on_models: [model_recording] depends_on_apis: [] auth: required: true roles: [] - id: api_transcribe_recording method: POST path: /api/recordings/[id]/transcribe summary: "Transcribe recording" description: "Run Whisper STT on audio file to generate transcript" tags: [recordings, ai] path_params: - name: id type: uuid description: "Recording ID" query_params: [] request_body: content_type: application/json schema: type: object properties: [] responses: - status: 200 description: "Transcription started" schema: type: object properties: - name: recording_id type: uuid - name: is_transcribing type: boolean example: recording_id: "rec-123" is_transcribing: true - status: 404 description: "Recording not found" schema: type: object properties: - name: error type: string example: error: "Recording not found" depends_on_models: [model_recording] depends_on_apis: [] auth: required: true roles: [] - id: api_summarize_recording method: POST path: /api/recordings/[id]/summarize summary: "Summarize recording" description: "Use Gemini to generate summary from transcript" tags: [recordings, ai] path_params: - name: id type: uuid description: "Recording ID" query_params: [] request_body: content_type: application/json schema: type: object properties: [] responses: - status: 200 description: "Summary generated" schema: type: object properties: - name: recording_id type: uuid - name: summary type: string example: recording_id: "rec-123" summary: "Meeting discussion about Q1 goals..." - status: 400 description: "No transcript available" schema: type: object properties: - name: error type: string example: error: "Transcript not available" - status: 404 description: "Recording not found" schema: type: object properties: - name: error type: string example: error: "Recording not found" depends_on_models: [model_recording] depends_on_apis: [api_transcribe_recording] auth: required: true roles: [] # ======================================== # GENERATED APP ENDPOINTS # ======================================== - id: api_list_apps method: GET path: /api/apps summary: "List generated apps" description: "Get all apps generated for authenticated user" tags: [apps] path_params: [] query_params: - name: limit type: integer required: false default: 50 description: "Maximum number of apps to return" - name: offset type: integer required: false default: 0 description: "Number of apps to skip" request_body: content_type: application/json schema: type: object properties: [] responses: - status: 200 description: "Apps list" schema: type: object properties: - name: apps type: array - name: total type: integer example: apps: - id: "app-123" title: "Todo App" app_type: "todo" status: "completed" created_at: "2024-12-19T06:00:00Z" total: 12 depends_on_models: [model_generated_app] depends_on_apis: [] auth: required: true roles: [] - id: api_generate_app method: POST path: /api/apps/generate summary: "Generate app from recording" description: "Trigger AI app generation based on recording summary (wake word detection)" tags: [apps, ai] path_params: [] query_params: [] request_body: content_type: application/json schema: type: object properties: - name: recording_id type: uuid required: true description: "Source recording ID" example: recording_id: "rec-123" responses: - status: 201 description: "App generation started" schema: type: object properties: - name: id type: uuid - name: recording_id type: uuid - name: status type: string example: id: "app-123" recording_id: "rec-123" status: "generating" - status: 400 description: "Recording has no summary" schema: type: object properties: - name: error type: string example: error: "Recording summary not available" - status: 404 description: "Recording not found" schema: type: object properties: - name: error type: string example: error: "Recording not found" depends_on_models: [model_generated_app, model_recording] depends_on_apis: [api_summarize_recording] auth: required: true roles: [] - id: api_get_app method: GET path: /api/apps/[id] summary: "Get single generated app" description: "Get app details including HTML content for iframe rendering" tags: [apps] path_params: - name: id type: uuid description: "App ID" query_params: [] request_body: content_type: application/json schema: type: object properties: [] responses: - status: 200 description: "App details" schema: type: object properties: - name: id type: uuid - name: recording_id type: uuid - name: title type: string - name: description type: string - name: html_content type: string - name: app_type type: string - name: status type: string - name: created_at type: datetime - status: 404 description: "App not found" schema: type: object properties: - name: error type: string example: error: "App not found" depends_on_models: [model_generated_app] depends_on_apis: [] auth: required: true roles: [] - id: api_delete_app method: DELETE path: /api/apps/[id] summary: "Delete generated app" description: "Delete generated app (recording remains)" tags: [apps] path_params: - name: id type: uuid description: "App ID" query_params: [] request_body: content_type: application/json schema: type: object properties: [] responses: - status: 200 description: "App deleted" schema: type: object properties: - name: success type: boolean example: success: true - status: 404 description: "App not found" schema: type: object properties: - name: error type: string example: error: "App not found" depends_on_models: [model_generated_app] depends_on_apis: [] auth: required: true roles: [] # ============================================================================ # LAYER 3: PAGES # ============================================================================ pages: - id: page_home name: "Home" path: / layout: layout_public data_needs: [] components: [component_header, component_hero, component_features] seo: title: "NoteToApp - Voice Recording with AI Summarization" description: "Record voice notes, get AI summaries, and generate apps automatically" auth: required: false roles: [] redirect: "" state: local: [] global: [] - id: page_login name: "Login" path: /login layout: layout_auth data_needs: [] components: [component_login_form] seo: title: "Login - NoteToApp" description: "Login to your account" auth: required: false roles: [] redirect: "" state: local: [error, isLoading] global: [] - id: page_register name: "Register" path: /register layout: layout_auth data_needs: [] components: [component_register_form] seo: title: "Register - NoteToApp" description: "Create a new account" auth: required: false roles: [] redirect: "" state: local: [error, isLoading] global: [] - id: page_dashboard name: "Dashboard" path: /dashboard layout: layout_app data_needs: - api_id: api_get_current_user purpose: "Display user info" on_load: true - api_id: api_list_recordings purpose: "Show recent recordings" on_load: true components: [component_header, component_sidebar, component_record_button, component_wake_word_indicator, component_recording_list] seo: title: "Dashboard - NoteToApp" description: "Your voice recordings and generated apps" auth: required: true roles: [] redirect: /login state: local: [isRecording, isListening, currentRecording] global: [user] - id: page_recordings name: "Recordings" path: /recordings layout: layout_app data_needs: - api_id: api_list_recordings purpose: "Display all recordings" on_load: true components: [component_header, component_sidebar, component_recording_list, component_recording_card] seo: title: "Recordings - NoteToApp" description: "All your voice recordings" auth: required: true roles: [] redirect: /login state: local: [searchQuery, sortBy] global: [user] - id: page_recording_detail name: "Recording Detail" path: /recordings/[id] layout: layout_app data_needs: - api_id: api_get_recording purpose: "Display recording details" on_load: true components: [component_header, component_sidebar, component_audio_player, component_transcript_viewer, component_summary_display] seo: title: "Recording Detail - NoteToApp" description: "View recording transcript and summary" auth: required: true roles: [] redirect: /login state: local: [isPlaying, currentTime, isTranscribing] global: [user] - id: page_apps name: "Generated Apps" path: /apps layout: layout_app data_needs: - api_id: api_list_apps purpose: "Display generated apps gallery" on_load: true components: [component_header, component_sidebar, component_app_gallery, component_app_card] seo: title: "Generated Apps - NoteToApp" description: "Your AI-generated applications" auth: required: true roles: [] redirect: /login state: local: [filterType] global: [user] - id: page_app_detail name: "App Preview" path: /apps/[id] layout: layout_app data_needs: - api_id: api_get_app purpose: "Display app in iframe" on_load: true components: [component_header, component_sidebar, component_app_iframe_viewer] seo: title: "App Preview - NoteToApp" description: "View generated application" auth: required: true roles: [] redirect: /login state: local: [isLoading] global: [user] # ============================================================================ # LAYER 3: COMPONENTS # ============================================================================ components: # ======================================== # LAYOUT COMPONENTS # ======================================== - id: component_header name: Header props: - name: user type: User | null required: false default: null description: "Current user for displaying name/avatar" events: [] uses_apis: [] uses_components: [] internal_state: [] variants: [default] - id: component_sidebar name: Sidebar props: - name: activePath type: string required: true description: "Current route path for highlighting" events: - name: onNavigate payload: "string" description: "Fired when navigation item clicked" uses_apis: [] uses_components: [] internal_state: [isCollapsed] variants: [default] - id: component_hero name: Hero props: [] events: - name: onGetStarted payload: "void" description: "Fired when CTA button clicked" uses_apis: [] uses_components: [] internal_state: [] variants: [default] - id: component_features name: Features props: [] events: [] uses_apis: [] uses_components: [] internal_state: [] variants: [default] # ======================================== # AUTHENTICATION COMPONENTS # ======================================== - id: component_login_form name: LoginForm props: [] events: - name: onSuccess payload: "User" description: "Fired when login successful" - name: onError payload: "string" description: "Fired when login fails" uses_apis: [api_login_user] uses_components: [] internal_state: [email, password, isLoading, error] variants: [default] - id: component_register_form name: RegisterForm props: [] events: - name: onSuccess payload: "User" description: "Fired when registration successful" - name: onError payload: "string" description: "Fired when registration fails" uses_apis: [api_register_user] uses_components: [] internal_state: [email, name, password, confirmPassword, isLoading, error] variants: [default] # ======================================== # RECORDING COMPONENTS # ======================================== - id: component_record_button name: RecordButton props: - name: isRecording type: boolean required: true description: "Whether currently recording" - name: isTranscribing type: boolean required: false default: false description: "Whether transcribing in real-time" events: - name: onStartRecording payload: "void" description: "Fired when recording starts" - name: onStopRecording payload: "Blob" description: "Fired when recording stops, includes audio blob" uses_apis: [] uses_components: [] internal_state: [mediaRecorder, audioChunks] variants: [default, large] - id: component_wake_word_indicator name: WakeWordIndicator props: - name: isListening type: boolean required: true description: "Whether wake word detection is active" - name: wakeWord type: string required: true description: "The wake word phrase" events: - name: onWakeWordDetected payload: "void" description: "Fired when wake word is detected" uses_apis: [] uses_components: [] internal_state: [lastDetectionTime] variants: [default] - id: component_recording_list name: RecordingList props: - name: recordings type: "Recording[]" required: true description: "Array of recordings to display" - name: isLoading type: boolean required: false default: false description: "Whether recordings are being loaded" events: - name: onSelectRecording payload: "string" description: "Fired when recording is clicked, payload is recording ID" - name: onDeleteRecording payload: "string" description: "Fired when delete confirmed, payload is recording ID" uses_apis: [] uses_components: [component_recording_card] internal_state: [] variants: [default, compact] - id: component_recording_card name: RecordingCard props: - name: recording type: Recording required: true description: "Recording to display" - name: showActions type: boolean required: false default: true description: "Show edit/delete buttons" events: - name: onClick payload: "string" description: "Fired when card clicked, payload is recording ID" - name: onDelete payload: "string" description: "Fired when delete confirmed, payload is recording ID" uses_apis: [] uses_components: [] internal_state: [isDeleting] variants: [default, compact] - id: component_audio_player name: AudioPlayer props: - name: audioUrl type: string required: true description: "URL to audio file" - name: duration type: integer required: true description: "Duration in seconds" events: - name: onPlayPause payload: "boolean" description: "Fired when play/pause toggled, payload is isPlaying" - name: onSeek payload: "number" description: "Fired when user seeks, payload is new time in seconds" uses_apis: [] uses_components: [] internal_state: [isPlaying, currentTime, audioElement] variants: [default] - id: component_transcript_viewer name: TranscriptViewer props: - name: transcript type: string required: true description: "Transcript text to display" - name: isLive type: boolean required: false default: false description: "Whether showing live transcription" events: [] uses_apis: [] uses_components: [] internal_state: [] variants: [default, live] - id: component_summary_display name: SummaryDisplay props: - name: summary type: string required: true description: "AI-generated summary text" - name: isLoading type: boolean required: false default: false description: "Whether summary is being generated" events: [] uses_apis: [] uses_components: [] internal_state: [] variants: [default] # ======================================== # GENERATED APP COMPONENTS # ======================================== - id: component_app_gallery name: AppGallery props: - name: apps type: "GeneratedApp[]" required: true description: "Array of generated apps to display" - name: isLoading type: boolean required: false default: false description: "Whether apps are being loaded" events: - name: onSelectApp payload: "string" description: "Fired when app is clicked, payload is app ID" uses_apis: [] uses_components: [component_app_card] internal_state: [] variants: [grid, list] - id: component_app_card name: AppCard props: - name: app type: GeneratedApp required: true description: "Generated app to display" - name: showActions type: boolean required: false default: true description: "Show delete button" events: - name: onClick payload: "string" description: "Fired when card clicked, payload is app ID" - name: onDelete payload: "string" description: "Fired when delete confirmed, payload is app ID" uses_apis: [] uses_components: [] internal_state: [isDeleting] variants: [default, compact] - id: component_app_iframe_viewer name: AppIframeViewer props: - name: htmlContent type: string required: true description: "HTML content to render in iframe" - name: title type: string required: true description: "App title for accessibility" events: - name: onLoadComplete payload: "void" description: "Fired when iframe finishes loading" uses_apis: [] uses_components: [] internal_state: [isLoading, iframeRef] variants: [default, fullscreen] # ============================================================================ # DEPENDENCY GRAPH # ============================================================================ dependency_graph: layers: - layer: 1 name: "Data Models" description: "Database schema - no dependencies" items: - id: model_user type: model dependencies: [] - id: model_recording type: model dependencies: [] - id: model_generated_app type: model dependencies: [] - layer: 2 name: "API Endpoints" description: "Backend APIs - depend on models" items: - id: api_register_user type: api dependencies: [model_user] - id: api_login_user type: api dependencies: [model_user] - id: api_logout_user type: api dependencies: [] - id: api_get_current_user type: api dependencies: [model_user] - id: api_list_recordings type: api dependencies: [model_recording] - id: api_create_recording type: api dependencies: [model_recording] - id: api_get_recording type: api dependencies: [model_recording] - id: api_delete_recording type: api dependencies: [model_recording] - id: api_transcribe_recording type: api dependencies: [model_recording] - id: api_summarize_recording type: api dependencies: [model_recording] - id: api_list_apps type: api dependencies: [model_generated_app] - id: api_generate_app type: api dependencies: [model_generated_app, model_recording] - id: api_get_app type: api dependencies: [model_generated_app] - id: api_delete_app type: api dependencies: [model_generated_app] - layer: 3 name: "UI Components & Pages" description: "Frontend - depend on APIs" items: # Components - id: component_header type: component dependencies: [] - id: component_sidebar type: component dependencies: [] - id: component_hero type: component dependencies: [] - id: component_features type: component dependencies: [] - id: component_login_form type: component dependencies: [api_login_user] - id: component_register_form type: component dependencies: [api_register_user] - id: component_record_button type: component dependencies: [] - id: component_wake_word_indicator type: component dependencies: [] - id: component_recording_list type: component dependencies: [component_recording_card] - id: component_recording_card type: component dependencies: [] - id: component_audio_player type: component dependencies: [] - id: component_transcript_viewer type: component dependencies: [] - id: component_summary_display type: component dependencies: [] - id: component_app_gallery type: component dependencies: [component_app_card] - id: component_app_card type: component dependencies: [] - id: component_app_iframe_viewer type: component dependencies: [] # Pages - id: page_home type: page dependencies: [component_header, component_hero, component_features] - id: page_login type: page dependencies: [component_login_form] - id: page_register type: page dependencies: [component_register_form] - id: page_dashboard type: page dependencies: [api_get_current_user, api_list_recordings, component_header, component_sidebar, component_record_button, component_wake_word_indicator, component_recording_list] - id: page_recordings type: page dependencies: [api_list_recordings, component_header, component_sidebar, component_recording_list, component_recording_card] - id: page_recording_detail type: page dependencies: [api_get_recording, component_header, component_sidebar, component_audio_player, component_transcript_viewer, component_summary_display] - id: page_apps type: page dependencies: [api_list_apps, component_header, component_sidebar, component_app_gallery, component_app_card] - id: page_app_detail type: page dependencies: [api_get_app, component_header, component_sidebar, component_app_iframe_viewer] dependency_map: # Models model_user: depends_on: [] depended_by: [api_register_user, api_login_user, api_get_current_user] model_recording: depends_on: [] depended_by: [api_list_recordings, api_create_recording, api_get_recording, api_delete_recording, api_transcribe_recording, api_summarize_recording, api_generate_app] model_generated_app: depends_on: [] depended_by: [api_list_apps, api_generate_app, api_get_app, api_delete_app] # APIs - Auth api_register_user: depends_on: [model_user] depended_by: [component_register_form] api_login_user: depends_on: [model_user] depended_by: [component_login_form] api_logout_user: depends_on: [] depended_by: [] api_get_current_user: depends_on: [model_user] depended_by: [page_dashboard] # APIs - Recordings api_list_recordings: depends_on: [model_recording] depended_by: [page_dashboard, page_recordings] api_create_recording: depends_on: [model_recording] depended_by: [] api_get_recording: depends_on: [model_recording] depended_by: [page_recording_detail] api_delete_recording: depends_on: [model_recording] depended_by: [] api_transcribe_recording: depends_on: [model_recording] depended_by: [] api_summarize_recording: depends_on: [model_recording] depended_by: [] # APIs - Apps api_list_apps: depends_on: [model_generated_app] depended_by: [page_apps] api_generate_app: depends_on: [model_generated_app, model_recording] depended_by: [] api_get_app: depends_on: [model_generated_app] depended_by: [page_app_detail] api_delete_app: depends_on: [model_generated_app] depended_by: [] # Components component_header: depends_on: [] depended_by: [page_home, page_dashboard, page_recordings, page_recording_detail, page_apps, page_app_detail] component_sidebar: depends_on: [] depended_by: [page_dashboard, page_recordings, page_recording_detail, page_apps, page_app_detail] component_hero: depends_on: [] depended_by: [page_home] component_features: depends_on: [] depended_by: [page_home] component_login_form: depends_on: [api_login_user] depended_by: [page_login] component_register_form: depends_on: [api_register_user] depended_by: [page_register] component_record_button: depends_on: [] depended_by: [page_dashboard] component_wake_word_indicator: depends_on: [] depended_by: [page_dashboard] component_recording_list: depends_on: [component_recording_card] depended_by: [page_dashboard, page_recordings] component_recording_card: depends_on: [] depended_by: [component_recording_list, page_recordings] component_audio_player: depends_on: [] depended_by: [page_recording_detail] component_transcript_viewer: depends_on: [] depended_by: [page_recording_detail] component_summary_display: depends_on: [] depended_by: [page_recording_detail] component_app_gallery: depends_on: [component_app_card] depended_by: [page_apps] component_app_card: depends_on: [] depended_by: [component_app_gallery, page_apps] component_app_iframe_viewer: depends_on: [] depended_by: [page_app_detail] # Pages page_home: depends_on: [component_header, component_hero, component_features] depended_by: [] page_login: depends_on: [component_login_form] depended_by: [] page_register: depends_on: [component_register_form] depended_by: [] page_dashboard: depends_on: [api_get_current_user, api_list_recordings, component_header, component_sidebar, component_record_button, component_wake_word_indicator, component_recording_list] depended_by: [] page_recordings: depends_on: [api_list_recordings, component_header, component_sidebar, component_recording_list, component_recording_card] depended_by: [] page_recording_detail: depends_on: [api_get_recording, component_header, component_sidebar, component_audio_player, component_transcript_viewer, component_summary_display] depended_by: [] page_apps: depends_on: [api_list_apps, component_header, component_sidebar, component_app_gallery, component_app_card] depended_by: [] page_app_detail: depends_on: [api_get_app, component_header, component_sidebar, component_app_iframe_viewer] depended_by: []