- Integrate MSAL (Azure AD) login gating the entire app - Add deploy.sh for building and serving via Apache on Ubuntu - Set Vite base path to /smartcrop26/ for subpath deployment - Add .env.example with required environment variables Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
3.2 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Commands
npm run dev # Dev server on http://localhost:8080
npm run build # Production build
npm run build:dev # Dev build with source maps
npm run lint # ESLint
npm run test # Vitest (single run)
npm run test:watch # Vitest (watch mode)
Architecture
SmartCrop2026 is a fully client-side React 18 + TypeScript + Vite app for AI-powered image cropping. No backend — all image processing runs in the browser except optional Google Gemini API calls.
Path alias
@/* maps to src/* (configured in vite.config.ts and tsconfig).
Key directories
src/pages/Index.tsx— Main orchestrator. Holds all top-level state (images,selectedRatios,cropsMap,enginetoggle). This is the central wiring point.src/components/— UI components (ImageUpload, RatioSelector, CropPreviewCard, CropEditor)src/components/ui/— shadcn-ui primitives (do not edit directly; regenerate via shadcn CLI)src/lib/— Core logic (analysis engines, types, export)src/hooks/— Custom React hooks
Dual analysis engines
- AI (
lib/analyze-image.ts): Sends base64 image to Google Gemini 2.5 Flash via function calling. RequiresVITE_GOOGLE_API_KEYenv var. - Local (
lib/analyze-local.ts): Sobel edge detection entirely in-browser. Scales image to 400px max, samples candidate crop windows with center-weight bias.
Both return CropSuggestion[] with normalized coordinates (0–1).
Image handling
Images are stored as data URLs via FileReader. Canvas API is used for rendering thumbnails (CropPreviewCard), interactive editing (CropEditor), and export resizing.
Export pipeline (lib/export-zip.ts)
Iterates all images/crops, rescales via canvas at each requested pixel size, packs PNGs into a ZIP using JSZip, triggers download with FileSaver.
Config format (lib/crop-types.ts)
parseConfig() handles multiple config schemas: current v2 JSON, legacy Python tool format, and simple ratio lists. PRESET_RATIOS defines 12 built-in aspect ratios grouped by platform.
Stack
- UI: shadcn-ui (Radix primitives) + Tailwind CSS 3.4 + Lucide icons
- State: React useState lifted to Index.tsx; TanStack React Query configured but lightly used
- Styling: HSL custom properties, dark mode via next-themes class strategy, Montserrat font
- Testing: Vitest + jsdom + Testing Library
- Auth: Azure AD via MSAL (
@azure/msal-browser+@azure/msal-react) - TypeScript: Loose config (noImplicitAny: false, no strict null checks)
Deployment
# On the Ubuntu server (as root or with sudo):
/opt/smartcrop26/deploy.sh
The app is deployed to https://ai-sandbox.oliver.solutions/smartcrop26. The deploy script (deploy.sh) pulls from git, builds with npm ci && npm run build, and copies dist/ to /var/www/html/smartcrop26/.
Environment variables
Stored in /opt/smartcrop26/.env on the server (not committed):
VITE_GOOGLE_API_KEY— Google Gemini API keyVITE_AZURE_TENANT_ID— Azure AD tenant IDVITE_AZURE_CLIENT_ID— Azure AD app registration client IDVITE_AZURE_REDIRECT_URI— OAuth redirect URI (production URL)