# visible-unknown/scribecrop architecture

> Architecture diagram of the GitHub repository visible-unknown/scribecrop, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-27). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/visible-unknown/scribecrop
- Repository: https://github.com/visible-unknown/scribecrop

## Overview

1. **Repository shape**
   - This is a two-target monorepo: `web/` contains the actual image-annotation application, and `desktop/` wraps the same app in Electron.
   - The root package primarily coordinates shared scripts for development and build, while the feature logic lives almost entirely in `web/src`.

2. **Primary product boundary: the web app**
   - The web application is a Next.js + React + TypeScript app.
   - It is the “source of truth” for the editor UI, canvas interaction, crop generation, previewing, and export.
   - The desktop app does not reimplement the editor; it loads the web build or local dev server.

3. **Desktop boundary: Electron shell**
   - `desktop/main.js` is the Electron main-process entry point.
   - Its role is to launch a native window around the web application, providing a desktop packaging/runtime layer rather than separate business logic.
   - This means the architecture is “web app first, desktop wrapper second,” not two independent clients.

4. **Application entry and layout**
   - In `web/src/app`, the Next.js App Router structure defines the top-level page and layout.
   - `layout.tsx`, `page.tsx`, and the CSS files establish the shell that contains the editor surface and supporting panels.
   - This is the UI composition boundary: everything else plugs into that page-level structure.

5. **Core editing subsystem**
   - `web/src/components/CanvasEditor.tsx` is the central interaction surface.
   - Based on the README and dependencies, this is where image regions are drawn, moved, resized, and rotated, likely using Konva for canvas scene management and transformer-style handles.
   - This component is the primary stateful boundary between user gestures and crop/annotation data.

6. **Image ingestion subsystem**
   - `web/src/components/Dropzone.tsx` and `web/src/hooks/useImage.ts` handle getting an image into the app.
   - The flow is: user selects or drops an image, the hook normalizes image loading/state, and the editor receives a usable source image plus metadata.
   - This boundary isolates file ingestion from the canvas/editor logic.

7. **Crop data and region management**
   - `web/src/types/index.ts` defines the shared domain model for things like crop regions, image state, and editor-related entities.
   - The crop regions are the central data structure linking drawing, preview, renaming, and export.
   - The README’s emphasis on rectangles, squares, circles, and polygons suggests the data model supports multiple annotation shapes rather than only simple rectangular crops.

8. **Preview and review subsystem**
   - `web/src/components/PreviewPanel.tsx` is the review layer for extracted regions.
   - It likely shows the generated crops, labels, and ordering before export, making it the user-facing validation step between canvas editing and file export.
   - This is a distinct boundary from the canvas: canvas edits the source image space, preview shows derived outputs.

9. **Crop generation utilities**
   - `web/src/utils/cropImage.ts` and `web/src/utils/exportCrops.ts` are the processing layer.
   - `cropImage` is responsible for turning a region definition plus source image into an actual cropped image representation.
   - `exportCrops` packages the set of generated crops into downloadable output, and the README indicates ZIP export is the intended final artifact.

10. **Naming and sequencing behavior**
   - The README’s “reactive renaming” capability implies the app maintains ordered crop metadata with prefix and numeric indexing.
   - This behavior is important architecturally because export names are not just labels; they are part of the processing pipeline and likely update live as crop order changes.
   - That makes naming a data transformation concern, not just a UI convenience.

11. **Data flow through the system**
   - Typical flow: image input → loaded image state → canvas annotations → derived crop regions → preview generation → ZIP/export package.
   - The crop regions are the handoff point between interactive editing and batch processing.
   - The preview/export stages depend on the editor state but do not need the full interactive canvas once regions are finalized.

12. **Styling and UI structure**
   - Styling is intentionally local and component-scoped via CSS Modules, with global styles only for app-wide baseline layout.
   - This keeps the editor, dropzone, and preview panel visually isolated, which matters in a tool-heavy interface with multiple panes.

13. **Tooling and runtime significance**
   - Next.js provides the web runtime and build/export pipeline; Electron provides desktop distribution; TypeScript adds shared model safety across components and utilities.
   - Konva is a key architectural dependency because the editor is canvas-driven rather than DOM-drawn.
   - Electron Builder is relevant only for packaging/distribution, not for the editor’s core runtime behavior.

14. **What to draw in an architecture diagram**
   - Show one central web application box containing: image input, canvas editor, preview panel, crop utilities, and export pipeline.
   - Show Electron as a thin outer host that launches the web app in desktop mode.
   - Emphasize the one-way flow from user input to derived crop artifacts, with crop metadata shared across editor, preview, and export subsystems.

Main entry points: [`web/src/app/page.tsx`](https://github.com/visible-unknown/scribecrop/blob/main/web/src/app/page.tsx) (App shell), [`web/src/components/CanvasEditor.tsx`](https://github.com/visible-unknown/scribecrop/blob/main/web/src/components/CanvasEditor.tsx) (Canvas editor), [`web/src/components/PreviewPanel.tsx`](https://github.com/visible-unknown/scribecrop/blob/main/web/src/components/PreviewPanel.tsx) (Preview panel), [`web/src/components/Dropzone.tsx`](https://github.com/visible-unknown/scribecrop/blob/main/web/src/components/Dropzone.tsx) (Dropzone)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_root["Root workspace"]
  node_root_pkg["Workspace<br/>monorepo scripts<br/>[package.json]"]
end

subgraph group_web["Web app"]
  node_web_shell["App shell<br/>next app router<br/>[page.tsx]"]
  node_web_layout["Layout<br/>[layout.tsx]"]
  node_canvas_editor["Canvas editor<br/>interactive editor<br/>[CanvasEditor.tsx]"]
  node_dropzone["Dropzone<br/>image ingress<br/>[Dropzone.tsx]"]
  node_use_image["Image hook<br/>image state<br/>[useImage.ts]"]
  node_types["Crop types<br/>domain model<br/>[index.ts]"]
  node_preview_panel["Preview panel<br/>[PreviewPanel.tsx]"]
  node_crop_image["Crop image<br/>processing util<br/>[cropImage.ts]"]
  node_export_crops["Export crops<br/>export util<br/>[exportCrops.ts]"]
  node_page_styles["Page styles<br/>css modules<br/>[page.module.css]"]
  node_editor_styles["Editor styles<br/>css modules"]
  node_dropzone_styles["Dropzone styles<br/>css modules"]
  node_preview_styles["Preview styles<br/>css modules"]
  node_globals_css["Global styles<br/>app css<br/>[globals.css]"]
  node_web_pkg["Web package<br/>next build<br/>[package.json]"]
end

subgraph group_desktop["Desktop shell"]
  node_electron_main["Electron main<br/>desktop host<br/>[main.js]"]
  node_desktop_pkg["Desktop package<br/>electron build<br/>[package.json]"]
end

node_root_pkg -->|"manages"| node_web_pkg
node_root_pkg -->|"manages"| node_desktop_pkg
node_desktop_pkg -->|"starts"| node_electron_main
node_electron_main -->|"hosts"| node_web_shell
node_web_shell -->|"composes"| node_web_layout
node_web_shell -->|"renders"| node_canvas_editor
node_web_shell -->|"renders"| node_dropzone
node_web_shell -->|"renders"| node_preview_panel
node_dropzone -->|"loads"| node_use_image
node_use_image -->|"uses"| node_types
node_canvas_editor -->|"uses"| node_types
node_preview_panel -->|"uses"| node_types
node_canvas_editor -->|"drives"| node_crop_image
node_crop_image -->|"feeds"| node_export_crops
node_preview_panel -->|"triggers"| node_export_crops
node_web_shell -->|"styles"| node_page_styles
node_canvas_editor -->|"styles"| node_editor_styles
node_dropzone -->|"styles"| node_dropzone_styles
node_preview_panel -->|"styles"| node_preview_styles
node_web_layout -->|"styles"| node_globals_css

click node_root_pkg "https://github.com/visible-unknown/scribecrop/blob/main/package.json"
click node_web_shell "https://github.com/visible-unknown/scribecrop/blob/main/web/src/app/page.tsx"
click node_web_layout "https://github.com/visible-unknown/scribecrop/blob/main/web/src/app/layout.tsx"
click node_canvas_editor "https://github.com/visible-unknown/scribecrop/blob/main/web/src/components/CanvasEditor.tsx"
click node_dropzone "https://github.com/visible-unknown/scribecrop/blob/main/web/src/components/Dropzone.tsx"
click node_use_image "https://github.com/visible-unknown/scribecrop/blob/main/web/src/hooks/useImage.ts"
click node_types "https://github.com/visible-unknown/scribecrop/blob/main/web/src/types/index.ts"
click node_preview_panel "https://github.com/visible-unknown/scribecrop/blob/main/web/src/components/PreviewPanel.tsx"
click node_crop_image "https://github.com/visible-unknown/scribecrop/blob/main/web/src/utils/cropImage.ts"
click node_export_crops "https://github.com/visible-unknown/scribecrop/blob/main/web/src/utils/exportCrops.ts"
click node_page_styles "https://github.com/visible-unknown/scribecrop/blob/main/web/src/app/page.module.css"
click node_editor_styles "https://github.com/visible-unknown/scribecrop/blob/main/web/src/components/CanvasEditor.module.css"
click node_dropzone_styles "https://github.com/visible-unknown/scribecrop/blob/main/web/src/components/Dropzone.module.css"
click node_preview_styles "https://github.com/visible-unknown/scribecrop/blob/main/web/src/components/PreviewPanel.module.css"
click node_globals_css "https://github.com/visible-unknown/scribecrop/blob/main/web/src/app/globals.css"
click node_electron_main "https://github.com/visible-unknown/scribecrop/blob/main/desktop/main.js"
click node_desktop_pkg "https://github.com/visible-unknown/scribecrop/blob/main/desktop/package.json"
click node_web_pkg "https://github.com/visible-unknown/scribecrop/blob/main/web/package.json"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_root_pkg toneBlue
class node_web_shell,node_web_layout,node_canvas_editor,node_dropzone,node_use_image,node_types,node_preview_panel,node_crop_image,node_export_crops,node_page_styles,node_editor_styles,node_dropzone_styles,node_preview_styles,node_globals_css,node_web_pkg toneAmber
class node_electron_main,node_desktop_pkg toneMint
```

## Components

### Root workspace

Top-level monorepo coordination and shared scripts

- [Workspace](https://github.com/visible-unknown/scribecrop/blob/main/package.json): monorepo scripts · Coordinates shared development and build tasks · `package.json`

### Web app

Next.js editor application and core image-annotation logic

- [App shell](https://github.com/visible-unknown/scribecrop/blob/main/web/src/app/page.tsx): next app router · Top-level page and layout composition for the editor UI · `web/src/app/page.tsx`
- [Layout](https://github.com/visible-unknown/scribecrop/blob/main/web/src/app/layout.tsx): next layout · Global app frame and shared chrome · `web/src/app/layout.tsx`
- [Canvas editor](https://github.com/visible-unknown/scribecrop/blob/main/web/src/components/CanvasEditor.tsx): interactive editor · Primary region for drawing and manipulating crops · `web/src/components/CanvasEditor.tsx`
- [Dropzone](https://github.com/visible-unknown/scribecrop/blob/main/web/src/components/Dropzone.tsx): image ingress · Handles file selection and drag-and-drop image input · `web/src/components/Dropzone.tsx`
- [Image hook](https://github.com/visible-unknown/scribecrop/blob/main/web/src/hooks/useImage.ts): image state · Normalizes loaded image state and metadata · `web/src/hooks/useImage.ts`
- [Crop types](https://github.com/visible-unknown/scribecrop/blob/main/web/src/types/index.ts): domain model · Shared shapes and editor data structures · `web/src/types/index.ts`
- [Preview panel](https://github.com/visible-unknown/scribecrop/blob/main/web/src/components/PreviewPanel.tsx): review panel · Shows generated crops and labels before export · `web/src/components/PreviewPanel.tsx`
- [Crop image](https://github.com/visible-unknown/scribecrop/blob/main/web/src/utils/cropImage.ts): processing util · Turns region definitions into cropped image outputs · `web/src/utils/cropImage.ts`
- [Export crops](https://github.com/visible-unknown/scribecrop/blob/main/web/src/utils/exportCrops.ts): export util · Packages generated crops for download or ZIP export · `web/src/utils/exportCrops.ts`
- [Page styles](https://github.com/visible-unknown/scribecrop/blob/main/web/src/app/page.module.css): css modules · Scoped styling for the editor page shell · `web/src/app/page.module.css`
- [Editor styles](https://github.com/visible-unknown/scribecrop/blob/main/web/src/components/CanvasEditor.module.css): css modules · Scoped styling for canvas editor UI · `web/src/components/CanvasEditor.module.css`
- [Dropzone styles](https://github.com/visible-unknown/scribecrop/blob/main/web/src/components/Dropzone.module.css): css modules · Scoped styling for image ingestion UI · `web/src/components/Dropzone.module.css`
- [Preview styles](https://github.com/visible-unknown/scribecrop/blob/main/web/src/components/PreviewPanel.module.css): css modules · Scoped styling for preview and export review · `web/src/components/PreviewPanel.module.css`
- [Global styles](https://github.com/visible-unknown/scribecrop/blob/main/web/src/app/globals.css): app css · Baseline styles for the web application · `web/src/app/globals.css`
- [Web package](https://github.com/visible-unknown/scribecrop/blob/main/web/package.json): next build · Web app dependencies and build scripts · `web/package.json`

### Desktop shell

Electron wrapper around the web app

- [Electron main](https://github.com/visible-unknown/scribecrop/blob/main/desktop/main.js): desktop host · Launches a native window around the web app · `desktop/main.js`
- [Desktop package](https://github.com/visible-unknown/scribecrop/blob/main/desktop/package.json): electron build · Desktop runtime and packaging configuration · `desktop/package.json`

## Connections

- Workspace → Web package: manages · Workspace scripts coordinate the web app build and dev flow
- Workspace → Desktop package: manages · Workspace scripts also coordinate desktop packaging and launch
- Desktop package → Electron main: starts · Desktop package boots the Electron entry point
- Electron main → App shell: hosts · Electron wraps the web application as the user-facing editor
- App shell → Layout: composes · Page is framed by the shared app layout
- App shell → Canvas editor: renders · Main page includes the interactive canvas editor
- App shell → Dropzone: renders · Main page exposes image ingestion controls
- App shell → Preview panel: renders · Main page includes crop review and export preview
- Dropzone → Image hook: loads · User-selected images are normalized into app state
- Image hook → Crop types: uses · Image state is shaped by shared domain types
- Canvas editor → Crop types: uses · Canvas interactions read and update crop region data
- Preview panel → Crop types: uses · Preview reads the same crop metadata and ordering
- Canvas editor → Crop image: drives · Editor state feeds crop generation
- Crop image → Export crops: feeds · Generated crops are bundled for export
- Preview panel → Export crops: triggers · Preview stage initiates export packaging
- App shell → Page styles: styles · Page shell uses scoped layout styling
- Canvas editor → Editor styles: styles · Canvas editor has component-scoped styling
- Dropzone → Dropzone styles: styles · Dropzone has component-scoped styling
- Preview panel → Preview styles: styles · Preview panel has component-scoped styling
- Layout → Global styles: styles · Global baseline styles apply across the app
