This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
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.
Key domain concepts:
- 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.
- Greedy meshing: Maximal rectangle algorithm generates optimized 3D geometry with separate wall generation to prevent T-junctions.
- Quantization algorithms: Posterize, median-cut, K-means, octree, and Wu methods for color reduction.
- Dedithering: Median-filter-like smoothing pass that replaces isolated dithered pixels with their most frequent neighbor color; runs as a pre-quantization step.
- Filament profiles: Reusable auto-paint filament configurations persisted to localStorage, importable/exportable as
.kappJSON files.
npm run dev # Start Vite dev server
npm run build # TypeScript check + Vite production build
npm run lint # ESLint with zero warnings policy (--max-warnings=0)
npm run lint:fix # ESLint with auto-fix
npm run format # Prettier format all src files
npm run preview # Preview production build locallyNo test framework is configured.
Stack: React 19 + TypeScript + Vite 7 + Three.js + Tailwind CSS v4 + Shadcn/Radix UI
Path alias: @/* maps to ./src/*
src/types/index.ts— Shared TypeScript types (Swatch,Filament,ThreeDControlsStateShape). Canonical location to avoid circular imports between lib modules and components.src/components/— React UI components.App.tsxis the root, holds top-level state.ThreeDControls.tsx— Orchestrator for 3D print settings; delegates to extracted sub-components and hooks.FilamentRow.tsx— Individual filament row with color picker, TD input, and auto-estimate.PrintSettingsCard.tsx— Print settings Card (pixel size, layer height, first layer height).PrintInstructions.tsx— Print instructions Card (recommended settings, swap plan, copy button).AutoPaintTab.tsx— Auto-paint tab content (profiles, filament list, max height, transition zones).
src/components/ui/— Shadcn/Radix primitive components (buttons, sliders, popovers, etc.).src/hooks/— Custom hooks that encapsulate business logic and state management:useSwatches— Async image histogram computation with cancellationuseQuantize— Color quantization algorithm dispatchuseThreeScene— Three.js scene setup, camera, controls, render loopuseAppHandlers— STL/3MF export orchestration, image downloaduseImageHistory— Undo/redo stackuseDropzone— Drag-and-drop file uploaduseHorizontalSplit— Draggable horizontal splitter state via CSS custom propertiesuseFilaments— Filament CRUD state (add, remove, update)useProfileManager— Profile save/load/delete/import/export for auto-paint filament configurationsuseColorSlicing— Color order and per-color slice height reconciliation with layer-height snappinguseSwapPlan— Swap plan computation (manual and auto-paint modes) and clipboard copyuseProcessingState— Processing overlay state (quantizing, dedithering, progress, label)useBuildWarning— Build warning logic, image dimension tracking, 3D state and rebuild signal
src/lib/— Pure algorithmic logic (no React dependencies):algorithms.ts— All quantization algorithms (K-means, median-cut, octree, Wu)meshing.ts— Greedy mesh generation for 3D geometryautoPaint.ts— Auto-paint layer stacking algorithm using TD and Beer-Lambert lawexportStl.ts— Binary STL file generationexport3mf.ts— 3MF multi-material export (uses JSZip)applyAdjustments.ts— Image adjustment filters (exposure, contrast, saturation, etc.)color.ts— RGB/HSL/Lab color space conversionscolorUtils.ts— Shared color utilities:hexLuminance()andestimateTDFromColor()profileManager.ts— CRUD + localStorage persistence for auto-paint filament profiles; import/export as.kappfilesprintSettingsStorage.ts— Print settings localStorage persistence (layer height, first layer height, pixel size)slicerDefaults.ts— Default slicer metadata (layer height, infill, nozzle diameter) embedded in 3MF exportslogger.ts— Environment-aware logger;debugis a no-op in productioncompose-refs.ts— Utility to compose multiple React refs into a single callback refutils.ts— Shadcncn()helper (clsx + tailwind-merge)
src/data/palettes.ts— Predefined color palettes
State lives in App.tsx and flows down through props. The pipeline is:
- Image upload →
useDropzone/useImageHistory - Adjustments applied →
applyAdjustments.tson offscreen canvases - Dedithering (optional) →
DeditherPanelruns a smoothing pass on quantized output - Quantization →
useQuantizedispatches to algorithm inalgorithms.ts - Swatch management →
useSwatchescomputes histogram, user reorders via dnd-kit - 3D preview →
useThreeScenebuilds geometry viameshing.ts, renders with Three.js - Export →
useAppHandlerscallsexportStl.tsorexport3mf.ts
Canvas rendering uses dual offscreen canvases (originalCanvasRef, processedCanvasRef) for non-destructive adjustment processing. CanvasPreview and the Three.js scene expose imperative handles via useImperativeHandle.
- Processing overlay: Managed by
useProcessingStatehook; unified progress indicator (processingActive,processingLabel,processingProgress) gates on quantization or dedithering and displays a progress bar. adjustmentsEpochcounter: ForcesAdjustmentsPanelto remount and reset sliders after baking adjustments into the image.- Build warning dialog: Managed by
useBuildWarninghook; anAlertDialogwarns before building 3D geometry when layer count exceeds 64 or pixel count exceeds 2.5M. ResizableSplitterlayout: The main 2-pane layout uses a percentage-based draggable splitter (30% default, 20–50% range).- Auto-paint persistence:
threeDState(filaments,paintMode: 'manual' | 'autopaint') is persisted to localStorage underkromacut.autopaint.v1with legacy migration. - 3MF export enrichment: Exports embed
layerHeight,firstLayerHeight, auto-paint filament colors, and slicer defaults fromslicerDefaults.ts.
- Three.js BufferGeometry with per-face (non-indexed) triangles so each color slice is a solid block.
CanvasTexturewithNearestFilterand disabled mipmaps for crisp pixel mapping.- STL/3MF export uses chunked processing with
setTimeout(_, 0)to keep the UI responsive.
- Prettier: 4-space indentation, single quotes, trailing commas (es5), semicolons, 100-char print width.
- ESLint: Zero warnings policy.
no-consolewarns (allowswarn/error). Unused vars warn (underscore-prefixed args ignored). - Naming: PascalCase for components/types, camelCase for hooks/functions, UPPER_SNAKE_CASE for constants.
- Hooks-first architecture: No class components. Business logic extracted into custom hooks. Event handlers stabilized with
useCallback. - TypeScript strict mode enabled. Explicit interfaces for component props and shared types.