A visual, internal tool for investigators to organize and reason through cases. Build investigation workflows by grouping related clues, connecting lines of reasoning, and previewing evidence directly on an infinite canvas.
- Infinite canvas with pan & zoom: Fluid navigation for complex investigations.
- Groups (categories): Draggable, connectable containers that hold multiple Tracks.
- Records (clues): Support rich content — text, images, video, and audio.
- Drag-and-drop everywhere:
- Move Records between Groups with clear visual feedback.
- Reorder Records within a Group.
- Inline editing: Edit Records in-place for rapid iteration.
- Group-to-Group connections: Represent reasoning flow between categories.
- State management with Zustand: Predictable, performant state updates.
- Drag-and-drop via dnd-kit: Accessible and smooth interactions.
- Routing with TanStack Router: Simple, file-based routes.
- Tailwind CSS styling: Utility-first, responsive UI.
- Optimized rendering:
React.memo,useMemo, anduseCallbackto minimize re-renders. - Undo/Redo: Time-travel state control for safe exploration.
- Export to JSON: Share and archive workflows.
- Inline media previews: Image zoom and a robust video player.
- React + Vite: Fast development and build pipeline.
- Zustand: Lightweight state management.
- @xyflow/react: Canvas primitives for nodes, edges, and panning/zooming.
- dnd-kit: Drag-and-drop interactions.
- TanStack Router: Modern, type-safe routing.
- Tailwind CSS: Styling and responsive design.
- react-medium-image-zoom: Image zoom preview.
- media-chrome: Accessible custom video player UI.
# Clone the repository
git clone https://github.com/lramos33/criminal-analysis-workflow.git
cd criminal-analysis-workflow
# Install dependencies
yarn install
# pnpm install
# npm installyarn dev
# pnpm dev
# npm run devThe app will start on the URL shown in the terminal (typically http://localhost:5173).
-
Create a Group:
- Use the "Add New Group" action to place a Group on the canvas.
- Drag to reposition Groups anywhere on the infinite canvas.
-
Add Records (clues):
- Within a group, add Records to represent text notes or media (images, video, audio).
- Drag Record to reorder within the same Group.
-
Move Records between Groups:
- Drag a Record from one Group and drop it into another. Visual feedback indicates valid targets.
-
Inline edit Tracks:
- Click a Record to edit inline.
-
Connect Groups:
- Create edges between Groups to visualize reasoning flow. Edges can be moved/updated as the investigation evolves.
-
Pan & Zoom:
- Use mouse/touchpad gestures or controls to pan and zoom across the canvas.
-
Preview media:
- Click images to open zoomed previews.
- Use the built-in video player to review footage; audio is supported as well.
-
Undo / Redo:
- Use the toolbar buttons to step backward or forward through changes.
-
Export workflow to JSON:
- Use the Export action to download the current board state as JSON for sharing or archiving.
-
Reset board:
- Use the Reset action to return to the initial state/sample board.
A concise view of the most relevant files and directories:
├─ src/
│ ├─ components/
│ │ ├─ action-buttons/ # Export, Undo/Redo, Reset, Toggle Theme, Add Group
│ │ ├─ canvas/ # Infinite canvas, nodes/groups, edges, editors
│ │ └─ ui/ # Reusable UI primitives (Button, Input, Select, etc.)
│ ├─ helpers/ # Utilities (e.g., className helpers)
│ ├─ mocks/ # Sample board data
│ ├─ routes/ # TanStack Router routes (root, index, about)
│ ├─ stores/ # Zustand stores (board, theme)
│ ├─ styles/ # Tailwind entrypoints
│ ├─ main.tsx # App bootstrap
│ └─ types.ts # Shared types
├─ vite.config.ts # Vite configuration
├─ tsconfig.json # TypeScript configs
└─ eslint.config.js # ESLint configuration
Key components to explore:
src/components/canvas/investigation-board.tsx: Canvas and board orchestration.src/components/canvas/investigation-node-group.tsx: Group container and Track list.src/components/canvas/record-editor.tsx: Track editing UI.src/components/canvas/custom-edge.tsx: Styling/behavior for reasoning connections.src/stores/investigation-board.store.ts: Core state, undo/redo, and actions.
- Rendering optimized via
memo,useMemo, anduseCallback. - Stateful logic centralized in Zustand to minimize prop drilling and re-renders.
- Virtualized-like behavior on canvas via XYFlow primitives and memoized selectors.
Made by Leonardo Ramos 👋 Get in touch!
