Auto-Save Implementation
The auto-save functionality in MyStoryFlow ensures that users never lose their work while creating stories. This document covers the complete implementation of the auto-save system.
Overview
The auto-save system provides:
- Automatic saving: Content is saved 500ms after the user stops typing
- Real-time feedback: Users see save status and word/page counts
- Error handling: Graceful handling of network failures
- Performance optimization: Debounced saves to prevent excessive API calls
Architecture
The auto-save system consists of:
- API Endpoint:
/api/stories/[storyId]- Handles story updates - Auto-Save Utilities: Core functions for saving and calculations
- Frontend Components: Editor shell and footer with real-time feedback
- Debounced Saving: 500ms delay to optimize performance
Key Components
API Implementation
// PATCH /api/stories/[storyId]/route.ts
export async function PATCH(request: NextRequest, { params }) {
const { storyId } = await params
const { content } = await request.json()
// Authentication and validation
const supabase = createClient()
const {
data: { user },
error: authError,
} = await supabase.auth.getUser()
// Calculate metrics
const wordCount = calculateWordCount(content)
const pageCount = calculatePageCount(wordCount)
// Update story with new content and metrics
const { data, error } = await supabase
.from('stories')
.update({ content, word_count: wordCount, page_count: pageCount })
.eq('id', storyId)
.eq('user_id', user.id)
.select()
.single()
return NextResponse.json({ success: true, data })
}
``` -->
### Auto-Save Utilities
```typescript
// apps/web-app/app/utils/autoSave.ts
export async function saveStoryContent(storyId: string, content: string) {
const response = await fetch(`/api/stories/${storyId}`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ content }),
})
return response.json()
}
export function calculateWordCount(content: string): number {
const textOnly = content.replace(/<[^>]*>/g, ' ')
return textOnly
.trim()
.split(/\s+/)
.filter((word) => word.length > 0).length
}
export function createDebouncedSave(saveFunction: Function, delay = 500) {
let timeoutId: NodeJS.Timeout | null = null
return (content: string) => {
if (timeoutId) clearTimeout(timeoutId)
timeoutId = setTimeout(() => saveFunction(content), delay)
}
}
``` -->
### Frontend Integration
The `EnhancedEditorShell` component orchestrates the auto-save functionality:
- **State Management**: Tracks save status, word count, and last saved time
- **Debounced Saving**: Uses 500ms delay after user stops typing
- **Real-time Updates**: Updates UI immediately while saving in background
- **Error Handling**: Displays appropriate status messages
### Editor Footer
The `EditorFooter` component provides real-time feedback:
- **Word Count**: Live word count as user types
- **Page Count**: Estimated pages at 250 words per page
- **Save Status**: Visual indicators for saving, saved, or error states
- **Timestamp**: Shows when content was last saved
## Features
### 1. Debounced Saving
- **Delay**: 500ms after user stops typing
- **Efficiency**: Prevents excessive API calls
- **Cancellation**: Previous saves are cancelled if new changes occur
### 2. Real-time Statistics
- **Word Count**: Strips HTML tags and counts actual words
- **Page Count**: Estimates pages at 250 words per page
- **Immediate Updates**: UI updates instantly, API saves debounced
### 3. Save Status Feedback
- **Visual Indicators**: Spinner for saving, colors for status
- **Timestamps**: Shows when content was last saved
- **Error Handling**: Clear error states and messaging
### 4. Security & Validation
- **Authentication**: Verifies user ownership of stories
- **Input Validation**: Sanitizes and validates content
- **Error Boundaries**: Graceful error handling
## Performance Considerations
### 1. Debouncing Strategy
- **500ms delay**: Balances responsiveness with efficiency
- **Cancellation**: Previous timeouts are cleared
- **Memory management**: Proper cleanup of timers
### 2. API Optimization
- **Minimal payload**: Only sends necessary data
- **Database efficiency**: Single query with proper indexing
- **Error handling**: Fast failure paths
### 3. UI Responsiveness
- **Immediate feedback**: Local state updates instantly
- **Progressive enhancement**: Works without JavaScript
- **Loading states**: Clear visual feedback during saves
## Testing
The implementation includes comprehensive tests for:
- API endpoint functionality
- Utility function accuracy
- Component behavior
- Error scenarios
This auto-save system provides a seamless writing experience while ensuring data integrity and optimal performance.