Skip to content

209 embedpdf viewer#210

Merged
InfinityBowman merged 23 commits into
mainfrom
209-embedpdf-viewer
Jan 4, 2026
Merged

209 embedpdf viewer#210
InfinityBowman merged 23 commits into
mainfrom
209-embedpdf-viewer

Conversation

@InfinityBowman
Copy link
Copy Markdown
Owner

@InfinityBowman InfinityBowman commented Jan 3, 2026

Summary by CodeRabbit

  • New Features

    • Added configurable PDF viewer with multiple viewing modes for enhanced flexibility
    • Implemented PDF virtualization for optimized rendering of large documents
    • Integrated alternative PDF display option for improved compatibility
  • Documentation

    • Added comprehensive database management and migration guides
  • Chores

    • Updated dependencies and database migration infrastructure

✏️ Tip: You can customize this high-level summary in your review settings.

@InfinityBowman InfinityBowman linked an issue Jan 3, 2026 that may be closed by this pull request
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 3, 2026

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

📝 Walkthrough

Walkthrough

The PR integrates EmbedPDF as an alternate PDF viewer alongside the existing PdfViewer, adding mode-based selection via configuration, wrapper components, PDF virtualization for large-file rendering efficiency, and database migration/script updates for production workflows.

Changes

Cohort / File(s) Summary
Configuration & Dependencies
.gitignore, packages/web/package.json, packages/web/src/config/pdfViewer.js, packages/workers/package.json
Added EmbedPDF and related dependencies; new PDF_VIEWER_MODE config (environment-driven, defaults to 'pdfjs'); updated prod DB migration scripts with --env production flag; added dotenv devDependency.
PDF Viewer Components
packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx, EmbedPdfViewerSnippet.jsx, EmbedPdfViewerPdfJs.jsx
Three new components: EmbedPdfViewer dispatcher (Switch/Match on mode), EmbedPdfViewerSnippet (blob-based EmbedPDF renderer with lifecycle, theme config, annotation controls), EmbedPdfViewerPdfJs (wrapper for existing PdfViewer).
Checklist PDF Integration
packages/web/src/components/checklist/ChecklistWithPdf.jsx, PdfPreviewPanel.jsx, SplitScreenLayout.jsx
ChecklistWithPdf now conditionally renders EmbedPdfViewer or PdfViewer based on mode; PdfPreviewPanel refactored to state machine (loading/error/ready/empty); SplitScreenLayout adjusted transform/contain properties (translateX/Y on hidden, no transform when shown; changed contain from layout to style).
PDF Rendering & Virtualization
packages/web/src/components/checklist/pdf/pdfVirtualization.js, PdfViewer.jsx
New pdfVirtualization module provides page-wise virtualization with binary-search lookup, lazy page-height computation, scroll listener management, and viewport-centered recalculation; PdfViewer docs enhanced via JSDoc.
Database & Scripts
packages/workers/migrations/meta/0000_snapshot.json, _journal.json, packages/workers/scripts/README.md, generate-test-sql.mjs, reset-db-prod.mjs
Migration snapshot/journal metadata updated (IDs, timestamps); comprehensive scripts README added; generate-test-sql now creates output directory; reset-db-prod adds migration-table drops and post-migration verification step.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant ChecklistWithPdf
    participant Config as PDF_VIEWER_MODE
    participant EmbedPdfViewer
    participant ViewerSnippet as EmbedPdfViewerSnippet
    participant ViewerPdfJs as EmbedPdfViewerPdfJs
    participant PdfViewer

    User->>ChecklistWithPdf: Render with pdfData
    ChecklistWithPdf->>Config: Read PDF_VIEWER_MODE
    alt mode === 'snippet'
        ChecklistWithPdf->>EmbedPdfViewer: Render (pdfData, pdfFileName, readOnly)
        EmbedPdfViewer->>ViewerSnippet: Match 'snippet' → Render
        ViewerSnippet->>ViewerSnippet: Create blob URL from pdfData
        ViewerSnippet->>ViewerSnippet: Initialize EmbedPDF viewer (theme, disabledCategories)
        ViewerSnippet->>ViewerSnippet: Setup lifecycle: createEffect + onCleanup
        ViewerSnippet->>User: Display PDF with EmbedPDF UI
    else mode === 'pdfjs' (default)
        ChecklistWithPdf->>EmbedPdfViewer: Render (pdfData, pdfFileName, readOnly)
        EmbedPdfViewer->>ViewerPdfJs: Match 'pdfjs' → Render
        ViewerPdfJs->>PdfViewer: Render with pdfData, pdfFileName
        PdfViewer->>User: Display PDF with pdfjs backend
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • Rename some labels #176: Modifies the same PDF UI components (ChecklistWithPdf.jsx and SplitScreenLayout.jsx); the retrieved PR adds pdfUrl/pdfData prop handling and import restructuring, making it a related code-level change that could conflict or overlap with viewer mode switching logic.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title '209 embedpdf viewer' is vague and lacks clarity. It references a ticket number and a general feature area but does not convey what was actually changed or implemented. Revise the title to be more descriptive, such as 'Add EmbedPDF viewer integration with mode selection' or 'Implement configurable PDF viewer with EmbedPDF and PDF.js support' to clearly communicate the main change.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented Jan 3, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
corates ffe4b93 Commit Preview URL Jan 04 2026, 02:27 AM

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (6)
packages/workers/scripts/reset-db-prod.mjs (1)

149-160: Verification checks only one table; consider broadening the check.

The verification only confirms that the verification table exists. This is a narrow check that may miss failures in other critical tables like user, projects, or organization. A single table check provides limited confidence that the migration succeeded completely.

Suggested improvements

Check for multiple critical tables to increase confidence:

-    // Verify critical tables were created
     console.log('  Verifying tables were created...');
     const verifyResult = runWranglerD1Execute(
-      "SELECT name FROM sqlite_master WHERE type='table' AND name='verification';",
+      "SELECT name FROM sqlite_master WHERE type='table' AND name IN ('user', 'projects', 'organization', 'verification') ORDER BY name;",
       { allowFailure: true },
     );
-    if (!verifyResult.stdout || !verifyResult.stdout.includes('verification')) {
-      console.error('  WARNING: verification table was not created!');
+    const expectedTables = ['user', 'projects', 'organization', 'verification'];
+    const missingTables = expectedTables.filter(table => !verifyResult.stdout.includes(table));
+    if (missingTables.length > 0) {
+      console.error(`  WARNING: Missing tables: ${missingTables.join(', ')}`);
       console.error('  Migration may have failed or been skipped.');
-      throw new Error('Migration verification failed: verification table missing');
+      throw new Error(`Migration verification failed: missing tables: ${missingTables.join(', ')}`);
     }
-    console.log('  Verification table exists');
+    console.log('  All critical tables verified');
packages/web/src/config/pdfViewer.js (1)

1-9: Consider validating PDF_VIEWER_MODE value.

The configuration accepts any value from the environment variable without validation. If someone sets VITE_PDF_VIEWER_MODE=invalid, the application will use that invalid mode, potentially causing runtime errors in components that depend on this value.

Suggested validation
+const VALID_MODES = ['pdfjs', 'snippet'];
+const mode = import.meta.env.VITE_PDF_VIEWER_MODE || 'pdfjs';
+
 // PDF viewer implementation mode:
 // - 'pdfjs': Uses PDF.js with custom UI (default)
 // - 'snippet': Uses EmbedPDF snippet viewer with full UI (toolbar, sidebar, etc.)
-export const PDF_VIEWER_MODE = import.meta.env.VITE_PDF_VIEWER_MODE || 'pdfjs';
+export const PDF_VIEWER_MODE = VALID_MODES.includes(mode) ? mode : 'pdfjs';
+
+if (!VALID_MODES.includes(mode) && mode !== 'pdfjs') {
+  console.warn(
+    `Invalid PDF_VIEWER_MODE "${mode}". Valid modes: ${VALID_MODES.join(', ')}. Falling back to 'pdfjs'.`
+  );
+}
packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx (1)

13-21: Incomplete JSDoc @returns annotation.

The @returns tag is empty. Consider completing it or removing the incomplete annotation.

Proposed fix
 /**
  * EmbedPdfViewer - Component for viewing PDF files using EmbedPDF snippet viewer
  * @param {Object} props - Component props
  * @param {ArrayBuffer} props.pdfData - ArrayBuffer of PDF data (required)
  * @param {string} props.pdfFileName - Name of the PDF file (optional, for display)
  * @param {boolean} props.readOnly - If true, view only mode
- *
- * @returns
+ * @returns {JSX.Element} The PDF viewer component
  */
packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx (2)

267-313: Consider reusing destroyViewer() in onCleanup to reduce duplication.

The cleanup logic duplicates most of destroyViewer(). While the extra safety check for the memo's blobUrl() is valid, the duplication increases maintenance burden.

Proposed simplification
   // Clean up on unmount
   onCleanup(() => {
-    // Destroy viewer instance
-    if (viewerInstance) {
-      try {
-        if (typeof viewerInstance.destroy === 'function') {
-          viewerInstance.destroy();
-        } else if (typeof viewerInstance.unmount === 'function') {
-          viewerInstance.unmount();
-        } else if (typeof viewerInstance.dispose === 'function') {
-          viewerInstance.dispose();
-        }
-      } catch (err) {
-        console.warn('Error destroying EmbedPDF viewer on cleanup:', err);
-      }
-      viewerInstance = null;
-    }
-
-    // Clear container contents
-    if (containerRef) {
-      try {
-        containerRef.innerHTML = '';
-      } catch (err) {
-        console.warn('Error clearing container:', err);
-      }
-    }
-
-    // Revoke blob URL (only the current one to avoid double-revoking)
-    if (currentBlobUrl) {
-      try {
-        URL.revokeObjectURL(currentBlobUrl);
-      } catch (err) {
-        console.warn('Error revoking blob URL:', err);
-      }
-      currentBlobUrl = null;
-    }
+    destroyViewer();

     // Also revoke the current blobUrl if different (shouldn't happen, but safety check)
     const url = blobUrl();
     if (url && url !== currentBlobUrl) {
       try {
         URL.revokeObjectURL(url);
       } catch (err) {
         console.warn('Error revoking blob URL:', err);
       }
     }
   });

317-327: Use Show component instead of ternary operator for conditional rendering.

Per coding guidelines, prefer Solid's Show component for conditional rendering instead of ternary operators.

Proposed fix
+import { createMemo, createEffect, onCleanup, Show } from 'solid-js';
...
-  const hasPdfData = createMemo(() => !!props.pdfData);
-
   return (
     <div class='h-full w-full bg-gray-100'>
-      {hasPdfData() ?
+      <Show
+        when={props.pdfData}
+        fallback={
+          <div class='flex h-full items-center justify-center'>
+            <div class='text-center text-gray-500'>
+              <p>No PDF selected</p>
+            </div>
+          </div>
+        }
+      >
         <div ref={containerRef} class='h-full w-full' />
-      : <div class='flex h-full items-center justify-center'>
-          <div class='text-center text-gray-500'>
-            <p>No PDF selected</p>
-          </div>
-        </div>
-      }
+      </Show>
     </div>
   );
packages/web/src/components/checklist/pdf/pdfVirtualization.js (1)

227-231: Consider logging errors in the catch block for debugging.

The catch block silently swallows errors and falls back to default heights. While the fallback is correct behavior, logging the error would help identify issues during development.

Proposed fix
-        } catch {
+        } catch (err) {
+          console.warn('Failed to precompute page heights, using defaults:', err);
           // Fall back to default height estimate if precompute fails.
           rebuildPrefixOffsets({ preserveScroll: true });
           handleScroll();
         }
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7c378fa and 07707b3.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (18)
  • .gitignore
  • packages/web/package.json
  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
  • packages/web/src/components/checklist/SplitScreenLayout.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx
  • packages/web/src/components/checklist/pdf/PdfViewer.jsx
  • packages/web/src/components/checklist/pdf/pdfVirtualization.js
  • packages/web/src/components/project/PdfPreviewPanel.jsx
  • packages/web/src/config/pdfViewer.js
  • packages/workers/migrations/0000_needy_puff_adder.sql
  • packages/workers/migrations/meta/0000_snapshot.json
  • packages/workers/migrations/meta/_journal.json
  • packages/workers/package.json
  • packages/workers/scripts/README.md
  • packages/workers/scripts/generate-test-sql.mjs
  • packages/workers/scripts/reset-db-prod.mjs
🧰 Additional context used
📓 Path-based instructions (16)
packages/web/**/!(*.test|*.spec).{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/error-handling.mdc)

packages/web/**/!(*.test|*.spec).{js,ts,jsx,tsx}: Always use handleFetchError from @/lib/error-utils.js for frontend fetch calls with optional showToast parameter
Use createFormErrorSignals from @/lib/form-errors.js for handling form validation errors, field-level errors, and global errors in frontend forms

Files:

  • packages/web/src/config/pdfViewer.js
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/src/components/project/PdfPreviewPanel.jsx
  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
  • packages/web/src/components/checklist/SplitScreenLayout.jsx
  • packages/web/src/components/checklist/pdf/pdfVirtualization.js
  • packages/web/src/components/checklist/pdf/PdfViewer.jsx
packages/{web,workers}/**/!(*.test|*.spec).{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/error-handling.mdc)

packages/{web,workers}/**/!(*.test|*.spec).{js,ts,jsx,tsx}: Never throw string literals; always throw Error objects or return domain errors from API routes
Use isErrorCode utility from @corates/shared or @/lib/error-utils.js to check for specific error codes instead of manual error comparisons

Files:

  • packages/web/src/config/pdfViewer.js
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/src/components/project/PdfPreviewPanel.jsx
  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
  • packages/web/src/components/checklist/SplitScreenLayout.jsx
  • packages/web/src/components/checklist/pdf/pdfVirtualization.js
  • packages/web/src/components/checklist/pdf/PdfViewer.jsx
packages/web/src/**/*.{js,jsx}

📄 CodeRabbit inference engine (.cursor/rules/form-state.mdc)

packages/web/src/**/*.{js,jsx}: Save form state to IndexedDB before initiating OAuth redirects (Google Drive, ORCID) using saveFormState() with form type ('createProject' or 'addStudies') and serializable state only
Only save serializable data to IndexedDB—exclude File objects, ArrayBuffers, functions, and other non-serializable objects from form state persistence
Restore form state after OAuth redirects by checking URL restore params with getRestoreParamsFromUrl(), retrieving saved state with getFormState(), restoring to form, clearing saved state with clearFormState(), and clearing URL params with clearRestoreParamsFromUrl()
For temporary File object storage during OAuth flows (e.g., pending PDFs), use projectStore.setPendingProjectData() instead of IndexedDB, as File objects cannot be serialized
Add restore parameters to the URL after OAuth redirects in the format '?restore=&projectId=' to signal form state restoration on mount
Clear URL restore parameters after form state restoration by calling clearRestoreParamsFromUrl() to prevent stale restoration attempts on subsequent navigation
Form state persistence library functions (saveFormState, getFormState, clearFormState, getRestoreParamsFromUrl, clearRestoreParamsFromUrl) are implemented in packages/web/src/lib/formStatePersistence.js and should be imported from @/lib/formStatePersistence.js

Files:

  • packages/web/src/config/pdfViewer.js
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/src/components/project/PdfPreviewPanel.jsx
  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
  • packages/web/src/components/checklist/SplitScreenLayout.jsx
  • packages/web/src/components/checklist/pdf/pdfVirtualization.js
  • packages/web/src/components/checklist/pdf/PdfViewer.jsx
packages/web/src/**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/pdf-handling.mdc)

packages/web/src/**/*.{js,jsx,ts,tsx}: Always use uploadPdf from @api/pdf-api.js for uploading PDF files. Pass object with projectId, studyId, tag ('primary' or 'supplementary'), and fileName
Validate PDF files on frontend by checking file.type includes 'pdf' and file.size is within MAX_PDF_SIZE limit (full validation is done on backend)
Use cachePdf and getCachedPdf from @primitives/pdfCache.js for caching PDF data in IndexedDB
Implement PDF caching strategy: check cache first, download from server if not cached, then cache the downloaded PDF
Store only PDF metadata in Yjs (id, name, size, tag, uploadedAt, uploadedBy), never store PDF binary data in Yjs as it is too large
Use importFromGoogleDrive from @api/google-drive.js for importing PDFs from Google Drive. Pass fileId, projectId, studyId, and tag
Save form state using saveFormState from @/lib/formStatePersistence.js before triggering OAuth redirects for Google Drive
Use addPdfToStudy operation from useProject hook to add PDFs to a study, passing id, name, size, tag, uploadedAt, and uploadedBy
Use removePdfFromStudy operation from useProject hook to remove PDFs from a study
Use pdfPreviewStore from @/stores/pdfPreviewStore.js for managing PDF preview state (openPreview, closePreview, getPreview methods)
Use downloadPdf from @api/pdf-api.js to download PDFs from server, then cache the result using cachePdf
Always cache PDFs after download and check cache before downloading to avoid redundant downloads
Use PDF operations from useProject hook instead of bypassing through direct API calls

Files:

  • packages/web/src/config/pdfViewer.js
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/src/components/project/PdfPreviewPanel.jsx
  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
  • packages/web/src/components/checklist/SplitScreenLayout.jsx
  • packages/web/src/components/checklist/pdf/pdfVirtualization.js
  • packages/web/src/components/checklist/pdf/PdfViewer.jsx
{packages/web/**,packages/landing/**}/**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/solidjs.mdc)

{packages/web/**,packages/landing/**}/**/*.{js,jsx,ts,tsx}: Use createSignal for simple reactive values in SolidJS components
Use createStore for complex objects and arrays that need granular reactivity in SolidJS
Use createMemo for computed/derived values that depend on reactive state in SolidJS
Always clean up SolidJS effects that create subscriptions or timers using onCleanup
Import stores directly in components and use store read/write action pattern - read from store, write via actions store
Prefer derived state with createMemo or signals over effects whenever possible
Use local createSignal or createStore for local component state; use external stores for shared/cross-feature state

Files:

  • packages/web/src/config/pdfViewer.js
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/src/components/project/PdfPreviewPanel.jsx
  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
  • packages/web/src/components/checklist/SplitScreenLayout.jsx
  • packages/web/src/components/checklist/pdf/pdfVirtualization.js
  • packages/web/src/components/checklist/pdf/PdfViewer.jsx
packages/{web,ui}/**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)

packages/{web,ui}/**/*.{js,jsx,ts,tsx}: Import UI components from '@corates/ui' package instead of local components directories
Use solid-icons library for icons instead of emojis or other icon sources
Use Tailwind CSS classes for styling UI components
Apply responsive design using mobile-first approach with Tailwind CSS

Files:

  • packages/web/src/config/pdfViewer.js
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/src/components/project/PdfPreviewPanel.jsx
  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
  • packages/web/src/components/checklist/SplitScreenLayout.jsx
  • packages/web/src/components/checklist/pdf/pdfVirtualization.js
  • packages/web/src/components/checklist/pdf/PdfViewer.jsx
packages/web/**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/ui-components.mdc)

Use import aliases from jsconfig.json (e.g., @/, @components/, @auth-ui/, @checklist-ui/, @project-ui/, @routes/, @primitives/, @api/, @config/, @lib/) instead of relative paths

Files:

  • packages/web/src/config/pdfViewer.js
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/src/components/project/PdfPreviewPanel.jsx
  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
  • packages/web/src/components/checklist/SplitScreenLayout.jsx
  • packages/web/src/components/checklist/pdf/pdfVirtualization.js
  • packages/web/src/components/checklist/pdf/PdfViewer.jsx
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/yjs-sync.mdc)

**/*.{js,jsx,ts,tsx}: Use the useProject hook for managing Yjs connections with reference counting instead of creating Y.Doc instances directly
Never create Y.Doc instances directly; always use the connection registry managed by useProject
Access Y.Doc connection state via projectStore.getConnectionState(projectId) instead of checking connection state directly
Read Yjs-synced data from projectStore (using getStudies, getChecklist, etc.) rather than accessing Y.Doc maps/arrays directly
Use operation functions from useProject or projectActionsStore for writing data instead of directly modifying Y.Doc
Don't store Y.Doc references in component state; always retrieve the connection through useProject
Handle connection cleanup via onCleanup() in Solid.js components or equivalent cleanup patterns, calling disconnect() when the component unmounts

**/*.{js,jsx,ts,tsx}: For UI icons, use solid-icons library or SVGs only (never emojis)
Prefer modern ES6+ syntax and features
Use import aliases from jsconfig.json (see ui-components.mdc)
Group related components in subdirectories with barrel exports
Use Ark UI components from @corates/ui package, NOT local components
Use solid-icons icon library (e.g., solid-icons/bi, solid-icons/fi) for icons
Comments should explain WHY something is being done, not narrate what the code does
Use comments to explain why a particular approach or workaround was chosen
Use comments to clarify intent when code could be misread or misunderstood
Use comments to provide context from external systems, specs, or requirements
Use comments to document assumptions, edge cases, or limitations
Do NOT narrate what the code is doing in comments
Do NOT duplicate function or variable names in plain English in comments
Do NOT leave stale comments that contradict the code
Do NOT reference removed or obsolete code paths in comments

Files:

  • packages/web/src/config/pdfViewer.js
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/src/components/project/PdfPreviewPanel.jsx
  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
  • packages/web/src/components/checklist/SplitScreenLayout.jsx
  • packages/web/src/components/checklist/pdf/pdfVirtualization.js
  • packages/web/src/components/checklist/pdf/PdfViewer.jsx
**/*

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*: NEVER use emojis anywhere - not in code, comments, documentation, plan files, commit messages, or examples
Do NOT use unicode symbols - unicode symbols are forbidden anywhere in the codebase

Files:

  • packages/web/src/config/pdfViewer.js
  • packages/workers/migrations/meta/_journal.json
  • packages/workers/scripts/README.md
  • packages/workers/scripts/generate-test-sql.mjs
  • packages/workers/package.json
  • packages/workers/migrations/meta/0000_snapshot.json
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/package.json
  • packages/web/src/components/project/PdfPreviewPanel.jsx
  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
  • packages/web/src/components/checklist/SplitScreenLayout.jsx
  • packages/web/src/components/checklist/pdf/pdfVirtualization.js
  • packages/workers/scripts/reset-db-prod.mjs
  • packages/web/src/components/checklist/pdf/PdfViewer.jsx
**/*.{ts,tsx,jsx,js}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{ts,tsx,jsx,js}: For UI icons, use solid-icons library or SVGs only (never emojis)
Prefer modern ES6+ syntax and features
Use import aliases from jsconfig.json as defined in the ui-components.mdc documentation
Prefer config files over hardcoding values
Ensure browser compatibility (Safari is usually problematic)
Group related components in subdirectories with barrel exports
Use Ark UI components from @corates/ui package, not local component implementations
Use solid-icons icon library (e.g., solid-icons/bi, solid-icons/fi) for icons
Comments should explain WHY something is being done, not WHAT the code is doing
Comment to explain why a particular approach or workaround was chosen
Comment to clarify intent when code could be misread or misunderstood
Comment to provide context from external systems, specs, or requirements
Comment to document assumptions, edge cases, or limitations
Do NOT comment by narrating what the code is doing
Do NOT duplicate function or variable names in plain English comments
Do NOT leave stale comments that contradict the code
Do NOT reference removed or obsolete code paths in comments

Files:

  • packages/web/src/config/pdfViewer.js
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/src/components/project/PdfPreviewPanel.jsx
  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
  • packages/web/src/components/checklist/SplitScreenLayout.jsx
  • packages/web/src/components/checklist/pdf/pdfVirtualization.js
  • packages/web/src/components/checklist/pdf/PdfViewer.jsx
**/*.{js,jsx,ts,tsx,css,scss}

📄 CodeRabbit inference engine (.cursor/rules/corates.mdc)

Ensure browser compatibility (Safari is usually problematic)

Files:

  • packages/web/src/config/pdfViewer.js
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/src/components/project/PdfPreviewPanel.jsx
  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
  • packages/web/src/components/checklist/SplitScreenLayout.jsx
  • packages/web/src/components/checklist/pdf/pdfVirtualization.js
  • packages/web/src/components/checklist/pdf/PdfViewer.jsx
packages/web/src/**

📄 CodeRabbit inference engine (.cursor/rules/organizations.mdc)

packages/web/src/**: Use human-readable slug in frontend URLs: /orgs/:orgSlug/...
Use orgId (UUID) for API calls, not orgSlug, when making fetch requests to backend endpoints

Files:

  • packages/web/src/config/pdfViewer.js
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/src/components/project/PdfPreviewPanel.jsx
  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
  • packages/web/src/components/checklist/SplitScreenLayout.jsx
  • packages/web/src/components/checklist/pdf/pdfVirtualization.js
  • packages/web/src/components/checklist/pdf/PdfViewer.jsx
packages/web/src/**/*.{jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/pdf-handling.mdc)

Use PdfViewer component from @/components/checklist-ui/pdf/PdfViewer.jsx for displaying PDFs, passing pdfData as ArrayBuffer, fileName, readOnly, and onPageChange

Files:

  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/src/components/project/PdfPreviewPanel.jsx
  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
  • packages/web/src/components/checklist/SplitScreenLayout.jsx
  • packages/web/src/components/checklist/pdf/PdfViewer.jsx
{packages/web/**,packages/landing/**}/**/*.{jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/solidjs.mdc)

{packages/web/**,packages/landing/**}/**/*.{jsx,tsx}: NEVER destructure props in SolidJS components - access props directly or wrap in functions to maintain reactivity
Use external stores in packages/web/src/stores/ for shared/cross-feature state instead of prop-drilling
Keep SolidJS components lean and focused on rendering - move business logic to stores, primitives, or utilities
Create reusable logic in primitives (hooks) in packages/web/src/primitives/ and import them into components
Use Solid's Show component for conditional rendering instead of ternary operators
Use Solid's For component for rendering lists instead of Array.map()
Use the children helper when manipulating props.children in SolidJS components

Files:

  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/src/components/project/PdfPreviewPanel.jsx
  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
  • packages/web/src/components/checklist/SplitScreenLayout.jsx
  • packages/web/src/components/checklist/pdf/PdfViewer.jsx
packages/web/**/*.{ts,tsx,jsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

packages/web/**/*.{ts,tsx,jsx}: Do NOT prop-drill application state in SolidJS - import stores directly where needed
Do NOT destructure props in SolidJS - access props.field directly or wrap in function: () => props.field
SolidJS components should receive at most 1-5 props (local config only, not shared state)
Move business logic to stores, utilities, or primitives (not in components) in SolidJS

Files:

  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/src/components/project/PdfPreviewPanel.jsx
  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
  • packages/web/src/components/checklist/SplitScreenLayout.jsx
  • packages/web/src/components/checklist/pdf/PdfViewer.jsx
packages/web/**/*.{jsx,tsx}

📄 CodeRabbit inference engine (.cursor/rules/corates.mdc)

packages/web/**/*.{jsx,tsx}: Do NOT prop-drill application state in SolidJS - import stores directly where needed
Do NOT destructure props in SolidJS - access props.field directly or wrap in function: () => props.field
Shared state lives in external stores under packages/web/src/stores/
SolidJS components should receive at most 1-5 props (local config only, not shared state)
Use createStore for complex state objects in SolidJS
Use createMemo for derived values in SolidJS
Move business logic to stores, utilities, or primitives - not components
Frontend uses orgSlug in URLs (/orgs/:orgSlug/...) for readability

Files:

  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/src/components/project/PdfPreviewPanel.jsx
  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
  • packages/web/src/components/checklist/SplitScreenLayout.jsx
  • packages/web/src/components/checklist/pdf/PdfViewer.jsx
🧠 Learnings (40)
📓 Common learnings
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/pdf-handling.mdc:0-0
Timestamp: 2025-12-27T03:02:05.951Z
Learning: Applies to packages/web/src/**/*.{jsx,tsx} : Use `PdfViewer` component from `@/components/checklist-ui/pdf/PdfViewer.jsx` for displaying PDFs, passing pdfData as ArrayBuffer, fileName, readOnly, and onPageChange
📚 Learning: 2025-12-27T03:02:05.951Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/pdf-handling.mdc:0-0
Timestamp: 2025-12-27T03:02:05.951Z
Learning: Applies to packages/web/src/**/*.{jsx,tsx} : Use `PdfViewer` component from `@/components/checklist-ui/pdf/PdfViewer.jsx` for displaying PDFs, passing pdfData as ArrayBuffer, fileName, readOnly, and onPageChange

Applied to files:

  • packages/web/src/config/pdfViewer.js
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/package.json
  • packages/web/src/components/project/PdfPreviewPanel.jsx
  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
  • packages/web/src/components/checklist/pdf/pdfVirtualization.js
  • packages/web/src/components/checklist/pdf/PdfViewer.jsx
📚 Learning: 2025-12-27T03:02:05.951Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/pdf-handling.mdc:0-0
Timestamp: 2025-12-27T03:02:05.951Z
Learning: Applies to packages/web/src/**/*.{js,jsx,ts,tsx} : Use `pdfPreviewStore` from `@/stores/pdfPreviewStore.js` for managing PDF preview state (openPreview, closePreview, getPreview methods)

Applied to files:

  • packages/web/src/config/pdfViewer.js
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/package.json
  • packages/web/src/components/project/PdfPreviewPanel.jsx
  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
  • packages/web/src/components/checklist/pdf/pdfVirtualization.js
  • packages/web/src/components/checklist/pdf/PdfViewer.jsx
📚 Learning: 2025-12-27T03:02:05.951Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/pdf-handling.mdc:0-0
Timestamp: 2025-12-27T03:02:05.951Z
Learning: Applies to packages/web/src/**/*.{js,jsx,ts,tsx} : Use `cachePdf` and `getCachedPdf` from `primitives/pdfCache.js` for caching PDF data in IndexedDB

Applied to files:

  • packages/web/src/config/pdfViewer.js
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/package.json
  • packages/web/src/components/project/PdfPreviewPanel.jsx
  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
  • packages/web/src/components/checklist/pdf/pdfVirtualization.js
  • packages/web/src/components/checklist/pdf/PdfViewer.jsx
📚 Learning: 2025-12-27T03:02:05.951Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/pdf-handling.mdc:0-0
Timestamp: 2025-12-27T03:02:05.951Z
Learning: Applies to packages/web/src/**/*.{js,jsx,ts,tsx} : Use PDF operations from `useProject` hook instead of bypassing through direct API calls

Applied to files:

  • packages/web/src/config/pdfViewer.js
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/package.json
  • packages/web/src/components/project/PdfPreviewPanel.jsx
  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
  • packages/web/src/components/checklist/pdf/pdfVirtualization.js
  • packages/web/src/components/checklist/pdf/PdfViewer.jsx
📚 Learning: 2025-12-27T03:02:05.951Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/pdf-handling.mdc:0-0
Timestamp: 2025-12-27T03:02:05.951Z
Learning: Applies to packages/web/src/**/*.{js,jsx,ts,tsx} : Store only PDF metadata in Yjs (id, name, size, tag, uploadedAt, uploadedBy), never store PDF binary data in Yjs as it is too large

Applied to files:

  • packages/web/src/config/pdfViewer.js
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/package.json
  • packages/web/src/components/checklist/pdf/PdfViewer.jsx
📚 Learning: 2025-12-27T03:02:05.951Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/pdf-handling.mdc:0-0
Timestamp: 2025-12-27T03:02:05.951Z
Learning: Applies to packages/web/src/**/*.{js,jsx,ts,tsx} : Implement PDF caching strategy: check cache first, download from server if not cached, then cache the downloaded PDF

Applied to files:

  • packages/web/src/config/pdfViewer.js
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
  • packages/web/src/components/checklist/pdf/pdfVirtualization.js
  • packages/web/src/components/checklist/pdf/PdfViewer.jsx
📚 Learning: 2025-12-27T03:02:05.951Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/pdf-handling.mdc:0-0
Timestamp: 2025-12-27T03:02:05.951Z
Learning: Applies to packages/web/src/**/*.{js,jsx,ts,tsx} : Validate PDF files on frontend by checking file.type includes 'pdf' and file.size is within MAX_PDF_SIZE limit (full validation is done on backend)

Applied to files:

  • packages/web/src/config/pdfViewer.js
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/checklist/pdf/pdfVirtualization.js
  • packages/web/src/components/checklist/pdf/PdfViewer.jsx
📚 Learning: 2026-01-01T23:32:06.083Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/corates.mdc:0-0
Timestamp: 2026-01-01T23:32:06.083Z
Learning: Applies to packages/workers/**/*.{js,ts} : Use Drizzle ORM for ALL database interactions and migrations

Applied to files:

  • packages/workers/scripts/README.md
  • packages/workers/package.json
  • packages/workers/scripts/reset-db-prod.mjs
📚 Learning: 2025-12-27T15:42:01.079Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-27T15:42:01.079Z
Learning: Applies to packages/workers/**/*.{ts,tsx} : Use Drizzle ORM for ALL database interactions and migrations

Applied to files:

  • packages/workers/scripts/README.md
  • packages/workers/package.json
  • packages/workers/scripts/reset-db-prod.mjs
📚 Learning: 2025-12-27T15:42:01.079Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-27T15:42:01.079Z
Learning: Applies to packages/workers/**/*.{ts,sql} : Use DrizzleKit to generate new migrations when necessary

Applied to files:

  • packages/workers/scripts/README.md
  • packages/workers/scripts/generate-test-sql.mjs
  • packages/workers/package.json
  • packages/workers/scripts/reset-db-prod.mjs
📚 Learning: 2025-12-27T03:01:45.070Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/error-handling.mdc:0-0
Timestamp: 2025-12-27T03:01:45.070Z
Learning: Applies to packages/workers/**/!(*.test|*.spec).{js,ts,jsx,tsx} : Wrap database operations in try-catch blocks and return domain errors using `createDomainError(SYSTEM_ERRORS.DB_ERROR, ...)` with operation metadata

Applied to files:

  • packages/workers/scripts/README.md
  • packages/workers/scripts/generate-test-sql.mjs
  • packages/workers/package.json
  • packages/workers/scripts/reset-db-prod.mjs
📚 Learning: 2026-01-01T23:32:23.479Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/workers.mdc:0-0
Timestamp: 2026-01-01T23:32:23.479Z
Learning: Applies to packages/workers/src/**/*.{js,ts,jsx,tsx} : ALWAYS use `db.batch()` for multiple related database operations in Drizzle to ensure atomicity - all operations must succeed or all fail together

Applied to files:

  • packages/workers/scripts/README.md
  • packages/workers/package.json
  • packages/workers/scripts/reset-db-prod.mjs
📚 Learning: 2025-12-27T15:42:01.079Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-12-27T15:42:01.079Z
Learning: Applies to packages/workers/**/*.sql : Do NOT create separate migration files manually - use DrizzleKit instead

Applied to files:

  • packages/workers/scripts/README.md
  • packages/workers/scripts/generate-test-sql.mjs
  • packages/workers/package.json
  • packages/workers/scripts/reset-db-prod.mjs
📚 Learning: 2026-01-01T23:31:43.748Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/api-routes.mdc:0-0
Timestamp: 2026-01-01T23:31:43.748Z
Learning: Applies to packages/workers/src/routes/**/*.js : Use `db.batch()` for related database operations that must be atomic

Applied to files:

  • packages/workers/scripts/README.md
📚 Learning: 2026-01-01T23:32:06.083Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/corates.mdc:0-0
Timestamp: 2026-01-01T23:32:06.083Z
Learning: Applies to packages/workers/**/*.sql : Use DrizzleKit to generate new migrations when necessary

Applied to files:

  • packages/workers/scripts/README.md
  • packages/workers/scripts/generate-test-sql.mjs
  • packages/workers/package.json
  • packages/workers/scripts/reset-db-prod.mjs
📚 Learning: 2026-01-01T23:32:06.083Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/corates.mdc:0-0
Timestamp: 2026-01-01T23:32:06.083Z
Learning: Applies to packages/workers/**/*.sql : Do NOT create separate migration files manually (0002_xxx.sql, etc.) - use DrizzleKit instead

Applied to files:

  • packages/workers/scripts/generate-test-sql.mjs
  • packages/workers/package.json
  • packages/workers/scripts/reset-db-prod.mjs
📚 Learning: 2026-01-01T23:31:43.748Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/api-routes.mdc:0-0
Timestamp: 2026-01-01T23:31:43.748Z
Learning: Applies to packages/workers/src/routes/**/*.js : Always create DB client from environment using `createDb` function in route handlers

Applied to files:

  • packages/workers/package.json
📚 Learning: 2026-01-01T23:31:43.748Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/api-routes.mdc:0-0
Timestamp: 2026-01-01T23:31:43.748Z
Learning: Applies to packages/workers/src/routes/**/*.js : Always use Drizzle ORM with query builders - never use raw SQL in database operations

Applied to files:

  • packages/workers/package.json
📚 Learning: 2025-12-27T03:02:14.854Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/reconciliation.mdc:0-0
Timestamp: 2025-12-27T03:02:14.854Z
Learning: Applies to {packages/web/src/components/checklist-ui/compare/**,packages/web/src/AMSTAR2/checklist-compare.js} : Use compareChecklists utility from checklist-compare.js for comparing reviewer checklists

Applied to files:

  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/src/components/project/PdfPreviewPanel.jsx
  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
  • packages/web/src/components/checklist/SplitScreenLayout.jsx
📚 Learning: 2025-12-27T03:02:05.951Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/pdf-handling.mdc:0-0
Timestamp: 2025-12-27T03:02:05.951Z
Learning: Applies to packages/web/src/**/*.{js,jsx,ts,tsx} : Use `addPdfToStudy` operation from `useProject` hook to add PDFs to a study, passing id, name, size, tag, uploadedAt, and uploadedBy

Applied to files:

  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/package.json
📚 Learning: 2025-12-27T03:02:26.947Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/solidjs.mdc:0-0
Timestamp: 2025-12-27T03:02:26.947Z
Learning: Applies to {packages/web/**,packages/landing/**}/**/*.{jsx,tsx} : Use Solid's Show component for conditional rendering instead of ternary operators

Applied to files:

  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx
  • packages/web/src/components/project/PdfPreviewPanel.jsx
  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
  • packages/web/src/components/checklist/SplitScreenLayout.jsx
📚 Learning: 2025-12-27T03:02:05.951Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/pdf-handling.mdc:0-0
Timestamp: 2025-12-27T03:02:05.951Z
Learning: Applies to packages/web/src/**/*.{js,jsx,ts,tsx} : Always use `uploadPdf` from `api/pdf-api.js` for uploading PDF files. Pass object with projectId, studyId, tag ('primary' or 'supplementary'), and fileName

Applied to files:

  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/package.json
📚 Learning: 2025-12-27T03:02:05.951Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/pdf-handling.mdc:0-0
Timestamp: 2025-12-27T03:02:05.951Z
Learning: Applies to packages/web/src/**/*.{js,jsx,ts,tsx} : Use `removePdfFromStudy` operation from `useProject` hook to remove PDFs from a study

Applied to files:

  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
📚 Learning: 2025-12-27T03:02:05.951Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/pdf-handling.mdc:0-0
Timestamp: 2025-12-27T03:02:05.951Z
Learning: Applies to packages/web/src/**/*.{js,jsx,ts,tsx} : Use `downloadPdf` from `api/pdf-api.js` to download PDFs from server, then cache the result using `cachePdf`

Applied to files:

  • packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx
  • packages/web/package.json
  • packages/web/src/components/project/PdfPreviewPanel.jsx
  • packages/web/src/components/checklist/pdf/pdfVirtualization.js
📚 Learning: 2025-12-27T03:01:54.727Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/form-state.mdc:0-0
Timestamp: 2025-12-27T03:01:54.727Z
Learning: Applies to packages/web/src/components/project-ui/**/*.{js,jsx} : Form state should include serializable metadata when handling files (name, size, type) and use the store's pendingPdfs pattern for actual File objects that persist across redirects

Applied to files:

  • packages/web/src/components/project/PdfPreviewPanel.jsx
📚 Learning: 2025-12-27T03:02:26.947Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/solidjs.mdc:0-0
Timestamp: 2025-12-27T03:02:26.947Z
Learning: Applies to {packages/web/**,packages/landing/**}/**/*.{js,jsx,ts,tsx} : Prefer derived state with createMemo or signals over effects whenever possible

Applied to files:

  • packages/web/src/components/project/PdfPreviewPanel.jsx
📚 Learning: 2025-12-27T03:02:26.947Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/solidjs.mdc:0-0
Timestamp: 2025-12-27T03:02:26.947Z
Learning: Applies to {packages/web/**,packages/landing/**}/**/*.{jsx,tsx} : Keep SolidJS components lean and focused on rendering - move business logic to stores, primitives, or utilities

Applied to files:

  • packages/web/src/components/project/PdfPreviewPanel.jsx
  • packages/web/src/components/checklist/SplitScreenLayout.jsx
📚 Learning: 2025-12-27T03:02:26.947Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/solidjs.mdc:0-0
Timestamp: 2025-12-27T03:02:26.947Z
Learning: Applies to {packages/web/**,packages/landing/**}/**/*.{js,jsx,ts,tsx} : Use createMemo for computed/derived values that depend on reactive state in SolidJS

Applied to files:

  • packages/web/src/components/project/PdfPreviewPanel.jsx
📚 Learning: 2026-01-01T23:32:06.083Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/corates.mdc:0-0
Timestamp: 2026-01-01T23:32:06.083Z
Learning: Applies to packages/web/**/*.{jsx,tsx} : Use `createMemo` for derived values in SolidJS

Applied to files:

  • packages/web/src/components/project/PdfPreviewPanel.jsx
📚 Learning: 2025-12-27T03:01:06.933Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/checklist-operations.mdc:0-0
Timestamp: 2025-12-27T03:01:06.933Z
Learning: Applies to packages/web/src/components/checklist-ui/**,packages/web/src/AMSTAR2/**,packages/web/src/ROBINS-I/**,packages/web/src/lib/checklist-domain.js,packages/web/src/primitives/useProject/checklists.js : Use checklist operations from useProject hook (createChecklist, updateChecklistAnswer, getChecklistData) instead of manually updating checklist structure

Applied to files:

  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
  • packages/web/src/components/checklist/SplitScreenLayout.jsx
📚 Learning: 2025-12-27T03:01:06.933Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/checklist-operations.mdc:0-0
Timestamp: 2025-12-27T03:01:06.933Z
Learning: Applies to packages/web/src/components/checklist-ui/** : Use NoteEditor component from @/components/checklist-ui/common/NoteEditor.jsx for question note editing with max 2000 character limit

Applied to files:

  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
📚 Learning: 2025-12-27T03:01:06.933Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/checklist-operations.mdc:0-0
Timestamp: 2025-12-27T03:01:06.933Z
Learning: Applies to packages/web/src/components/checklist-ui/**,packages/web/src/primitives/useProject/checklists.js : Store question notes as Y.Text objects obtained from useProject hook via getQuestionNote operation to enable collaborative editing

Applied to files:

  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
📚 Learning: 2025-12-27T03:02:14.854Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/reconciliation.mdc:0-0
Timestamp: 2025-12-27T03:02:14.854Z
Learning: Applies to packages/web/src/components/checklist-ui/compare/** : Use Y.Text objects for collaborative editing of question notes in reconciliation

Applied to files:

  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
📚 Learning: 2025-12-27T03:01:06.933Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/checklist-operations.mdc:0-0
Timestamp: 2025-12-27T03:01:06.933Z
Learning: Applies to packages/web/src/components/checklist-ui/**,packages/web/src/AMSTAR2/**,packages/web/src/ROBINS-I/**,packages/web/src/lib/checklist-domain.js : Use getChecklistStatus utility from @/lib/checklist-domain.js to determine current checklist status before performing operations

Applied to files:

  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
📚 Learning: 2025-12-27T03:01:06.933Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/checklist-operations.mdc:0-0
Timestamp: 2025-12-27T03:01:06.933Z
Learning: Applies to packages/web/src/components/checklist-ui/**,packages/web/src/lib/checklist-domain.js : Register and retrieve checklists using checklist-registry: getChecklistType and getChecklistComponent functions

Applied to files:

  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
📚 Learning: 2025-12-27T03:01:06.933Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/checklist-operations.mdc:0-0
Timestamp: 2025-12-27T03:01:06.933Z
Learning: Applies to packages/web/src/components/checklist-ui/**,packages/web/src/AMSTAR2/** : Use scoreChecklist utility from @/AMSTAR2/checklist.js to determine quality assessment rating: 'High' | 'Moderate' | 'Low' | 'Critically Low'

Applied to files:

  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
📚 Learning: 2025-12-27T03:01:06.933Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/checklist-operations.mdc:0-0
Timestamp: 2025-12-27T03:01:06.933Z
Learning: Applies to packages/web/src/components/checklist-ui/**,packages/web/src/AMSTAR2/**,packages/web/src/ROBINS-I/**,packages/web/src/lib/checklist-domain.js : Maintain separate answer format implementations for each checklist type (AMSTAR2, ROBINS-I, Generic) to prevent data corruption

Applied to files:

  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
📚 Learning: 2025-12-27T03:01:06.933Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/checklist-operations.mdc:0-0
Timestamp: 2025-12-27T03:01:06.933Z
Learning: Applies to packages/web/src/components/checklist-ui/**,packages/web/src/ROBINS-I/** : Use scoreChecklist utility from @/ROBINS-I/checklist.js to determine risk of bias rating: 'Low' | 'Moderate' | 'Serious' | 'Critical'

Applied to files:

  • packages/web/src/components/checklist/ChecklistWithPdf.jsx
📚 Learning: 2025-12-27T03:02:26.947Z
Learnt from: CR
Repo: InfinityBowman/corates PR: 0
File: .cursor/rules/solidjs.mdc:0-0
Timestamp: 2025-12-27T03:02:26.947Z
Learning: Applies to {packages/web/**,packages/landing/**}/**/*.{jsx,tsx} : Use the children helper when manipulating props.children in SolidJS components

Applied to files:

  • packages/web/src/components/checklist/SplitScreenLayout.jsx
🧬 Code graph analysis (4)
packages/workers/scripts/generate-test-sql.mjs (2)
packages/workers/scripts/reset-db-prod.mjs (1)
  • __dirname (13-13)
packages/workers/scripts/generate-openapi.mjs (1)
  • __dirname (16-16)
packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx (3)
packages/web/src/config/pdfViewer.js (2)
  • PDF_VIEWER_MODE (9-9)
  • PDF_VIEWER_MODE (9-9)
packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx (1)
  • EmbedPdfViewerSnippet (14-329)
packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx (1)
  • EmbedPdfViewerPdfJs (8-13)
packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx (1)
packages/web/src/components/checklist/pdf/PdfViewer.jsx (1)
  • PdfViewer (31-120)
packages/web/src/components/project/PdfPreviewPanel.jsx (2)
packages/web/src/stores/pdfPreviewStore.js (1)
  • pdfPreviewStore (69-84)
packages/web/src/components/checklist/pdf/PdfViewer.jsx (1)
  • PdfViewer (31-120)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Workers Builds: corates

Comment thread .gitignore
.wrangler
.turbo
/reference
reference/
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check for any reference directories in the repository
echo "=== All reference directories ==="
fd --type d --full-path 'reference$' --exclude node_modules --exclude .git 2>/dev/null || echo "No reference directories found"

echo ""
echo "=== Current .gitignore content (around line 13) ==="
if [ -f .gitignore ]; then
  sed -n '10,16p' .gitignore
fi

Repository: InfinityBowman/corates

Length of output: 216


🏁 Script executed:

#!/bin/bash
# Check git history for .gitignore changes
echo "=== Recent .gitignore changes ==="
git log --oneline -n 20 -- .gitignore

echo ""
echo "=== Previous .gitignore content (showing reference pattern) ==="
git log -p -- .gitignore | grep -A 5 -B 5 'reference' | head -30

echo ""
echo "=== Commit that modified the reference pattern ==="
git log -p -- .gitignore | grep -B 20 'reference/' | grep -E '^\+reference/|^-/reference|^commit|^Author' | head -20

Repository: InfinityBowman/corates

Length of output: 297


Verify whether the reference directory ignore pattern change was intentional.

The pattern reference/ (matches any level) is technically broader than /reference (root-only), as noted. However, no reference/ directories currently exist in the repository that would be newly ignored by this change. If this broadening was unintentional, it should be reverted to /reference; if intentional to catch future reference/ directories at any level, the broader pattern is acceptable.

🤖 Prompt for AI Agents
.gitignore around line 13: the entry "reference/" is broader than the root-only
pattern "/reference" and may unintentionally ignore any nested reference/
directories; confirm whether the broader match was intended — if it was
unintentional, change the line back to "/reference" and commit the revert; if it
was intentional, keep "reference/" but add a brief comment above explaining the
reason (or update repo documentation) so future contributors understand why
nested reference/ dirs should be ignored.

Comment thread packages/web/package.json Outdated
"analyze": "vite build --mode analyze && source-map-explorer dist/assets/index-*.js --no-border-checks"
},
"dependencies": {
"@corates/embedpdf-solid": "workspace:*",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Verify the embedpdf-solid workspace package exists and has proper exports

# Check if the workspace package directory exists
if [ -d "packages/embedpdf-solid" ]; then
  echo "=== embedpdf-solid package found ==="
  cat packages/embedpdf-solid/package.json | jq '{name, version, exports, main}'
  
  echo ""
  echo "=== Checking for component exports ==="
  fd --type f '\.(jsx?|tsx?)$' packages/embedpdf-solid/src -x echo {}
else
  echo "ERROR: packages/embedpdf-solid directory not found in workspace"
  exit 1
fi

echo ""
echo "=== Checking usage in web package ==="
rg --type ts --type tsx -C3 "@corates/embedpdf-solid" packages/web/src

Repository: InfinityBowman/corates

Length of output: 129


🏁 Script executed:

#!/bin/bash
# List all packages in the workspace
echo "=== Packages in workspace ==="
ls -la packages/

echo ""
echo "=== Searching for embedpdf-solid references in codebase ==="
rg "embedpdf-solid" --type json --type ts --type tsx --type js

echo ""
echo "=== Checking package.json workspace configuration ==="
cat pnpm-workspace.yaml 2>/dev/null || cat lerna.json 2>/dev/null || echo "No workspace config found"

echo ""
echo "=== Checking for pdf-related packages ==="
ls -la packages/ | grep -i pdf

Repository: InfinityBowman/corates

Length of output: 902


🏁 Script executed:

#!/bin/bash
echo "=== Checking for import attempts in web package ==="
rg "embedpdf-solid|from.*embedpdf" packages/web/src/ --type ts --type tsx --type js

echo ""
echo "=== Full web package.json content ==="
cat packages/web/package.json

Repository: InfinityBowman/corates

Length of output: 2068


Remove unused workspace dependency or create the missing package.

The dependency @corates/embedpdf-solid was added to packages/web/package.json but the package does not exist in the monorepo (no packages/embedpdf-solid directory found), and there are no imports of this package anywhere in the codebase. The workspace:* reference will cause install failures. Either remove this dependency if it's not needed, or ensure the packages/embedpdf-solid package is created and properly exported as part of this PR.

🤖 Prompt for AI Agents
In packages/web/package.json at line 20, the workspace dependency
"@corates/embedpdf-solid": "workspace:*" references a package that doesn't exist
in the monorepo and causes install failures; remove this dependency from
package.json if the package is not needed, or instead add a new package under
packages/embedpdf-solid with a valid package.json and exports, and update any
imports to reference it; ensure workspace entries and the root
package.json/lerna/yarn workspaces config are updated and that CI installs
successfully.

Comment thread packages/web/package.json Outdated
Comment on lines +23 to +30
"@embedpdf/core": "^2.1.1",
"@embedpdf/engines": "^2.1.1",
"@embedpdf/models": "^2.1.1",
"@embedpdf/plugin-document-manager": "^2.1.1",
"@embedpdf/plugin-render": "^2.1.1",
"@embedpdf/plugin-scroll": "^2.1.1",
"@embedpdf/plugin-viewport": "^2.1.1",
"@embedpdf/snippet": "^2.0.0",
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

@embedpdf/core npm package version 2.1.1

💡 Result:

I couldn't find an @embedpdf/core v2.1.1 on npm. The official npm package page lists version 1.0.26 as the current published version. [1]

There are other EmbedPDF packages (e.g., @embedpdf/pdfium, some plugins) with versions 2.1.1, but not @embedpdf/core. [2][3]

Sources:

  • npm page for @embedpdf/core. [1]
  • jsDelivr listing for @embedpdf/pdfium (example of a different package at v2.1.1). [2]
  • package metadata summary showing other @embedpdf packages/versions. [3]

Would you like me to watch for a @embedpdf/core v2.1.1 release and notify you?


🌐 Web query:

@embedpdf/engines npm package version 2.1.1

💡 Result:

I couldn't find a published @embedpdf/engines version 2.1.1 on npm. The npm package currently shows version 1.0.20 (most recent publish info on the npm page), and third‑party trackers list recent releases in the 1.x range. [1][2]

If you want, I can:

  • check again for a specific publish date or tarball URL, or
  • search the package's GitHub releases/tags for a 2.1.1 tag.

🌐 Web query:

@embedpdf/snippet npm package security vulnerabilities

💡 Result:

I found no public security advisories specifically for the npm package @embedpdf/snippet (no entries in Snyk’s database or on EmbedPDF’s GitHub/docs pages). Sources checked: EmbedPDF docs, the project GitHub, jsDelivr/npm metadata and Snyk scans. [1][2][3][4]

If you’re using the package I recommend: run npm audit / yarn audit on your project, scan with Snyk or GitHub Dependabot, and review the package’s dependencies and changelog for recent fixes.

Sources:

  • EmbedPDF Snippet docs (package usage). [1]
  • EmbedPDF GitHub organization / embed-pdf-viewer repo. [2]
  • jsDelivr/npm listing for @embedpdf/snippet. [3]
  • Snyk package search (no direct vulnerabilities reported). [4]

🌐 Web query:

embedpdf npm security advisories CVE

💡 Result:

I couldn’t find any public CVE or security advisory specifically for the "embedpdf" or @embedpdf/* packages. npm listings/security scanners show package pages but no CVE entries for those packages. [1]

There are, however, known CVEs affecting other PDF-related npm packages (example: node-qpdf — CVE-2023-26155). If you use any PDF-processing/npm PDF libraries in your project, scan them too. [2][3]

Actions I recommend:

  • Run npm audit (or Snyk/Dependabot) against your project to detect known advisories.
  • If you want, tell me the exact package name/version you use and I’ll run targeted checks.

Sources:


The specified EmbedPDF package versions do not exist on npm and will cause installation failures.

@embedpdf/core v2.1.1 does not exist (current: 1.0.26) and @embedpdf/engines v2.1.1 does not exist (current: 1.x range). Correct these versions before merging. The other @embedpdf packages at ^2.1.1 should also be verified against npm registry. No public security advisories were found for @embedpdf packages.

🤖 Prompt for AI Agents
packages/web/package.json lines 23-30: the pinned @embedpdf/* versions (e.g.
@embedpdf/core @embedpdf/engines and others set to ^2.1.1) do not exist on npm
and will break installs; inspect the npm registry (npm view <pkg> version or npm
info) for each @embedpdf package and replace the non-existent versions with the
correct published versions (for example set @embedpdf/core to 1.0.26 and
@embedpdf/engines to a published 1.x range if that matches the registry), or
change them to a valid semver range (e.g. ^1.x) or to workspace/local paths if
you intended to use unpublished packages; ensure all @embedpdf entries are
updated consistently and run npm install to confirm resolution.

Comment on lines +75 to +79
<EmbedPdfViewer
pdfData={props.pdfData}
pdfFileName={props.pdfFileName}
readOnly={props.readOnly}
/>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find the EmbedPdfViewer component file and examine its function signature
fd -t f 'EmbedPdfViewer.jsx' packages/web/src/

Repository: InfinityBowman/corates

Length of output: 131


🏁 Script executed:

#!/bin/bash
# Find the PdfViewer component file and examine its function signature
fd -t f 'PdfViewer.jsx' packages/web/src/

Repository: InfinityBowman/corates

Length of output: 187


🏁 Script executed:

#!/bin/bash
# Examine the EmbedPdfViewer component definition
cat -n packages/web/src/components/checklist/embedpdf/EmbedPdfViewer.jsx

Repository: InfinityBowman/corates

Length of output: 1587


🏁 Script executed:

#!/bin/bash
# Examine the PdfViewer component definition - get first 100 lines to see function signature and props
head -100 packages/web/src/components/checklist-ui/pdf/PdfViewer.jsx

Repository: InfinityBowman/corates

Length of output: 183


🏁 Script executed:

#!/bin/bash
# Check the ChecklistWithPdf.jsx file around lines 75-79 for context
sed -n '60,90p' packages/web/src/components/checklist/ChecklistWithPdf.jsx

Repository: InfinityBowman/corates

Length of output: 783


🏁 Script executed:

#!/bin/bash
# Find and examine PdfViewer component in correct location
head -80 packages/web/src/components/checklist/pdf/PdfViewer.jsx

Repository: InfinityBowman/corates

Length of output: 3171


🏁 Script executed:

#!/bin/bash
# Check the EmbedPdfViewerSnippet implementation to see what it supports
head -80 packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx

Repository: InfinityBowman/corates

Length of output: 2678


Document the intentional feature gap between EmbedPdfViewer and PdfViewer modes.

The feature disparity between EmbedPdfViewer and PdfViewer is confirmed. EmbedPdfViewer supports only basic viewing (pdfData, pdfFileName, readOnly), while PdfViewer supports multi-PDF management (onPdfChange, onPdfClear, allowDelete, pdfs, selectedPdfId, onPdfSelect). This appears to be intentional design—the EmbedPdfViewerSnippet implementation relies on the third-party @embedpdf/snippet library which is a simplified viewer. Consider adding:

  • A comment in EmbedPdfViewer explaining why the snippet viewer has limited features
  • Documentation distinguishing the capabilities of each mode
  • Feature flags or validation to disable snippet mode when features like multi-PDF selection or delete are required
🤖 Prompt for AI Agents
In packages/web/src/components/checklist/ChecklistWithPdf.jsx around lines 75 to
79, the review notes an intentional feature gap between EmbedPdfViewer (basic
snippet viewer: pdfData, pdfFileName, readOnly) and PdfViewer (full-featured:
multi-PDF, onPdfChange/onPdfClear, allowDelete, pdfs, selectedPdfId,
onPdfSelect); add a short comment inside the EmbedPdfViewer component explaining
that it uses the @embedpdf/snippet library and therefore intentionally supports
only basic viewing, update component-level documentation (README or JSDoc) to
clearly list capabilities of EmbedPdfViewer vs PdfViewer, and add runtime
validation or a simple prop-check in ChecklistWithPdf to warn/throw or
automatically select PdfViewer when multi-PDF or delete/select props are passed
(or introduce a feature flag) so callers cannot accidentally rely on unsupported
features.

Comment on lines +8 to +12
export default function EmbedPdfViewerPdfJs(props) {
// props.pdfData - ArrayBuffer of PDF data (required)
// props.pdfFileName - Name of the PDF file (optional, for display)

return <PdfViewer pdfData={props.pdfData} pdfFileName={props.pdfFileName} />;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Missing readOnly prop forwarding creates inconsistent behavior.

The EmbedPdfViewer parent passes readOnly to EmbedPdfViewerSnippet but not to this component. However, if this wrapper is meant to be interchangeable with the snippet viewer, it should also respect readOnly to ensure consistent behavior across viewer modes.

Based on learnings, the PdfViewer component accepts readOnly as a prop.

Proposed fix
 export default function EmbedPdfViewerPdfJs(props) {
   // props.pdfData - ArrayBuffer of PDF data (required)
   // props.pdfFileName - Name of the PDF file (optional, for display)
+  // props.readOnly - If true, view only mode (optional)

-  return <PdfViewer pdfData={props.pdfData} pdfFileName={props.pdfFileName} />;
+  return <PdfViewer pdfData={props.pdfData} pdfFileName={props.pdfFileName} readOnly={props.readOnly} />;
 }

Also update EmbedPdfViewer.jsx Line 34 to pass readOnly:

-        <EmbedPdfViewerPdfJs pdfData={props.pdfData} pdfFileName={props.pdfFileName} />
+        <EmbedPdfViewerPdfJs pdfData={props.pdfData} pdfFileName={props.pdfFileName} readOnly={props.readOnly} />
🤖 Prompt for AI Agents
In packages/web/src/components/checklist/embedpdf/EmbedPdfViewerPdfJs.jsx around
lines 8-12, the wrapper does not forward the readOnly prop to PdfViewer which
causes inconsistent behavior with other viewers; update the component to pass
props.readOnly into the PdfViewer call (i.e., include readOnly={props.readOnly}
when rendering PdfViewer) and also ensure the parent EmbedPdfViewer.jsx (around
line 34) is updated to pass its readOnly prop down to this wrapper so readOnly
flows from parent to PdfViewer.

Comment on lines +25 to +32
// Create blob URL from pdfData
const blobUrl = createMemo(() => {
const pdfData = props.pdfData;
if (!pdfData) return null;

const blob = new Blob([pdfData], { type: 'application/pdf' });
return URL.createObjectURL(blob);
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Potential blob URL memory leak on pdfData changes.

When pdfData changes, createMemo creates a new blob URL, but the previous blob URL from the memo is not revoked. The destroyViewer function only revokes currentBlobUrl (the one actively used by the viewer), not the one held in the memo's reactive closure.

Consider using createEffect with cleanup instead of createMemo for blob URL management, or track the previous URL for explicit revocation.

Proposed approach using createEffect with cleanup
-  // Create blob URL from pdfData
-  const blobUrl = createMemo(() => {
-    const pdfData = props.pdfData;
-    if (!pdfData) return null;
-
-    const blob = new Blob([pdfData], { type: 'application/pdf' });
-    return URL.createObjectURL(blob);
-  });
+  // Create blob URL from pdfData with proper cleanup
+  const [blobUrl, setBlobUrl] = createSignal(null);
+  
+  createEffect(() => {
+    const pdfData = props.pdfData;
+    if (!pdfData) {
+      setBlobUrl(null);
+      return;
+    }
+    
+    const blob = new Blob([pdfData], { type: 'application/pdf' });
+    const url = URL.createObjectURL(blob);
+    setBlobUrl(url);
+    
+    onCleanup(() => {
+      URL.revokeObjectURL(url);
+    });
+  });

This ensures each blob URL is revoked when the effect re-runs or on unmount.

Comment on lines +187 to +246
viewerInstance.registry.then(registry => {
try {
const ui = registry.getPlugin('ui')?.provides();
if (ui) {
const schema = ui.getSchema();
const mainToolbar = schema.toolbars?.['main-toolbar'];

if (mainToolbar?.responsive?.breakpoints) {
const originalBreakpoints = mainToolbar.responsive.breakpoints;
// Adjust breakpoints to switch to mobile view at a larger width
// Preserve all show/hide arrays, only change the width thresholds
ui.mergeSchema({
toolbars: {
'main-toolbar': {
...mainToolbar,
responsive: {
...mainToolbar.responsive,
breakpoints: {
...originalBreakpoints,
// Adjust xs breakpoint: keep original, mobile view will start later
xs:
originalBreakpoints.xs ?
{
...originalBreakpoints.xs,
}
: originalBreakpoints.xs,
// Adjust sm breakpoint: mobile view now starts at 400px instead of 640px
// This means desktop mode stays active on smaller screens (until < 400px)
sm:
originalBreakpoints.sm ?
{
minWidth: 400, // Changed from 640 to 400 (desktop mode stays on smaller screens)
maxWidth: 768, // Keep maxWidth at 768
// Preserve the original show/hide arrays to keep buttons visible
hide: originalBreakpoints.sm.hide || [],
show: originalBreakpoints.sm.show || [],
}
: originalBreakpoints.sm,
// Adjust md breakpoint: desktop view now starts at 640px instead of 768px
// This means desktop mode comes earlier (at smaller screen sizes)
md:
originalBreakpoints.md ?
{
minWidth: 640, // Changed from 768 to 640 (desktop mode comes earlier)
// Preserve the original show/hide arrays
hide: originalBreakpoints.md.hide || [],
show: originalBreakpoints.md.show || [],
}
: originalBreakpoints.md,
},
},
},
},
});
}
}
} catch (err) {
console.warn('Failed to customize breakpoints:', err);
}
});
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Potential race condition with async registry.then() callback.

If the effect re-runs (e.g., pdfData changes) while the viewerInstance.registry.then() promise is still pending, the callback may execute on a stale/destroyed viewer instance. The viewerInstance captured in the closure may have been nullified by destroyViewer().

Consider tracking a cancellation token or verifying the instance is still current before modifying the schema.

Proposed fix
+        // Capture current instance for closure
+        const currentInstance = viewerInstance;
+
         // Customize responsive breakpoints after initialization
         // Adjust mobile view threshold (default is 640px for sm breakpoint)
-        viewerInstance.registry.then(registry => {
+        currentInstance.registry.then(registry => {
           try {
+            // Verify this is still the active instance
+            if (viewerInstance !== currentInstance) return;
+            
             const ui = registry.getPlugin('ui')?.provides();
             if (ui) {
               // ... rest of the code
             }
           } catch (err) {
             console.warn('Failed to customize breakpoints:', err);
           }
         });
🤖 Prompt for AI Agents
In packages/web/src/components/checklist/embedpdf/EmbedPdfViewerSnippet.jsx
around lines 187 to 246, the registry.then() callback can run after the
component has re-rendered or the viewer has been destroyed, causing schema
modifications on a stale instance; capture a cancellation token or a local
instance id before awaiting registry, then before calling ui.mergeSchema verify
the token/id still matches the current viewer (and that viewerInstance is
non-null and not destroyed); implement a cleanup that increments/invalidates the
token when destroying/recreating the viewer so the callback skips applying the
schema if stale.

Comment on lines +115 to +119
// Also drop migration tracking tables if they exist
// Wrangler D1 stores migration history in system tables
console.log(' Dropping migration tracking tables...');
runWranglerD1Execute(`DROP TABLE IF EXISTS __drizzle_migrations;`, { allowFailure: true });
runWranglerD1Execute(`DROP TABLE IF EXISTS _cf_KV;`, { allowFailure: true });
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Dropping __drizzle_migrations breaks migration tracking.

Drizzle ORM uses __drizzle_migrations to track which migrations have been applied. Dropping this table means the system loses all migration history. On the next migration run, Drizzle won't know which migrations were already applied, potentially causing:

  • Re-application of migrations (which will fail if tables already exist)
  • Inconsistent migration state between environments
  • Loss of migration audit trail
Recommended fix

Remove the lines that drop migration tracking tables. These should persist across resets to maintain migration history:

-    // Also drop migration tracking tables if they exist
-    // Wrangler D1 stores migration history in system tables
-    console.log('  Dropping migration tracking tables...');
-    runWranglerD1Execute(`DROP TABLE IF EXISTS __drizzle_migrations;`, { allowFailure: true });
-    runWranglerD1Execute(`DROP TABLE IF EXISTS _cf_KV;`, { allowFailure: true });

If you truly need to reset migration history, the proper workflow is:

  1. Drop all tables including __drizzle_migrations
  2. Run migrations with Drizzle, which will recreate __drizzle_migrations and record all migrations as applied

However, this is already happening in Step 3 (line 146), so these explicit drops are redundant and harmful.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Also drop migration tracking tables if they exist
// Wrangler D1 stores migration history in system tables
console.log(' Dropping migration tracking tables...');
runWranglerD1Execute(`DROP TABLE IF EXISTS __drizzle_migrations;`, { allowFailure: true });
runWranglerD1Execute(`DROP TABLE IF EXISTS _cf_KV;`, { allowFailure: true });
🤖 Prompt for AI Agents
In packages/workers/scripts/reset-db-prod.mjs around lines 115 to 119, the
script drops the __drizzle_migrations and _cf_KV tables which removes Drizzle's
migration history and breaks migration tracking; remove the runWranglerD1Execute
calls that drop __drizzle_migrations (and _cf_KV if it’s used for migration
tracking) so migration history is preserved, leaving table drops to the
controlled full-reset workflow (or ensure drops happen only in the explicit
full-reset sequence described in the comments around Step 3).

@InfinityBowman InfinityBowman merged commit bd0907a into main Jan 4, 2026
3 checks passed
@InfinityBowman InfinityBowman deleted the 209-embedpdf-viewer branch January 4, 2026 02:28
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.

EmbedPDF Viewer

2 participants