From 7b5af20dee944b8308a5cb6cb95777bd9078b04c Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Tue, 7 Oct 2025 03:18:02 -0700 Subject: [PATCH] docs: capture autosave roll-out plan --- docs/autosave-completion-guide.md | 61 ++++++ prd/PRD-auto-save-functionality.md | 338 +++++++++++++++++++++++++++++ 2 files changed, 399 insertions(+) create mode 100644 docs/autosave-completion-guide.md create mode 100644 prd/PRD-auto-save-functionality.md diff --git a/docs/autosave-completion-guide.md b/docs/autosave-completion-guide.md new file mode 100644 index 0000000..6db20c7 --- /dev/null +++ b/docs/autosave-completion-guide.md @@ -0,0 +1,61 @@ +# Admin Autosave Completion Guide + +## Objectives +- Eliminate redundant save requests triggered on initial page load. +- Restore reliable local draft recovery, including clear-up of stale backups. +- Deliver autosave status feedback that visibly transitions back to `idle` after successful saves. +- Ensure navigation/unload flows wait for pending autosaves instead of cancelling them mid-flight. + +## Key Problem Areas + +### Missing Draft Handlers +- `src/routes/admin/posts/[id]/edit/+page.svelte:425` references `restoreDraft` and `dismissDraft`, but the functions are never defined. Draft recovery buttons therefore break compilation and runtime behavior. + +### Immediate Autosaves on Load +- Effects in `src/routes/admin/posts/[id]/edit/+page.svelte:307` and `src/lib/components/admin/ProjectForm.svelte:157` call `autoSave.schedule()` as soon as the component mounts. Because the payload hash includes `updatedAt`, each mount triggers redundant PUTs until the server response realigns the hash. + +### Ineffective Navigation Guard +- `beforeNavigate(() => autoSave.flush())` (posts + project form) does not cancel the outbound navigation, so the flush typically aborts when the route unloads. Result: unsaved work if the user navigates away during a pending autosave. + +### Controller Lifecycle Gaps +- `createAutoSaveController` timers/AbortController persist after leaving the page because callers never invoke `destroy()`. +- Post editor imports `clearDraft` but never clears the draft after successful saves or when dismissing the prompt, so stale backups reappear. + +## Controller Enhancements (`src/lib/admin/autoSave.ts`) +- **Baseline priming**: Add a `prime(initialPayload)` (or allow `onSaved` to pass the response payload) to set `lastSentHash` immediately after fetching server data. This prevents an automatic save when the user has not made changes. +- **Auto-idle transition**: When status becomes `'saved'`, set a timeout (e.g., 2s) that reverts status to `'idle'`. Cancel the timeout on any new state change. +- **Robust destroy**: Ensure `destroy()` clears pending timers and aborts the current request; expose and require callers to invoke it on component teardown. +- Consider optional helper flags (e.g., `autoResetStatus`) so forms do not reimplement timing logic. + +## Shared Lifecycle Helper +Create a utility (e.g., `initAutoSaveLifecycle`) that accepts the controller plus configuration: +- Registers keyboard shortcut (`Cmd/Ctrl+S`) to `flush()` once the page has loaded. +- Provides a real navigation guard that cancels the navigation event, awaits `flush()`, then resumes or surfaces an error. +- Hooks into `onDestroy` to remove listeners and call `controller.destroy()`. +- Optionally wires window unload handling if needed. + +## Form Integration Checklist + +### Posts Editor (`src/routes/admin/posts/[id]/edit/+page.svelte`) +1. Implement `restoreDraft` / `dismissDraft` and handle `clearDraft` after autosave or manual save success. +2. Introduce a `hasLoaded` flag set after `loadPost()` (and controller `prime`) before scheduling autosave. +3. Adopt the shared lifecycle helper for navigation, keyboard shortcuts, and cleanup. + +### Project Form (`src/lib/components/admin/ProjectForm.svelte`) +1. Mirror baseline priming and `hasLoaded` gating before scheduling. +2. Clear drafts on success or dismissal, and reuse the lifecycle helper. +3. Ensure autosave only starts after the initial project data populates `formData`. + +### Other Forms (Simple Post, Essay, Photo, etc.) +- Audit each admin form to ensure they use the shared lifecycle helper, seed baselines, clear drafts, and transition status back to `idle`. + +## Testing & Verification +- **Unit Tests**: Cover controller state transitions, baseline priming, abort handling, and auto-idle timeout (`tests/autoSaveController.test.ts`). Run with `node --test --loader tsx tests/autoSaveController.test.ts`. +- **Component Tests**: Verify autosave does not fire on initial mount, drafts restore/clear correctly, and navigation waits for flush. +- **Manual QA**: Confirm keyboard shortcut behavior, offline fallback, and that UI returns to `idle` after showing “saved”. + +## Structural Considerations +- Factor shared autosave wiring into reusable modules to avoid copy/paste drift. +- Ensure server response payloads used in `prime()` reflect the canonical representation (including normalized fields) so hashes stay in sync. +- Document the lifecycle helper so new admin screens adopt the proven pattern without regression. + diff --git a/prd/PRD-auto-save-functionality.md b/prd/PRD-auto-save-functionality.md new file mode 100644 index 0000000..3b2563a --- /dev/null +++ b/prd/PRD-auto-save-functionality.md @@ -0,0 +1,338 @@ +# Product Requirements Document: Auto-Save Functionality + +## Executive Summary +Implement an intelligent auto-save system for all admin forms and editors to prevent data loss and improve the content creation experience. + +## Problem Statement +Currently, users must manually save their work in the admin interface, which can lead to: +- Data loss if the browser crashes or connection is interrupted +- Anxiety about losing work during long editing sessions +- Inefficient workflow with frequent manual saves +- No recovery mechanism for unsaved changes + +## Goals & Success Metrics + +### Primary Goals +1. Prevent data loss during content creation +2. Provide seamless, unobtrusive saving experience +3. Enable recovery from unexpected interruptions +4. Maintain data consistency and integrity + +### Success Metrics +- 0% data loss from browser crashes or network issues +- <3 second save latency for typical content +- 95% of saves complete without user intervention +- User satisfaction with editing experience improvement + +## User Stories + +### As a content creator +- I want my work to be automatically saved so I don't lose progress +- I want to see clear feedback about save status +- I want to recover my work if something goes wrong +- I want control over when auto-save is active + +### As a site administrator +- I want to ensure data integrity across all saves +- I want to minimize server load from frequent saves +- I want to track save patterns for optimization + +## Functional Requirements + +### Core Auto-Save System + +#### 1. Smart Debouncing +- **Content changes**: 2-second delay after user stops typing +- **Metadata changes**: Immediate save for critical fields +- **Navigation events**: Immediate save before leaving page +- **Keyboard shortcut**: Cmd/Ctrl+S for manual save + +#### 2. Save States & Feedback +- **Idle**: No pending changes +- **Saving**: Active save in progress with spinner +- **Saved**: Confirmation with timestamp +- **Error**: Clear error message with retry option +- **Conflict**: Detection and resolution UI + +#### 3. Data Persistence +- **Server-first**: Primary storage in database +- **Local backup**: IndexedDB for offline/recovery +- **Conflict detection**: Version tracking with timestamps +- **Partial saves**: Only send changed fields + +### Visual Design + +#### Status Indicator +``` +States: +- Idle: No indicator (clean UI) +- Saving: "Saving..." with subtle spinner +- Saved: "All changes saved" (fades after 2s) +- Error: Red indicator with retry button +- Offline: "Working offline" badge +``` + +#### Positioning +- Fixed position in editor header +- Non-intrusive, doesn't shift content +- Responsive to different screen sizes +- Accessible color contrast + +### API Design + +#### New Endpoints +```typescript +// Auto-save endpoint +POST /api/posts/[id]/autosave +Body: { + content?: JSONContent, + title?: string, + metadata?: object, + lastModified: timestamp +} +Response: { + success: boolean, + lastModified: timestamp, + conflict?: { + serverVersion: object, + serverModified: timestamp + } +} + +// Recovery endpoint +GET /api/posts/[id]/recover +Response: { + localDraft?: object, + serverVersion: object, + timestamps: { + local?: timestamp, + server: timestamp + } +} +``` + +### Integration Points + +#### Form Components to Update +1. **EssayForm.svelte** - Blog posts and essays +2. **ProjectForm.svelte** - Project case studies +3. **AlbumForm.svelte** - Album descriptions +4. **SimplePostForm.svelte** - Simple text posts +5. **PhotoPostForm.svelte** - Photo posts with captions + +#### Composer Integration +- Hook into TipTap editor's `onUpdate` event +- Track content changes separately from metadata +- Handle rich media embeds appropriately + +## Technical Requirements + +### Frontend Architecture + +#### Auto-Save Hook (`useAutoSave.svelte.ts`) +```typescript +class AutoSave { + private state = $state<'idle' | 'saving' | 'saved' | 'error'>('idle') + private lastSaved = $state(null) + private saveTimer: NodeJS.Timeout | null = null + private saveQueue: Set = new Set() + + constructor(options: AutoSaveOptions) { + // Initialize with endpoint, auth, debounce settings + } + + track(field: string, value: any): void + save(immediate?: boolean): Promise + recover(): Promise + reset(): void +} +``` + +#### Svelte 5 Integration +- Use `$state` rune for reactive state +- Use `$effect` for side effects and cleanup +- Use `$derived` for computed values +- Maintain compatibility with existing stores + +### Backend Requirements + +#### Database Schema Updates +```sql +-- Add version tracking +ALTER TABLE posts ADD COLUMN version INTEGER DEFAULT 1; +ALTER TABLE posts ADD COLUMN last_auto_save TIMESTAMP; + +-- Auto-save drafts table +CREATE TABLE auto_save_drafts ( + id SERIAL PRIMARY KEY, + entity_type VARCHAR(50), + entity_id INTEGER, + user_id INTEGER, + content JSONB, + created_at TIMESTAMP DEFAULT NOW() +); +``` + +#### Performance Optimizations +- Implement request coalescing for rapid changes +- Use database transactions for consistency +- Add Redis caching for conflict detection +- Implement rate limiting per user + +### Security Considerations +- Validate user ownership before auto-save +- Sanitize content to prevent XSS +- Rate limit to prevent abuse +- Encrypt local storage data +- Audit trail for all saves + +## Non-Functional Requirements + +### Performance +- Save latency <500ms for text content +- <2MB memory overhead per form +- Debounce efficiency >90% reduction in requests +- Support 100+ concurrent editors + +### Reliability +- 99.9% save success rate +- Graceful degradation on network issues +- Automatic retry with exponential backoff +- Data recovery from last 24 hours + +### Usability +- Zero configuration for basic use +- Clear, non-technical error messages +- Intuitive conflict resolution +- Keyboard accessible + +### Compatibility +- Chrome 90+, Firefox 88+, Safari 14+ +- Mobile responsive +- Works with screen readers +- Progressive enhancement + +## Implementation Plan + +### Phase 1: Core Infrastructure (Week 1-2) +- [ ] Create `useAutoSave` hook +- [ ] Implement debouncing logic +- [ ] Add basic status component +- [ ] Create auto-save API endpoint + +### Phase 2: Form Integration (Week 2-3) +- [ ] Integrate with EssayForm +- [ ] Integrate with ProjectForm +- [ ] Add keyboard shortcuts +- [ ] Implement local storage backup + +### Phase 3: Advanced Features (Week 3-4) +- [ ] Conflict detection and resolution +- [ ] Offline support with service worker +- [ ] Recovery interface +- [ ] Performance monitoring + +### Phase 4: Polish & Testing (Week 4-5) +- [ ] UI/UX refinements +- [ ] Comprehensive testing +- [ ] Documentation +- [ ] Performance optimization + +## Testing Strategy + +### Unit Tests +- Debounce logic validation +- State management correctness +- API error handling +- Local storage operations + +### Integration Tests +- Form component integration +- API endpoint validation +- Conflict resolution flow +- Recovery scenarios + +### E2E Tests +- Complete save flow +- Network interruption handling +- Multi-tab scenarios +- Mobile experience + +### Performance Tests +- Load testing with concurrent users +- Memory leak detection +- Network bandwidth usage +- Database query optimization + +## Rollout Strategy + +1. **Beta Testing**: Deploy to staging with select users +2. **Gradual Rollout**: Enable for 10% → 50% → 100% of forms +3. **Monitoring**: Track save success rates and user feedback +4. **Iteration**: Refine based on real-world usage + +## Future Enhancements + +### Version 2.0 +- Real-time collaboration indicators +- Revision history with diff view +- Auto-save templates and drafts +- AI-powered content suggestions + +### Version 3.0 +- Multi-device sync +- Offline-first architecture +- Advanced merge conflict resolution +- Team collaboration features + +## Risks & Mitigations + +| Risk | Impact | Mitigation | +|------|--------|------------| +| Data corruption | High | Implement checksums and validation | +| Performance degradation | Medium | Rate limiting and request batching | +| User confusion | Low | Clear UI feedback and documentation | +| Storage limits | Low | Implement cleanup and quotas | + +## Dependencies + +### External Libraries +- None required (uses native Svelte/SvelteKit features) + +### Internal Systems +- Existing authentication system +- Toast notification system +- TipTap editor integration +- Prisma database client + +## Acceptance Criteria + +- [ ] Auto-save activates within 2 seconds of changes +- [ ] Visual feedback appears for all save states +- [ ] Manual save button remains functional +- [ ] Recovery works after browser crash +- [ ] No data loss in normal operation +- [ ] Performance metrics meet targets +- [ ] Accessibility standards met +- [ ] Documentation complete + +## Appendix + +### Competitive Analysis +- **Notion**: Instant save with "Saving..." indicator +- **Google Docs**: Real-time with conflict resolution +- **WordPress**: Auto-save drafts every 60 seconds +- **Medium**: Continuous save with version history + +### User Research Insights +- Users expect auto-save in modern editors +- Visual feedback reduces anxiety +- Recovery options increase trust +- Performance is critical for user satisfaction + +--- + +**Document Version**: 1.0 +**Last Updated**: 2025-01-30 +**Author**: System Architecture Team +**Status**: Ready for Implementation \ No newline at end of file