|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## What is Kromacut |
| 6 | + |
| 7 | +Kromacut is a browser-based tool for converting images into stacked, color-layered 3D prints (lithophanes). Users upload an image, reduce it to a small color palette via quantization algorithms, configure per-color layer heights and ordering, preview in 3D, and export to STL or 3MF for multi-material printing. |
| 8 | + |
| 9 | +Key domain concepts: |
| 10 | +- **Transmission Distance (TD):** Models how light transmits through thin filament layers; used by the auto-paint algorithm to simulate multi-filament lithophane effects via Beer-Lambert law optical simulation. |
| 11 | +- **Greedy meshing:** Maximal rectangle algorithm generates optimized 3D geometry with separate wall generation to prevent T-junctions. |
| 12 | +- **Quantization algorithms:** Posterize, median-cut, K-means, octree, and Wu methods for color reduction. |
| 13 | +- **Dedithering:** Median-filter-like smoothing pass that replaces isolated dithered pixels with their most frequent neighbor color; runs as a pre-quantization step. |
| 14 | +- **Filament profiles:** Reusable auto-paint filament configurations persisted to localStorage, importable/exportable as `.kapp` JSON files. |
| 15 | + |
| 16 | +## Commands |
| 17 | + |
| 18 | +```bash |
| 19 | +npm run dev # Start Vite dev server |
| 20 | +npm run build # TypeScript check + Vite production build |
| 21 | +npm run lint # ESLint with zero warnings policy (--max-warnings=0) |
| 22 | +npm run lint:fix # ESLint with auto-fix |
| 23 | +npm run format # Prettier format all src files |
| 24 | +npm run preview # Preview production build locally |
| 25 | +``` |
| 26 | + |
| 27 | +No test framework is configured. |
| 28 | + |
| 29 | +## Architecture |
| 30 | + |
| 31 | +**Stack:** React 19 + TypeScript + Vite 7 + Three.js + Tailwind CSS v4 + Shadcn/Radix UI |
| 32 | + |
| 33 | +**Path alias:** `@/*` maps to `./src/*` |
| 34 | + |
| 35 | +### Code organization |
| 36 | + |
| 37 | +- `src/types/index.ts` — Shared TypeScript types (`Swatch`, `Filament`, `ThreeDControlsStateShape`). Canonical location to avoid circular imports between lib modules and components. |
| 38 | +- `src/components/` — React UI components. `App.tsx` is the root, holds top-level state. |
| 39 | + - `ThreeDControls.tsx` — Orchestrator for 3D print settings; delegates to extracted sub-components and hooks. |
| 40 | + - `FilamentRow.tsx` — Individual filament row with color picker, TD input, and auto-estimate. |
| 41 | + - `PrintSettingsCard.tsx` — Print settings Card (pixel size, layer height, first layer height). |
| 42 | + - `PrintInstructions.tsx` — Print instructions Card (recommended settings, swap plan, copy button). |
| 43 | + - `AutoPaintTab.tsx` — Auto-paint tab content (profiles, filament list, max height, transition zones). |
| 44 | +- `src/components/ui/` — Shadcn/Radix primitive components (buttons, sliders, popovers, etc.). |
| 45 | +- `src/hooks/` — Custom hooks that encapsulate business logic and state management: |
| 46 | + - `useSwatches` — Async image histogram computation with cancellation |
| 47 | + - `useQuantize` — Color quantization algorithm dispatch |
| 48 | + - `useThreeScene` — Three.js scene setup, camera, controls, render loop |
| 49 | + - `useAppHandlers` — STL/3MF export orchestration, image download |
| 50 | + - `useImageHistory` — Undo/redo stack |
| 51 | + - `useDropzone` — Drag-and-drop file upload |
| 52 | + - `useHorizontalSplit` — Draggable horizontal splitter state via CSS custom properties |
| 53 | + - `useFilaments` — Filament CRUD state (add, remove, update) |
| 54 | + - `useProfileManager` — Profile save/load/delete/import/export for auto-paint filament configurations |
| 55 | + - `useColorSlicing` — Color order and per-color slice height reconciliation with layer-height snapping |
| 56 | + - `useSwapPlan` — Swap plan computation (manual and auto-paint modes) and clipboard copy |
| 57 | + - `useProcessingState` — Processing overlay state (quantizing, dedithering, progress, label) |
| 58 | + - `useBuildWarning` — Build warning logic, image dimension tracking, 3D state and rebuild signal |
| 59 | +- `src/lib/` — Pure algorithmic logic (no React dependencies): |
| 60 | + - `algorithms.ts` — All quantization algorithms (K-means, median-cut, octree, Wu) |
| 61 | + - `meshing.ts` — Greedy mesh generation for 3D geometry |
| 62 | + - `autoPaint.ts` — Auto-paint layer stacking algorithm using TD and Beer-Lambert law |
| 63 | + - `exportStl.ts` — Binary STL file generation |
| 64 | + - `export3mf.ts` — 3MF multi-material export (uses JSZip) |
| 65 | + - `applyAdjustments.ts` — Image adjustment filters (exposure, contrast, saturation, etc.) |
| 66 | + - `color.ts` — RGB/HSL/Lab color space conversions |
| 67 | + - `colorUtils.ts` — Shared color utilities: `hexLuminance()` and `estimateTDFromColor()` |
| 68 | + - `profileManager.ts` — CRUD + localStorage persistence for auto-paint filament profiles; import/export as `.kapp` files |
| 69 | + - `printSettingsStorage.ts` — Print settings localStorage persistence (layer height, first layer height, pixel size) |
| 70 | + - `slicerDefaults.ts` — Default slicer metadata (layer height, infill, nozzle diameter) embedded in 3MF exports |
| 71 | + - `logger.ts` — Environment-aware logger; `debug` is a no-op in production |
| 72 | + - `compose-refs.ts` — Utility to compose multiple React refs into a single callback ref |
| 73 | + - `utils.ts` — Shadcn `cn()` helper (clsx + tailwind-merge) |
| 74 | +- `src/data/palettes.ts` — Predefined color palettes |
| 75 | + |
| 76 | +### Data flow |
| 77 | + |
| 78 | +State lives in `App.tsx` and flows down through props. The pipeline is: |
| 79 | + |
| 80 | +1. Image upload → `useDropzone` / `useImageHistory` |
| 81 | +2. Adjustments applied → `applyAdjustments.ts` on offscreen canvases |
| 82 | +3. Dedithering (optional) → `DeditherPanel` runs a smoothing pass on quantized output |
| 83 | +4. Quantization → `useQuantize` dispatches to algorithm in `algorithms.ts` |
| 84 | +5. Swatch management → `useSwatches` computes histogram, user reorders via dnd-kit |
| 85 | +6. 3D preview → `useThreeScene` builds geometry via `meshing.ts`, renders with Three.js |
| 86 | +7. Export → `useAppHandlers` calls `exportStl.ts` or `export3mf.ts` |
| 87 | + |
| 88 | +Canvas rendering uses dual offscreen canvases (`originalCanvasRef`, `processedCanvasRef`) for non-destructive adjustment processing. `CanvasPreview` and the Three.js scene expose imperative handles via `useImperativeHandle`. |
| 89 | + |
| 90 | +### Key UI patterns |
| 91 | + |
| 92 | +- **Processing overlay:** Managed by `useProcessingState` hook; unified progress indicator (`processingActive`, `processingLabel`, `processingProgress`) gates on quantization or dedithering and displays a progress bar. |
| 93 | +- **`adjustmentsEpoch` counter:** Forces `AdjustmentsPanel` to remount and reset sliders after baking adjustments into the image. |
| 94 | +- **Build warning dialog:** Managed by `useBuildWarning` hook; an `AlertDialog` warns before building 3D geometry when layer count exceeds 64 or pixel count exceeds 2.5M. |
| 95 | +- **`ResizableSplitter` layout:** The main 2-pane layout uses a percentage-based draggable splitter (30% default, 20–50% range). |
| 96 | +- **Auto-paint persistence:** `threeDState` (filaments, `paintMode: 'manual' | 'autopaint'`) is persisted to localStorage under `kromacut.autopaint.v1` with legacy migration. |
| 97 | +- **3MF export enrichment:** Exports embed `layerHeight`, `firstLayerHeight`, auto-paint filament colors, and slicer defaults from `slicerDefaults.ts`. |
| 98 | + |
| 99 | +### Rendering details |
| 100 | + |
| 101 | +- Three.js BufferGeometry with per-face (non-indexed) triangles so each color slice is a solid block. |
| 102 | +- `CanvasTexture` with `NearestFilter` and disabled mipmaps for crisp pixel mapping. |
| 103 | +- STL/3MF export uses chunked processing with `setTimeout(_, 0)` to keep the UI responsive. |
| 104 | + |
| 105 | +## Code style |
| 106 | + |
| 107 | +- **Prettier:** 4-space indentation, single quotes, trailing commas (es5), semicolons, 100-char print width. |
| 108 | +- **ESLint:** Zero warnings policy. `no-console` warns (allows `warn`/`error`). Unused vars warn (underscore-prefixed args ignored). |
| 109 | +- **Naming:** PascalCase for components/types, camelCase for hooks/functions, UPPER_SNAKE_CASE for constants. |
| 110 | +- **Hooks-first architecture:** No class components. Business logic extracted into custom hooks. Event handlers stabilized with `useCallback`. |
| 111 | +- **TypeScript strict mode** enabled. Explicit interfaces for component props and shared types. |
| 112 | + |
0 commit comments