Skip to content

feat: implement import flow for scanned content - #1

Merged
kerinin merged 28 commits into
mainfrom
feature/import-flow
Jan 8, 2026
Merged

feat: implement import flow for scanned content#1
kerinin merged 28 commits into
mainfrom
feature/import-flow

Conversation

@kerinin

@kerinin kerinin commented Jan 6, 2026

Copy link
Copy Markdown
Owner

Summary

Implements the first user flow: importing scanned content into Patchwork.

  • OCR Service: Client-side OCR using Tesseract.js with confidence thresholds
  • Import Store: Queue management for file imports with status tracking
  • DropZone Component: Drag-and-drop file import with visual feedback
  • ImportStatus Component: Non-blocking progress bar that persists during navigation
  • Route Rename: Inbox → Import with updated navigation labels
  • Edge Function: embed-text function for OpenAI embeddings
  • Auth Service: Dev-mode auto-login for easier testing

Navigation

  • Import → Assemble → Edit workflow
  • Patches appear in Import view only if OCR needs review (low confidence)

Patch Status Flow

processingneeds_review or readyapplied or discarded

Test Plan

  • 161 frontend tests passing
  • Type check: 0 errors
  • Lint: 0 warnings
  • Manual test: Drop image files on Import page
  • Manual test: Verify status bar appears during processing
  • Manual test: Navigate away and back - status persists

kerinin and others added 24 commits January 6, 2026 13:26
Design for the first user flow: dropping files to import patches.
Key decisions: Tesseract.js for client-side OCR, thin Edge Function
for embeddings, non-blocking status bar, dev-mode auto-login.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Detailed task breakdown for implementing file drop import with
Tesseract.js OCR, import queue management, and embed_text Edge Function.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Update PatchStatus type to support the new import flow:
- 'processing' - patch is being processed (OCR, embedding)
- 'needs_review' - patch needs user review (replaces 'inbox' and 'review')
- 'ocr_complete' - OCR is done, ready for suggestion generation
- 'ready' - suggestion generated, ready for user action
- 'applied' - patch has been applied to a document
- 'discarded' - patch was discarded by user

Also updated all references in services and tests to use new status values.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add authentication service with dev-mode auto-login functionality:
- Add DEV_AUTO_LOGIN, DEV_USER_EMAIL, DEV_USER_PASSWORD env variables
- Create auth.ts with ensureAuthenticated() and getCurrentUserId()
- Auto-login with dev credentials when no session exists in dev mode
- Include comprehensive tests for auth service

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add documentation comment explaining hardcoded dev credentials decision
- Fix inconsistent null handling for email (use ?? undefined in both places)
- Add test for non-browser environment error
- Add test for auto-login returns no user case
- Add test for non-dev mode (auto-login disabled)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds client-side OCR processing for extracting text from scanned images.
Includes confidence-based review detection to flag low-quality results
for manual review.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add tests for getLowConfidenceWords() and terminateOcr() functions:
- getLowConfidenceWords: verify filtering words below 75% confidence
- terminateOcr: verify worker termination behavior

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add defensive null check for data.words to handle undefined cases
- Fix worker initialization race condition using promise-based singleton
- Add JSDoc explaining confidence threshold rationale

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add a Svelte store to manage the import queue state for the file import
flow. The store provides pure state management for tracking files through
the upload -> create patch -> OCR -> update pipeline.

Features:
- Queue management with pending/uploading/processing/complete/error states
- File type validation (accepts jpeg, png, webp, tiff images)
- Progress tracking per item
- Derived stores for pending items, processing items, and error detection
- Helper functions: addFilesToQueue, clearCompleted

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Import and call processQueue() after files are added to trigger processing
- Add tabindex="0" for keyboard accessibility
- Add processQueue() export function to import store

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Non-blocking status bar that shows import progress:
- Processing state with spinner and progress bar
- Error state when imports fail
- Complete state with success indicator
- View button to navigate to /import
- Dismiss button to clear completed items

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add ARIA attributes to improve screen reader support:
- role="status" and aria-live="polite" on container for live region
- aria-label on View and Dismiss buttons for clear action description

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Renamed src/routes/inbox to src/routes/import
- Updated TopBar navigation labels: Inbox→Import, Editor→Edit
- Updated variable name from modes to navItems for clarity

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Change root route redirect from /inbox to /import
- Update DESIGN.md route documentation and API examples

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Integrate the DropZone component into the Import page to enable
drag-and-drop file importing. Add patch list display with toggle
between "Needs Review" and "All Patches" views. Include processing
status indicators and error handling with retry functionality.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add type="button" to prevent form submission on Needs Review and All Patches buttons
- Type error parameter as unknown for stricter TypeScript checking

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add the ImportStatus component to the app layout so it persists
across page navigation. The component uses fixed positioning to
display as an overlay showing import progress.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Thin proxy that hides the OpenAI API key from clients. Reuses the
existing shared embeddings utility for consistency with embed-content.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create embed_text_test.ts covering CORS, validation, and success cases
- Fix CORS preflight to return "ok" body instead of null

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Words in Tesseract.js are nested in blocks -> paragraphs -> lines -> words,
not directly on the Page object. This fixes the type errors and ensures
proper extraction of word data for bounding boxes and confidence scores.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Root cause: processQueue was a stub that only set isProcessing=true
but never actually processed pending items through the pipeline.

Changes:
- Implement processQueue to process items in batches
- Add processItem helper for full pipeline: upload → create patch → OCR → update
- Add integration tests for processQueue covering success, failure, and low-confidence cases
- Fix test mock to include 'dev' export from $app/environment

The tests didn't catch this because they tested store methods in isolation
with all dependencies mocked. Added integration tests to prevent regression.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Creates dev@patchwork.local / devpassword123 user in Supabase Auth
during `supabase db reset`. Required for dev auto-login feature.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@kerinin
kerinin force-pushed the feature/import-flow branch from 6371170 to e42c041 Compare January 7, 2026 00:22
kerinin and others added 4 commits January 6, 2026 19:24
Supabase storage rejects filenames with spaces and Unicode characters.
Added sanitizeFilename() to replace these with underscores.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Changes:
- Add integration tests that run against real Supabase instance
- Add migration to update patch status constraint with new values
  (processing, needs_review, ocr_complete, ready, applied, discarded)
- Tests verify: auth, storage upload, patch CRUD, full import pipeline

Integration tests use @vitest-environment node to enable real HTTP requests.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Create PatchCard component that loads images from storage
- Uses signed URLs via storage.getPatchImageUrl()
- Shows loading spinner while fetching, graceful fallback on error
- Add support for more image formats: GIF, BMP, HEIC, HEIF

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Image on left with document aspect ratio (17:22 ≈ 8.5x11)
- OCR text on right with monospace font, preserving whitespace
- Added OCR confidence indicator with color-coded progress bar
- Header with status badge and filename
- Wider card layout (1-2 columns instead of 1-2-3)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@kerinin
kerinin merged commit 5165c6f into main Jan 8, 2026
0 of 2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant