mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
Adds a Rounded Crop image tool for logo, favicon, and app-icon work. It masks the framed square to a rounded rectangle (with a corner-radius control) or an iOS-style squircle, reusing circle-crop's zoom/offset framing, border ring, background fill, and output-size options. Includes translations across all 21 locales. Closes #601
2708 lines
68 KiB
TypeScript
2708 lines
68 KiB
TypeScript
import { expandConversionPresets } from "./conversion-presets.js";
|
|
import { AUDIO_INPUTS, IMAGE_INPUTS, SUBTITLE_INPUTS, VIDEO_INPUTS } from "./modality.js";
|
|
import { toolSection } from "./section.js";
|
|
import type { CategoryInfo, SocialMediaPreset, Tool } from "./types.js";
|
|
|
|
export const CATEGORIES: CategoryInfo[] = [
|
|
// Image
|
|
{ id: "essentials", name: "Essentials", icon: "Layers", color: "#3B82F6" },
|
|
{ id: "adjustments", name: "Adjustments", icon: "SlidersHorizontal", color: "#8B5CF6" },
|
|
{ id: "enhance", name: "Enhance & AI", icon: "Sparkles", color: "#F59E0B" },
|
|
{ id: "watermark", name: "Watermark & Overlay", icon: "Stamp", color: "#EF4444" },
|
|
{ id: "layout", name: "Layout & Composition", icon: "LayoutGrid", color: "#EC4899" },
|
|
{ id: "utilities", name: "Utilities", icon: "Wrench", color: "#6366F1" },
|
|
{ id: "optimization", name: "Optimization", icon: "Zap", color: "#10B981" },
|
|
{ id: "format", name: "Format & Conversion", icon: "FileType", color: "#14B8A6" },
|
|
// Video
|
|
{ id: "video-edit", name: "Edit", icon: "Video", color: "#EF4444" },
|
|
{ id: "video-convert", name: "Convert", icon: "FileVideo", color: "#F97316" },
|
|
{ id: "video-effects", name: "Effects & Compose", icon: "Wand2", color: "#EC4899" },
|
|
{ id: "video-subtitles", name: "Subtitles", icon: "Captions", color: "#8B5CF6" },
|
|
{ id: "video-metadata", name: "Metadata", icon: "Tags", color: "#6366F1" },
|
|
// Audio
|
|
{ id: "audio-edit", name: "Edit", icon: "AudioLines", color: "#10B981" },
|
|
{ id: "audio-convert", name: "Convert", icon: "FileAudio", color: "#14B8A6" },
|
|
{ id: "audio-effects", name: "Effects & Compose", icon: "Waves", color: "#06B6D4" },
|
|
{ id: "audio-metadata", name: "Metadata", icon: "Tags", color: "#6366F1" },
|
|
// Documents
|
|
{ id: "pdf-organize", name: "Organize", icon: "FolderOpen", color: "#8B5CF6" },
|
|
{ id: "pdf-edit", name: "Edit & Annotate", icon: "PenLine", color: "#3B82F6" },
|
|
{ id: "pdf-security", name: "Security", icon: "Lock", color: "#EF4444" },
|
|
{ id: "pdf-optimize", name: "Optimize", icon: "Zap", color: "#10B981" },
|
|
{ id: "doc-convert", name: "Convert", icon: "FileType", color: "#14B8A6" },
|
|
// Data & Files
|
|
{ id: "data", name: "Files", icon: "Table", color: "#F59E0B" },
|
|
{ id: "archives", name: "Archives", icon: "FolderArchive", color: "#6366F1" },
|
|
];
|
|
|
|
const BASE_TOOLS: Tool[] = [
|
|
// Essentials
|
|
{
|
|
id: "resize",
|
|
name: "Resize Image",
|
|
description: "Resize by pixels, percentage, or social media presets",
|
|
category: "essentials",
|
|
icon: "Maximize2",
|
|
route: "/resize",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "crop",
|
|
name: "Crop Image",
|
|
description: "Freeform crop, aspect ratio presets, shape crop",
|
|
category: "essentials",
|
|
icon: "Crop",
|
|
route: "/crop",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "rotate",
|
|
name: "Rotate & Flip Image",
|
|
description: "Rotate, flip, and straighten images",
|
|
category: "essentials",
|
|
icon: "RotateCw",
|
|
route: "/rotate",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "convert",
|
|
name: "Convert Image",
|
|
description: "Convert between image formats",
|
|
category: "essentials",
|
|
icon: "FileOutput",
|
|
route: "/convert",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
keywords: [
|
|
"image converter",
|
|
"jpg to png",
|
|
"png to jpg",
|
|
"heic to jpg",
|
|
"webp to png",
|
|
"convert image format",
|
|
],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "compress",
|
|
name: "Compress Image",
|
|
description: "Reduce file size by quality or target size",
|
|
category: "essentials",
|
|
icon: "Minimize2",
|
|
route: "/compress",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
// Optimization
|
|
{
|
|
id: "optimize-for-web",
|
|
name: "Optimize for Web",
|
|
description:
|
|
"Optimize images for web with format conversion, quality control, and live preview",
|
|
category: "optimization",
|
|
icon: "Globe",
|
|
route: "/optimize-for-web",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "strip-metadata",
|
|
name: "Remove Image Metadata",
|
|
description: "Remove EXIF, GPS, and camera info",
|
|
category: "optimization",
|
|
icon: "ShieldOff",
|
|
route: "/strip-metadata",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "edit-metadata",
|
|
name: "Edit Image Metadata",
|
|
description: "Edit EXIF, GPS, and camera info",
|
|
category: "optimization",
|
|
icon: "PenLine",
|
|
route: "/edit-metadata",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "bulk-rename",
|
|
name: "Bulk Rename",
|
|
description: "Rename multiple files with patterns",
|
|
category: "optimization",
|
|
icon: "FilePen",
|
|
route: "/bulk-rename",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "image-to-pdf",
|
|
name: "Image to PDF",
|
|
description: "Combine images into a PDF document",
|
|
category: "optimization",
|
|
icon: "FileText",
|
|
route: "/image-to-pdf",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
outputModality: "document",
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "favicon",
|
|
name: "Favicon Generator",
|
|
description: "Generate all favicon and app icon sizes",
|
|
category: "optimization",
|
|
icon: "AppWindow",
|
|
route: "/favicon",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
// Adjustments
|
|
{
|
|
id: "adjust-colors",
|
|
name: "Adjust Colors",
|
|
description: "Brightness, contrast, exposure, saturation, temperature, sharpness, and effects",
|
|
category: "adjustments",
|
|
icon: "SlidersHorizontal",
|
|
route: "/adjust-colors",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "sharpening",
|
|
name: "Sharpen Image",
|
|
description: "Adaptive, unsharp mask, and high-pass sharpening with presets",
|
|
keywords: ["sharpen", "sharpening", "unsharp", "clarity"],
|
|
category: "adjustments",
|
|
icon: "Focus",
|
|
route: "/sharpening",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "replace-color",
|
|
name: "Replace & Invert Color",
|
|
description: "Replace specific colors or invert",
|
|
category: "adjustments",
|
|
icon: "Pipette",
|
|
route: "/replace-color",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "color-blindness",
|
|
name: "Color Blindness Simulation",
|
|
description: "Simulate how images appear with color vision deficiency",
|
|
category: "adjustments",
|
|
icon: "Eye",
|
|
route: "/color-blindness",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
// Enhance & AI
|
|
{
|
|
id: "remove-background",
|
|
name: "Remove Background",
|
|
description: "AI-powered background removal",
|
|
category: "enhance",
|
|
icon: "Eraser",
|
|
route: "/remove-background",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "remove-gif-background",
|
|
name: "Remove GIF Background",
|
|
description: "AI background removal for animated GIFs, WebP, and APNG",
|
|
category: "enhance",
|
|
icon: "Film",
|
|
route: "/remove-gif-background",
|
|
modality: "image",
|
|
acceptedInputs: [".gif", ".webp", ".apng", ".png"],
|
|
executionHint: "long",
|
|
keywords: [
|
|
"gif",
|
|
"animated",
|
|
"transparent gif",
|
|
"animated webp",
|
|
"apng",
|
|
"remove gif background",
|
|
"gif background",
|
|
"animated background removal",
|
|
"transparent background gif",
|
|
"gif cutout",
|
|
],
|
|
},
|
|
{
|
|
id: "upscale",
|
|
name: "Image Upscaling",
|
|
description: "AI super-resolution enhancement",
|
|
category: "enhance",
|
|
icon: "ZoomIn",
|
|
route: "/upscale",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "erase-object",
|
|
name: "Object Eraser",
|
|
description: "Remove unwanted objects with AI",
|
|
category: "enhance",
|
|
icon: "Wand",
|
|
route: "/erase-object",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "ocr",
|
|
name: "Extract Text from Image (OCR)",
|
|
description: "Extract text from images",
|
|
category: "doc-convert",
|
|
icon: "ScanText",
|
|
route: "/ocr",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
outputModality: "file",
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "ocr-pdf",
|
|
name: "PDF OCR",
|
|
description: "Extract text from PDF documents using AI-powered OCR",
|
|
category: "doc-convert",
|
|
icon: "ScanText",
|
|
route: "/ocr-pdf",
|
|
modality: "document",
|
|
acceptedInputs: [".pdf"],
|
|
outputModality: "file",
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "blur-faces",
|
|
name: "Blur Faces & PII",
|
|
description: "Auto-detect and blur faces and sensitive info",
|
|
keywords: ["blur faces", "pii", "redact face", "anonymize"],
|
|
category: "enhance",
|
|
icon: "EyeOff",
|
|
route: "/blur-faces",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "smart-crop",
|
|
name: "Smart Crop",
|
|
description: "Smart subject, face, or trim-based cropping",
|
|
category: "enhance",
|
|
icon: "Crosshair",
|
|
route: "/smart-crop",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "image-enhancement",
|
|
name: "Image Enhancement",
|
|
description: "One-click auto-improve with smart analysis",
|
|
category: "enhance",
|
|
icon: "Sparkles",
|
|
route: "/image-enhancement",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast", // pure sharp/CV; optional deepEnhance defers to noise-removal
|
|
},
|
|
{
|
|
id: "enhance-faces",
|
|
name: "Face Enhancement",
|
|
description: "Restore and enhance faces with AI",
|
|
category: "enhance",
|
|
icon: "ScanFace",
|
|
route: "/enhance-faces",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "colorize",
|
|
name: "AI Colorization",
|
|
description: "Convert B&W photos to full color with AI",
|
|
category: "enhance",
|
|
icon: "Palette",
|
|
route: "/colorize",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "noise-removal",
|
|
name: "Noise Removal",
|
|
description: "AI-powered noise and grain removal",
|
|
category: "enhance",
|
|
icon: "AudioLines",
|
|
route: "/noise-removal",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "red-eye-removal",
|
|
name: "Red Eye Removal",
|
|
description: "AI-detect and fix red eye in flash photos",
|
|
category: "enhance",
|
|
icon: "ScanEye",
|
|
route: "/red-eye-removal",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "restore-photo",
|
|
name: "Photo Restoration",
|
|
description: "Fix scratches, tears, and damage on old photos with AI",
|
|
category: "enhance",
|
|
icon: "Undo2",
|
|
route: "/restore-photo",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "passport-photo",
|
|
name: "Passport Photo",
|
|
description: "AI-powered passport and ID photo generator",
|
|
category: "utilities",
|
|
icon: "UserCheck",
|
|
route: "/passport-photo",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "content-aware-resize",
|
|
name: "Content-Aware Resize",
|
|
description: "Seam carving resize that preserves important content with face protection",
|
|
category: "enhance",
|
|
icon: "Scaling",
|
|
route: "/content-aware-resize",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "ai-canvas-expand",
|
|
name: "AI Canvas Expand",
|
|
description: "Expand canvas with AI-powered fill",
|
|
category: "enhance",
|
|
icon: "Expand",
|
|
route: "/ai-canvas-expand",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "transcribe-audio",
|
|
name: "Transcribe Audio",
|
|
description: "Convert speech to text with AI-powered transcription",
|
|
category: "audio-convert",
|
|
icon: "MicVocal",
|
|
route: "/transcribe-audio",
|
|
modality: "audio",
|
|
acceptedInputs: AUDIO_INPUTS,
|
|
outputModality: "file",
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "auto-subtitles",
|
|
name: "Auto Subtitles",
|
|
description: "Generate subtitle files from video audio tracks",
|
|
category: "video-subtitles",
|
|
icon: "Captions",
|
|
route: "/auto-subtitles",
|
|
modality: "video",
|
|
acceptedInputs: VIDEO_INPUTS,
|
|
outputModality: "file",
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "transparency-fixer",
|
|
name: "PNG Transparency Fixer",
|
|
description: "Fix fake transparent PNGs in one click",
|
|
category: "enhance",
|
|
icon: "ShieldCheck",
|
|
route: "/transparency-fixer",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "background-replace",
|
|
name: "Background Replace",
|
|
description: "Replace image background with a solid color",
|
|
category: "enhance",
|
|
icon: "PaintBucket",
|
|
route: "/background-replace",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "blur-background",
|
|
name: "Blur Background",
|
|
description: "Blur the background while keeping the subject sharp",
|
|
category: "enhance",
|
|
icon: "Focus",
|
|
route: "/blur-background",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "long",
|
|
},
|
|
// Watermark & Overlay
|
|
{
|
|
id: "watermark-text",
|
|
name: "Text Watermark",
|
|
description: "Add text watermark overlay",
|
|
category: "watermark",
|
|
icon: "Type",
|
|
route: "/watermark-text",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "watermark-image",
|
|
name: "Image Watermark",
|
|
description: "Overlay a logo as watermark",
|
|
category: "watermark",
|
|
icon: "Image",
|
|
route: "/watermark-image",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "text-overlay",
|
|
name: "Text Overlay",
|
|
description: "Add styled text to images",
|
|
category: "watermark",
|
|
icon: "TextCursorInput",
|
|
route: "/text-overlay",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "compose",
|
|
name: "Image Composition",
|
|
description: "Layer images with position and opacity",
|
|
category: "watermark",
|
|
icon: "Layers",
|
|
route: "/compose",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "meme-generator",
|
|
name: "Meme Generator",
|
|
description: "Create memes with templates and custom text",
|
|
category: "watermark",
|
|
icon: "Laugh",
|
|
route: "/meme-generator",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
// Utilities
|
|
{
|
|
id: "info",
|
|
name: "Image Info",
|
|
description: "View all metadata and image properties",
|
|
category: "utilities",
|
|
icon: "Info",
|
|
route: "/info",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "compare",
|
|
name: "Image Compare",
|
|
description: "Side-by-side comparison of two images",
|
|
category: "utilities",
|
|
icon: "Columns2",
|
|
route: "/compare",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "find-duplicates",
|
|
name: "Find Duplicates",
|
|
description: "Detect duplicate and near-duplicate images",
|
|
category: "utilities",
|
|
icon: "Copy",
|
|
route: "/find-duplicates",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "color-palette",
|
|
name: "Color Palette",
|
|
description: "Extract dominant colors from image",
|
|
category: "utilities",
|
|
icon: "Droplets",
|
|
route: "/color-palette",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "qr-generate",
|
|
name: "QR Code Generator",
|
|
description: "Generate styled QR codes with custom colors, patterns, and logos",
|
|
category: "utilities",
|
|
icon: "QrCode",
|
|
route: "/qr-generate",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "html-to-image",
|
|
name: "HTML to Image",
|
|
description: "Capture webpages as high-quality images",
|
|
category: "utilities",
|
|
icon: "Globe",
|
|
route: "/html-to-image",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "barcode-read",
|
|
name: "Barcode Reader",
|
|
description: "Scan images for QR codes, barcodes, and 2D codes",
|
|
category: "utilities",
|
|
icon: "ScanLine",
|
|
route: "/barcode-read",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "image-to-base64",
|
|
name: "Image to Base64",
|
|
description: "Convert images to base64 strings for embedding in HTML, CSS, and more",
|
|
category: "utilities",
|
|
icon: "Code",
|
|
route: "/image-to-base64",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "barcode-generate",
|
|
name: "Barcode Generator",
|
|
description: "Generate barcodes in Code 128, EAN-13, UPC-A, Code 39, ITF-14, and Data Matrix",
|
|
category: "utilities",
|
|
icon: "Barcode",
|
|
route: "/barcode-generate",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
// Layout & Composition
|
|
{
|
|
id: "collage",
|
|
name: "Collage & Grid",
|
|
description: "Combine images into beautiful grid collages with 25+ templates",
|
|
category: "layout",
|
|
icon: "LayoutGrid",
|
|
route: "/collage",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "stitch",
|
|
name: "Stitch Images",
|
|
description: "Join images side by side, stacked, or in a grid",
|
|
category: "layout",
|
|
icon: "Columns2",
|
|
route: "/stitch",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "split",
|
|
name: "Split Image",
|
|
description: "Split images into grid tiles or by pixel size with live preview",
|
|
category: "layout",
|
|
icon: "Grid3x3",
|
|
route: "/split",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "border",
|
|
name: "Border & Frame",
|
|
description: "Add borders, rounded corners, shadows",
|
|
category: "layout",
|
|
icon: "Frame",
|
|
route: "/border",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "beautify",
|
|
name: "Beautify Screenshot",
|
|
description: "Add gradient backgrounds, device frames, shadows, and social media sizing",
|
|
category: "layout",
|
|
icon: "ImagePlus",
|
|
route: "/beautify",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "circle-crop",
|
|
name: "Circle Crop",
|
|
description: "Crop image to a centered circle with transparent corners",
|
|
category: "layout",
|
|
icon: "Circle",
|
|
route: "/circle-crop",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "rounded-crop",
|
|
name: "Rounded Crop",
|
|
description: "Crop image to a rounded square or squircle with transparent corners",
|
|
category: "layout",
|
|
icon: "Squircle",
|
|
route: "/rounded-crop",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
keywords: [
|
|
"rounded corners",
|
|
"rounded square",
|
|
"squircle",
|
|
"favicon",
|
|
"app icon",
|
|
"logo",
|
|
"avatar",
|
|
"corner radius",
|
|
],
|
|
},
|
|
{
|
|
id: "duotone",
|
|
name: "Duotone",
|
|
description: "Apply a two-color duotone effect with custom shadow and highlight colors",
|
|
category: "adjustments",
|
|
icon: "Palette",
|
|
route: "/duotone",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "image-pad",
|
|
name: "Image Pad",
|
|
description: "Pad image to a target aspect ratio with a solid color background",
|
|
category: "layout",
|
|
icon: "RectangleHorizontal",
|
|
route: "/image-pad",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "pixelate",
|
|
name: "Pixelate",
|
|
description: "Apply a pixelation effect to the full image or a specific region",
|
|
category: "adjustments",
|
|
icon: "Grid2x2",
|
|
route: "/pixelate",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "vignette",
|
|
name: "Vignette",
|
|
description: "Add a vignette effect with adjustable strength and color",
|
|
category: "adjustments",
|
|
icon: "Aperture",
|
|
route: "/vignette",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "gif-webp",
|
|
name: "GIF/WebP Converter",
|
|
description: "Convert animated GIF to WebP and vice versa, preserving all frames",
|
|
category: "format",
|
|
icon: "Repeat",
|
|
route: "/gif-webp",
|
|
modality: "image",
|
|
acceptedInputs: [".gif", ".webp"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "histogram",
|
|
name: "Histogram",
|
|
description: "Generate an RGB histogram chart from an image",
|
|
category: "utilities",
|
|
icon: "BarChart3",
|
|
route: "/histogram",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "lqip-placeholder",
|
|
name: "LQIP Placeholder",
|
|
description: "Generate a tiny low-quality image placeholder with base64 data URI",
|
|
category: "utilities",
|
|
icon: "ImageDown",
|
|
route: "/lqip-placeholder",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "sprite-sheet",
|
|
name: "Sprite Sheet",
|
|
description: "Combine multiple images into a single sprite sheet grid",
|
|
category: "layout",
|
|
icon: "Grid3x3",
|
|
route: "/sprite-sheet",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
// Format & Conversion
|
|
{
|
|
id: "svg-to-raster",
|
|
name: "SVG to Raster",
|
|
description: "Convert SVG to PNG, JPEG, WebP, AVIF, TIFF, GIF, or HEIF at custom scale and DPI",
|
|
category: "format",
|
|
icon: "FileImage",
|
|
route: "/svg-to-raster",
|
|
modality: "image",
|
|
acceptedInputs: [".svg", ".svgz"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "vectorize",
|
|
name: "Image to SVG",
|
|
description: "Vectorize images using tracing",
|
|
category: "format",
|
|
icon: "PenTool",
|
|
route: "/vectorize",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "gif-tools",
|
|
name: "GIF Tools",
|
|
description:
|
|
"Resize, optimize, change speed, reverse, extract frames, and rotate animated GIFs",
|
|
category: "format",
|
|
icon: "Film",
|
|
route: "/gif-tools",
|
|
modality: "image",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "pdf-to-image",
|
|
name: "PDF to Image",
|
|
description: "Convert PDF pages to images",
|
|
category: "pdf-organize",
|
|
icon: "BookImage",
|
|
route: "/pdf-to-image",
|
|
modality: "document",
|
|
acceptedInputs: [".pdf"],
|
|
outputModality: "image",
|
|
executionHint: "fast",
|
|
},
|
|
// Video
|
|
{
|
|
id: "convert-video",
|
|
name: "Convert Video",
|
|
description: "Convert videos between MP4, MOV, and WebM",
|
|
category: "video-convert",
|
|
icon: "Video",
|
|
route: "/convert-video",
|
|
modality: "video",
|
|
acceptedInputs: VIDEO_INPUTS,
|
|
keywords: ["video converter", "mov to mp4", "mkv to mp4", "avi to mp4", "webm to mp4"],
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "compress-video",
|
|
name: "Compress Video",
|
|
description: "Shrink video file size with quality control",
|
|
category: "video-convert",
|
|
icon: "FileVideo",
|
|
route: "/compress-video",
|
|
modality: "video",
|
|
acceptedInputs: VIDEO_INPUTS,
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "trim-video",
|
|
name: "Trim Video",
|
|
description: "Cut a clip out of a video",
|
|
category: "video-edit",
|
|
icon: "Scissors",
|
|
route: "/trim-video",
|
|
modality: "video",
|
|
acceptedInputs: VIDEO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "mute-video",
|
|
name: "Mute Video",
|
|
description: "Remove the audio track from a video",
|
|
category: "video-edit",
|
|
icon: "VolumeX",
|
|
route: "/mute-video",
|
|
modality: "video",
|
|
acceptedInputs: VIDEO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "video-to-gif",
|
|
name: "Video to GIF",
|
|
description: "Turn a video clip into an animated GIF",
|
|
category: "video-convert",
|
|
icon: "Film",
|
|
route: "/video-to-gif",
|
|
modality: "video",
|
|
acceptedInputs: VIDEO_INPUTS,
|
|
outputModality: "image",
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "resize-video",
|
|
name: "Resize Video",
|
|
description: "Scale a video to a new resolution or preset size",
|
|
category: "video-edit",
|
|
icon: "Scaling",
|
|
route: "/resize-video",
|
|
modality: "video",
|
|
acceptedInputs: VIDEO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "crop-video",
|
|
name: "Crop Video",
|
|
description: "Crop a region out of a video",
|
|
category: "video-edit",
|
|
icon: "Crop",
|
|
route: "/crop-video",
|
|
modality: "video",
|
|
acceptedInputs: VIDEO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "rotate-video",
|
|
name: "Rotate Video",
|
|
description: "Rotate or flip a video",
|
|
category: "video-edit",
|
|
icon: "RotateCw",
|
|
route: "/rotate-video",
|
|
modality: "video",
|
|
acceptedInputs: VIDEO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "change-fps",
|
|
name: "Change FPS",
|
|
description: "Change the frame rate of a video",
|
|
category: "video-edit",
|
|
icon: "Gauge",
|
|
route: "/change-fps",
|
|
modality: "video",
|
|
acceptedInputs: VIDEO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "video-color",
|
|
name: "Video Color",
|
|
description: "Adjust brightness, contrast, saturation, and gamma",
|
|
category: "video-edit",
|
|
icon: "SlidersHorizontal",
|
|
route: "/video-color",
|
|
modality: "video",
|
|
acceptedInputs: VIDEO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "video-speed",
|
|
name: "Video Speed",
|
|
description: "Speed up or slow down a video",
|
|
category: "video-edit",
|
|
icon: "FastForward",
|
|
route: "/video-speed",
|
|
modality: "video",
|
|
acceptedInputs: VIDEO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "reverse-video",
|
|
name: "Reverse Video",
|
|
description: "Play a video clip backwards",
|
|
category: "video-edit",
|
|
icon: "Rewind",
|
|
route: "/reverse-video",
|
|
modality: "video",
|
|
acceptedInputs: VIDEO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "video-loudnorm",
|
|
name: "Normalize Video Audio",
|
|
description: "Normalize video audio volume to broadcast standard",
|
|
keywords: ["loudness", "loudnorm", "normalize audio", "broadcast"],
|
|
category: "video-edit",
|
|
icon: "Volume2",
|
|
route: "/video-loudnorm",
|
|
modality: "video",
|
|
acceptedInputs: VIDEO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "aspect-pad",
|
|
name: "Aspect Pad",
|
|
description: "Add solid-color bars to fit a target aspect ratio",
|
|
category: "video-effects",
|
|
icon: "RectangleHorizontal",
|
|
route: "/aspect-pad",
|
|
modality: "video",
|
|
acceptedInputs: VIDEO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "blur-pad",
|
|
name: "Blur Pad",
|
|
description: "Fill bars with a blurred copy of the video",
|
|
category: "video-effects",
|
|
icon: "GalleryHorizontalEnd",
|
|
route: "/blur-pad",
|
|
modality: "video",
|
|
acceptedInputs: VIDEO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "watermark-video",
|
|
name: "Watermark Video",
|
|
description: "Burn a text watermark onto video frames",
|
|
category: "video-effects",
|
|
icon: "Stamp",
|
|
route: "/watermark-video",
|
|
modality: "video",
|
|
acceptedInputs: VIDEO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "stabilize-video",
|
|
name: "Stabilize Video",
|
|
description: "Reduce camera shake with two-pass stabilization",
|
|
category: "video-effects",
|
|
icon: "Anchor",
|
|
route: "/stabilize-video",
|
|
modality: "video",
|
|
acceptedInputs: VIDEO_INPUTS,
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "gif-to-video",
|
|
name: "GIF to Video",
|
|
description: "Convert an animated GIF into an MP4 or WebM video",
|
|
category: "video-convert",
|
|
icon: "Film",
|
|
route: "/gif-to-video",
|
|
modality: "video",
|
|
acceptedInputs: [".gif"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "video-to-webp",
|
|
name: "Video to WebP",
|
|
description: "Convert a video clip into an animated WebP image",
|
|
category: "video-convert",
|
|
icon: "Image",
|
|
route: "/video-to-webp",
|
|
modality: "video",
|
|
acceptedInputs: VIDEO_INPUTS,
|
|
outputModality: "image",
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "video-to-frames",
|
|
name: "Video to Frames",
|
|
description: "Extract frames from a video as a ZIP of images",
|
|
category: "video-convert",
|
|
icon: "Images",
|
|
route: "/video-to-frames",
|
|
modality: "video",
|
|
acceptedInputs: VIDEO_INPUTS,
|
|
outputModality: "file",
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "merge-videos",
|
|
name: "Merge Videos",
|
|
description: "Join multiple video clips into one file",
|
|
category: "video-effects",
|
|
icon: "Combine",
|
|
route: "/merge-videos",
|
|
modality: "video",
|
|
acceptedInputs: VIDEO_INPUTS,
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "replace-audio",
|
|
name: "Replace Audio",
|
|
description: "Swap the audio track of a video with another file",
|
|
category: "video-effects",
|
|
icon: "MicVocal",
|
|
route: "/replace-audio",
|
|
modality: "video",
|
|
acceptedInputs: [...VIDEO_INPUTS, ...AUDIO_INPUTS],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "burn-subtitles",
|
|
name: "Burn Subtitles",
|
|
description: "Permanently render subtitles onto video frames",
|
|
category: "video-subtitles",
|
|
icon: "Captions",
|
|
route: "/burn-subtitles",
|
|
modality: "video",
|
|
acceptedInputs: [...VIDEO_INPUTS, ...SUBTITLE_INPUTS],
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "embed-subtitles",
|
|
name: "Embed Subtitles",
|
|
description: "Mux a subtitle track into the video container",
|
|
category: "video-subtitles",
|
|
icon: "MessageSquareText",
|
|
route: "/embed-subtitles",
|
|
modality: "video",
|
|
acceptedInputs: [...VIDEO_INPUTS, ...SUBTITLE_INPUTS],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "extract-subtitles",
|
|
name: "Extract Subtitles",
|
|
description: "Pull the subtitle track out of a video as an SRT file",
|
|
category: "video-subtitles",
|
|
icon: "FileText",
|
|
route: "/extract-subtitles",
|
|
modality: "video",
|
|
acceptedInputs: VIDEO_INPUTS,
|
|
outputModality: "file",
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "images-to-video",
|
|
name: "Images to Video",
|
|
description: "Turn a set of images into a slideshow video",
|
|
category: "video-effects",
|
|
icon: "GalleryThumbnails",
|
|
route: "/images-to-video",
|
|
modality: "video",
|
|
acceptedInputs: IMAGE_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "video-metadata",
|
|
name: "Clean Video Metadata",
|
|
description: "Strip metadata from a video and report what was found",
|
|
category: "video-metadata",
|
|
icon: "Tags",
|
|
route: "/video-metadata",
|
|
modality: "video",
|
|
acceptedInputs: VIDEO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
// Audio
|
|
{
|
|
id: "convert-audio",
|
|
name: "Convert Audio",
|
|
description: "Convert audio between MP3, WAV, OGG, and more",
|
|
category: "audio-convert",
|
|
icon: "AudioLines",
|
|
route: "/convert-audio",
|
|
modality: "audio",
|
|
acceptedInputs: AUDIO_INPUTS,
|
|
keywords: ["audio converter", "m4a to mp3", "aac to mp3", "wav to mp3", "ogg to mp3"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "trim-audio",
|
|
name: "Trim Audio",
|
|
description: "Cut a section out of an audio file",
|
|
category: "audio-edit",
|
|
icon: "Scissors",
|
|
route: "/trim-audio",
|
|
modality: "audio",
|
|
acceptedInputs: AUDIO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "extract-audio",
|
|
name: "Extract Audio",
|
|
description: "Pull the audio track out of a video",
|
|
category: "audio-edit",
|
|
icon: "FileAudio",
|
|
route: "/extract-audio",
|
|
modality: "video",
|
|
acceptedInputs: VIDEO_INPUTS,
|
|
outputModality: "audio",
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "volume-adjust",
|
|
name: "Adjust Volume",
|
|
description: "Increase or decrease audio volume by a fixed gain",
|
|
category: "audio-edit",
|
|
icon: "Volume2",
|
|
route: "/volume-adjust",
|
|
modality: "audio",
|
|
acceptedInputs: AUDIO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "normalize-audio",
|
|
name: "Normalize Audio",
|
|
description: "Even out loudness to broadcast standard levels",
|
|
category: "audio-edit",
|
|
icon: "AudioWaveform",
|
|
route: "/normalize-audio",
|
|
modality: "audio",
|
|
acceptedInputs: AUDIO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "fade-audio",
|
|
name: "Fade Audio",
|
|
description: "Add fade-in and fade-out effects to audio",
|
|
category: "audio-edit",
|
|
icon: "Waves",
|
|
route: "/fade-audio",
|
|
modality: "audio",
|
|
acceptedInputs: AUDIO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "reverse-audio",
|
|
name: "Reverse Audio",
|
|
description: "Play audio backwards",
|
|
category: "audio-edit",
|
|
icon: "Rewind",
|
|
route: "/reverse-audio",
|
|
modality: "audio",
|
|
acceptedInputs: AUDIO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "audio-speed",
|
|
name: "Audio Speed",
|
|
description: "Speed up or slow down audio playback",
|
|
category: "audio-edit",
|
|
icon: "FastForward",
|
|
route: "/audio-speed",
|
|
modality: "audio",
|
|
acceptedInputs: AUDIO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "pitch-shift",
|
|
name: "Pitch Shift",
|
|
description: "Raise or lower pitch by semitones without changing speed",
|
|
category: "audio-edit",
|
|
icon: "Music",
|
|
route: "/pitch-shift",
|
|
modality: "audio",
|
|
acceptedInputs: AUDIO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "audio-channels",
|
|
name: "Audio Channels",
|
|
description: "Convert between mono, stereo, or swap left and right channels",
|
|
category: "audio-edit",
|
|
icon: "Split",
|
|
route: "/audio-channels",
|
|
modality: "audio",
|
|
acceptedInputs: AUDIO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "silence-removal",
|
|
name: "Silence Removal",
|
|
description: "Strip silent sections from audio",
|
|
category: "audio-edit",
|
|
icon: "VolumeX",
|
|
route: "/silence-removal",
|
|
modality: "audio",
|
|
acceptedInputs: AUDIO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "noise-reduction",
|
|
name: "Noise Reduction",
|
|
description: "Reduce background noise with FFT-based denoising",
|
|
category: "audio-edit",
|
|
icon: "Sparkles",
|
|
route: "/noise-reduction",
|
|
modality: "audio",
|
|
acceptedInputs: AUDIO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "merge-audio",
|
|
name: "Merge Audio",
|
|
description: "Combine multiple audio files into one",
|
|
category: "audio-effects",
|
|
icon: "Combine",
|
|
route: "/merge-audio",
|
|
modality: "audio",
|
|
acceptedInputs: AUDIO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "split-audio",
|
|
name: "Split Audio",
|
|
description: "Split audio by time, equal parts, or silence detection",
|
|
category: "audio-effects",
|
|
icon: "Scissors",
|
|
route: "/split-audio",
|
|
modality: "audio",
|
|
acceptedInputs: AUDIO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "ringtone-maker",
|
|
name: "Ringtone Maker",
|
|
description: "Create a ringtone clip from any audio file",
|
|
category: "audio-convert",
|
|
icon: "BellRing",
|
|
route: "/ringtone-maker",
|
|
modality: "audio",
|
|
acceptedInputs: AUDIO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "waveform-image",
|
|
name: "Waveform Image",
|
|
description: "Generate a waveform visualization as a PNG image",
|
|
category: "audio-effects",
|
|
icon: "Activity",
|
|
route: "/waveform-image",
|
|
modality: "audio",
|
|
acceptedInputs: AUDIO_INPUTS,
|
|
outputModality: "image",
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "audio-metadata",
|
|
name: "Audio Metadata",
|
|
description: "View, edit, or strip audio tags (ID3)",
|
|
category: "audio-metadata",
|
|
icon: "Tags",
|
|
route: "/audio-metadata",
|
|
modality: "audio",
|
|
acceptedInputs: AUDIO_INPUTS,
|
|
executionHint: "fast",
|
|
},
|
|
// PDF & Documents
|
|
{
|
|
id: "merge-pdf",
|
|
name: "Merge PDFs",
|
|
description: "Combine multiple PDFs into one",
|
|
category: "pdf-organize",
|
|
icon: "Combine",
|
|
route: "/merge-pdf",
|
|
modality: "document",
|
|
acceptedInputs: [".pdf"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "split-pdf",
|
|
name: "Split PDF",
|
|
description: "Extract pages or split into parts",
|
|
category: "pdf-organize",
|
|
icon: "Split",
|
|
route: "/split-pdf",
|
|
modality: "document",
|
|
acceptedInputs: [".pdf"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "compress-pdf",
|
|
name: "Compress PDF",
|
|
description: "Shrink PDF file size",
|
|
category: "pdf-optimize",
|
|
icon: "FileArchive",
|
|
route: "/compress-pdf",
|
|
modality: "document",
|
|
acceptedInputs: [".pdf"],
|
|
// "long": the target-size mode runs several ghostscript passes; async keeps
|
|
// the request off the sync window and surfaces a real progress bar.
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "rotate-pdf",
|
|
name: "Rotate PDF",
|
|
description: "Rotate pages in a PDF",
|
|
category: "pdf-edit",
|
|
icon: "RotateCw",
|
|
route: "/rotate-pdf",
|
|
modality: "document",
|
|
acceptedInputs: [".pdf"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "convert-document",
|
|
name: "Convert Document",
|
|
description: "Convert between Word, OpenDocument, RTF, and plain text formats",
|
|
category: "doc-convert",
|
|
icon: "FileType2",
|
|
route: "/convert-document",
|
|
modality: "document",
|
|
acceptedInputs: [".docx", ".doc", ".odt", ".rtf", ".txt"],
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "convert-presentation",
|
|
name: "Convert Presentation",
|
|
description: "Convert between PowerPoint and OpenDocument presentation formats",
|
|
category: "doc-convert",
|
|
icon: "Presentation",
|
|
route: "/convert-presentation",
|
|
modality: "document",
|
|
acceptedInputs: [".pptx", ".ppt", ".odp"],
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "convert-spreadsheet",
|
|
name: "Convert Spreadsheet",
|
|
description:
|
|
"Convert between Excel, OpenDocument, and CSV formats. Multi-sheet workbooks export the first sheet to CSV.",
|
|
category: "doc-convert",
|
|
icon: "Grid3x3",
|
|
route: "/convert-spreadsheet",
|
|
modality: "document",
|
|
acceptedInputs: [".xlsx", ".xls", ".ods", ".csv"],
|
|
keywords: ["excel to csv", "xlsx to csv", "spreadsheet converter"],
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "excel-to-pdf",
|
|
name: "Excel to PDF",
|
|
description: "Convert spreadsheets to PDF. Wide sheets may paginate across multiple pages.",
|
|
category: "doc-convert",
|
|
icon: "Table",
|
|
route: "/excel-to-pdf",
|
|
modality: "document",
|
|
acceptedInputs: [".xlsx", ".xls", ".ods", ".csv"],
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "word-to-pdf",
|
|
name: "Word to PDF",
|
|
description: "Convert Word documents to PDF",
|
|
category: "doc-convert",
|
|
icon: "FileText",
|
|
route: "/word-to-pdf",
|
|
modality: "document",
|
|
acceptedInputs: [".docx", ".doc", ".odt", ".rtf", ".txt"],
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "extract-pages",
|
|
name: "Extract Pages",
|
|
description: "Pull selected pages into a new PDF",
|
|
category: "pdf-organize",
|
|
icon: "FileOutput",
|
|
route: "/extract-pages",
|
|
modality: "document",
|
|
acceptedInputs: [".pdf"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "remove-pages",
|
|
name: "Remove Pages",
|
|
description: "Delete specific pages from a PDF",
|
|
category: "pdf-organize",
|
|
icon: "FileX",
|
|
route: "/remove-pages",
|
|
modality: "document",
|
|
acceptedInputs: [".pdf"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "organize-pdf",
|
|
name: "Organize PDF",
|
|
description: "Reorder pages with an explicit page order",
|
|
category: "pdf-organize",
|
|
icon: "ListOrdered",
|
|
route: "/organize-pdf",
|
|
modality: "document",
|
|
acceptedInputs: [".pdf"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "protect-pdf",
|
|
name: "Protect PDF",
|
|
description: "Add password protection (AES-256 encryption)",
|
|
category: "pdf-security",
|
|
icon: "Lock",
|
|
route: "/protect-pdf",
|
|
modality: "document",
|
|
acceptedInputs: [".pdf"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "unlock-pdf",
|
|
name: "Unlock PDF",
|
|
description: "Remove password protection from a PDF",
|
|
category: "pdf-security",
|
|
icon: "LockOpen",
|
|
route: "/unlock-pdf",
|
|
modality: "document",
|
|
acceptedInputs: [".pdf"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "repair-pdf",
|
|
name: "Repair PDF",
|
|
description: "Attempt to repair a damaged or corrupted PDF",
|
|
category: "pdf-optimize",
|
|
icon: "Wrench",
|
|
route: "/repair-pdf",
|
|
modality: "document",
|
|
acceptedInputs: [".pdf"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "linearize-pdf",
|
|
name: "Web-Optimize PDF",
|
|
description: "Linearize a PDF for fast web viewing",
|
|
category: "pdf-optimize",
|
|
icon: "Zap",
|
|
route: "/linearize-pdf",
|
|
modality: "document",
|
|
acceptedInputs: [".pdf"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "grayscale-pdf",
|
|
name: "Grayscale PDF",
|
|
description: "Convert all colors to grayscale",
|
|
category: "pdf-optimize",
|
|
icon: "Contrast",
|
|
route: "/grayscale-pdf",
|
|
modality: "document",
|
|
acceptedInputs: [".pdf"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "pdfa-convert",
|
|
name: "PDF/A Converter",
|
|
description: "Convert to archival PDF/A-2",
|
|
category: "pdf-optimize",
|
|
icon: "Archive",
|
|
route: "/pdfa-convert",
|
|
modality: "document",
|
|
acceptedInputs: [".pdf"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "crop-pdf",
|
|
name: "Crop PDF",
|
|
description: "Crop all pages with a uniform margin",
|
|
category: "pdf-optimize",
|
|
icon: "Crop",
|
|
route: "/crop-pdf",
|
|
modality: "document",
|
|
acceptedInputs: [".pdf"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "nup-pdf",
|
|
name: "Pages Per Sheet (N-up)",
|
|
description: "Arrange multiple pages per sheet",
|
|
keywords: ["nup", "n-up", "pages per sheet", "impose", "2-up", "4-up"],
|
|
category: "pdf-optimize",
|
|
icon: "LayoutGrid",
|
|
route: "/nup-pdf",
|
|
modality: "document",
|
|
acceptedInputs: [".pdf"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "booklet-pdf",
|
|
name: "Booklet PDF",
|
|
description: "Arrange pages for folding into a booklet",
|
|
category: "pdf-optimize",
|
|
icon: "BookOpen",
|
|
route: "/booklet-pdf",
|
|
modality: "document",
|
|
acceptedInputs: [".pdf"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "watermark-pdf",
|
|
name: "Watermark PDF",
|
|
description: "Add a text watermark to every page",
|
|
category: "pdf-edit",
|
|
icon: "Stamp",
|
|
route: "/watermark-pdf",
|
|
modality: "document",
|
|
acceptedInputs: [".pdf"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "pdf-page-numbers",
|
|
name: "PDF Page Numbers",
|
|
description: "Add page numbers to every page",
|
|
category: "pdf-edit",
|
|
icon: "Hash",
|
|
route: "/pdf-page-numbers",
|
|
modality: "document",
|
|
acceptedInputs: [".pdf"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "flatten-pdf",
|
|
name: "Flatten PDF",
|
|
description: "Bake forms and annotations into page content",
|
|
category: "pdf-edit",
|
|
icon: "Layers2",
|
|
route: "/flatten-pdf",
|
|
modality: "document",
|
|
acceptedInputs: [".pdf"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "redact-pdf",
|
|
name: "Redact PDF",
|
|
description: "Permanently remove text occurrences (verified true redaction)",
|
|
category: "pdf-edit",
|
|
icon: "EyeOff",
|
|
route: "/redact-pdf",
|
|
modality: "document",
|
|
acceptedInputs: [".pdf"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "sign-pdf",
|
|
name: "Sign PDF",
|
|
description: "Draw, type, or upload a signature and place it anywhere on a PDF",
|
|
category: "pdf-edit",
|
|
icon: "Signature",
|
|
route: "/sign-pdf",
|
|
modality: "document",
|
|
acceptedInputs: [".pdf"],
|
|
executionHint: "fast",
|
|
keywords: ["sign", "signature", "e-sign", "esign", "fill and sign", "autograph"],
|
|
},
|
|
{
|
|
id: "pdf-to-text",
|
|
name: "PDF to Text",
|
|
description: "Extract plain text from a PDF",
|
|
category: "doc-convert",
|
|
icon: "FileText",
|
|
route: "/pdf-to-text",
|
|
modality: "document",
|
|
acceptedInputs: [".pdf"],
|
|
outputModality: "file",
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "pdf-to-word",
|
|
name: "PDF to Word",
|
|
description: "Best for text-based PDFs; scanned pages need OCR",
|
|
category: "doc-convert",
|
|
icon: "FileType",
|
|
route: "/pdf-to-word",
|
|
modality: "document",
|
|
acceptedInputs: [".pdf"],
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "pdf-metadata",
|
|
name: "PDF Metadata",
|
|
description: "Read and write PDF document metadata",
|
|
category: "doc-convert",
|
|
icon: "Tags",
|
|
route: "/pdf-metadata",
|
|
modality: "document",
|
|
acceptedInputs: [".pdf"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "powerpoint-to-pdf",
|
|
name: "PowerPoint to PDF",
|
|
description: "Convert presentations to PDF",
|
|
category: "doc-convert",
|
|
icon: "Presentation",
|
|
route: "/powerpoint-to-pdf",
|
|
modality: "document",
|
|
acceptedInputs: [".pptx", ".ppt", ".odp"],
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "html-to-pdf",
|
|
name: "HTML to PDF",
|
|
description: "Convert an HTML file to PDF. Remote resources are disabled for privacy.",
|
|
category: "doc-convert",
|
|
icon: "FileCode",
|
|
route: "/html-to-pdf",
|
|
modality: "document",
|
|
acceptedInputs: [".html", ".htm"],
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "markdown-to-docx",
|
|
name: "Markdown to Word",
|
|
description: "Convert a Markdown file to a Word document (DOCX)",
|
|
category: "doc-convert",
|
|
icon: "FileType",
|
|
route: "/markdown-to-docx",
|
|
modality: "document",
|
|
acceptedInputs: [".md", ".markdown"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "markdown-to-html",
|
|
name: "Markdown to HTML",
|
|
description:
|
|
"Convert a Markdown file to a standalone HTML page. Remote images in the source are left as-is in the output.",
|
|
category: "doc-convert",
|
|
icon: "FileCode",
|
|
route: "/markdown-to-html",
|
|
modality: "document",
|
|
acceptedInputs: [".md", ".markdown"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "markdown-to-pdf",
|
|
name: "Markdown to PDF",
|
|
description:
|
|
"Convert a Markdown file to a styled PDF. Remote resources are disabled for privacy.",
|
|
category: "doc-convert",
|
|
icon: "FileCode2",
|
|
route: "/markdown-to-pdf",
|
|
modality: "document",
|
|
acceptedInputs: [".md", ".markdown"],
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "epub-convert",
|
|
name: "Convert from EPUB",
|
|
description:
|
|
"Convert an EPUB to PDF, DOCX, HTML, or Markdown. Remote resources inside the book are not fetched.",
|
|
category: "doc-convert",
|
|
icon: "BookOpen",
|
|
route: "/epub-convert",
|
|
modality: "document",
|
|
acceptedInputs: [".epub"],
|
|
executionHint: "long",
|
|
},
|
|
{
|
|
id: "to-epub",
|
|
name: "Convert to EPUB",
|
|
description: "Convert Word, Markdown, HTML, or plain text files to EPUB",
|
|
category: "doc-convert",
|
|
icon: "Book",
|
|
route: "/to-epub",
|
|
modality: "document",
|
|
acceptedInputs: [".docx", ".md", ".html", ".txt"],
|
|
executionHint: "long",
|
|
},
|
|
// Data Files
|
|
{
|
|
id: "chart-maker",
|
|
name: "Chart Maker",
|
|
description: "Create bar, line, or pie charts from CSV or JSON data",
|
|
category: "data",
|
|
icon: "BarChart3",
|
|
route: "/chart-maker",
|
|
modality: "file",
|
|
acceptedInputs: [".csv", ".json"],
|
|
outputModality: "image",
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "csv-excel",
|
|
name: "CSV to Excel",
|
|
description: "Convert between CSV and Excel (XLSX), both directions",
|
|
category: "data",
|
|
icon: "Table",
|
|
route: "/csv-excel",
|
|
modality: "file",
|
|
acceptedInputs: [".csv", ".tsv", ".xlsx"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "csv-json",
|
|
name: "CSV to JSON",
|
|
description: "Convert between CSV and JSON, both directions",
|
|
category: "data",
|
|
icon: "Braces",
|
|
route: "/csv-json",
|
|
modality: "file",
|
|
acceptedInputs: [".csv", ".tsv", ".json"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "json-xml",
|
|
name: "JSON to XML",
|
|
description: "Convert between JSON and XML, both directions",
|
|
category: "data",
|
|
icon: "Code",
|
|
route: "/json-xml",
|
|
modality: "file",
|
|
acceptedInputs: [".json", ".xml"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "split-csv",
|
|
name: "Split CSV",
|
|
description: "Split a CSV into smaller files by row count",
|
|
category: "data",
|
|
icon: "Split",
|
|
route: "/split-csv",
|
|
modality: "file",
|
|
acceptedInputs: [".csv", ".tsv"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "merge-csvs",
|
|
name: "Merge CSVs",
|
|
description: "Combine multiple CSV or TSV files with matching columns into one",
|
|
category: "data",
|
|
icon: "Combine",
|
|
route: "/merge-csvs",
|
|
modality: "file",
|
|
acceptedInputs: [".csv", ".tsv"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "yaml-json",
|
|
name: "Convert YAML / JSON",
|
|
description: "Convert between YAML and JSON, both directions",
|
|
category: "data",
|
|
icon: "Braces",
|
|
route: "/yaml-json",
|
|
modality: "file",
|
|
acceptedInputs: [".yaml", ".yml", ".json"],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "xml-to-csv",
|
|
name: "XML to CSV",
|
|
description: "Extract repeating elements from XML into a CSV table",
|
|
category: "data",
|
|
icon: "Grid3x3",
|
|
route: "/xml-to-csv",
|
|
modality: "file",
|
|
acceptedInputs: [".xml"],
|
|
executionHint: "fast",
|
|
},
|
|
// Archives
|
|
{
|
|
id: "create-zip",
|
|
name: "Create ZIP",
|
|
description: "Bundle multiple files into a single ZIP archive",
|
|
category: "archives",
|
|
icon: "FolderArchive",
|
|
route: "/create-zip",
|
|
modality: "file",
|
|
acceptedInputs: [],
|
|
executionHint: "fast",
|
|
},
|
|
{
|
|
id: "extract-zip",
|
|
name: "Extract ZIP",
|
|
description:
|
|
"Safely extract files from a ZIP archive with bomb protection. Single-file archives return the file directly.",
|
|
category: "archives",
|
|
icon: "FolderOpen",
|
|
route: "/extract-zip",
|
|
modality: "file",
|
|
acceptedInputs: [".zip"],
|
|
executionHint: "fast",
|
|
},
|
|
];
|
|
|
|
export const TOOLS: Tool[] = [...BASE_TOOLS, ...expandConversionPresets(BASE_TOOLS)];
|
|
|
|
for (const tool of TOOLS) {
|
|
const slug = `/${toolSection(tool)}`;
|
|
if (!tool.route.startsWith(`${slug}/`)) {
|
|
tool.route = `${slug}${tool.route}`;
|
|
}
|
|
}
|
|
|
|
export function apiToolPath(
|
|
toolOrId: string | Pick<Tool, "id" | "modality" | "acceptedInputs">,
|
|
): string {
|
|
const tool = typeof toolOrId === "string" ? TOOLS.find((t) => t.id === toolOrId) : toolOrId;
|
|
if (!tool) throw new Error(`apiToolPath: unknown tool "${String(toolOrId)}"`);
|
|
return `/api/v1/tools/${toolSection(tool)}/${tool.id}`;
|
|
}
|
|
|
|
export const SOCIAL_MEDIA_PRESETS: SocialMediaPreset[] = [
|
|
{ platform: "Instagram", name: "Post (Square)", width: 1080, height: 1080 },
|
|
{ platform: "Instagram", name: "Story / Reel", width: 1080, height: 1920 },
|
|
{ platform: "Instagram", name: "Profile Picture", width: 320, height: 320 },
|
|
{ platform: "Instagram", name: "Landscape Post", width: 1080, height: 566 },
|
|
{ platform: "Instagram", name: "Portrait Post", width: 1080, height: 1350 },
|
|
{ platform: "Twitter/X", name: "Post Image", width: 1200, height: 675 },
|
|
{ platform: "Twitter/X", name: "Header", width: 1500, height: 500 },
|
|
{ platform: "Twitter/X", name: "Profile Picture", width: 400, height: 400 },
|
|
{ platform: "Facebook", name: "Post Image", width: 1200, height: 630 },
|
|
{ platform: "Facebook", name: "Cover Photo", width: 820, height: 312 },
|
|
{ platform: "Facebook", name: "Profile Picture", width: 170, height: 170 },
|
|
{ platform: "Facebook", name: "Event Cover", width: 1920, height: 1005 },
|
|
{ platform: "YouTube", name: "Thumbnail", width: 1280, height: 720 },
|
|
{ platform: "YouTube", name: "Channel Banner", width: 2560, height: 1440 },
|
|
{ platform: "YouTube", name: "Profile Picture", width: 800, height: 800 },
|
|
{ platform: "LinkedIn", name: "Post Image", width: 1200, height: 627 },
|
|
{ platform: "LinkedIn", name: "Banner", width: 1584, height: 396 },
|
|
{ platform: "LinkedIn", name: "Profile Picture", width: 400, height: 400 },
|
|
{ platform: "TikTok", name: "Video Cover", width: 1080, height: 1920 },
|
|
{ platform: "TikTok", name: "Profile Picture", width: 200, height: 200 },
|
|
{ platform: "WhatsApp", name: "Profile Picture", width: 500, height: 500 },
|
|
{ platform: "Pinterest", name: "Pin", width: 1000, height: 1500 },
|
|
{ platform: "Threads", name: "Post Image", width: 1080, height: 1080 },
|
|
];
|
|
|
|
export interface SmartCropFacePreset {
|
|
id: string;
|
|
label: string;
|
|
multiplier: number;
|
|
}
|
|
|
|
export const SMART_CROP_FACE_PRESETS: SmartCropFacePreset[] = [
|
|
{ id: "closeup", label: "Close-up", multiplier: 1.8 },
|
|
{ id: "head-shoulders", label: "Head & Shoulders", multiplier: 2.8 },
|
|
{ id: "upper-body", label: "Upper Body", multiplier: 4.5 },
|
|
{ id: "half-body", label: "Half Body", multiplier: 7.0 },
|
|
];
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Passport / ID Photo Specs
|
|
// ---------------------------------------------------------------------------
|
|
|
|
export type PassportRegion = "americas" | "europe" | "asia" | "africa" | "oceania" | "middle-east";
|
|
|
|
export interface PassportDocumentSpec {
|
|
type: string;
|
|
label: string;
|
|
width: number; // mm
|
|
height: number; // mm
|
|
dpi: number;
|
|
headHeightMin: number; // fraction of photo height
|
|
headHeightMax: number; // fraction of photo height
|
|
eyeLineFromBottom: number; // fraction of photo height
|
|
bgColor: string; // default background hex
|
|
bgColors: string[]; // allowed background colors
|
|
}
|
|
|
|
export interface PassportSpec {
|
|
code: string;
|
|
name: string;
|
|
flag: string;
|
|
region: PassportRegion;
|
|
documents: PassportDocumentSpec[];
|
|
}
|
|
|
|
export const PASSPORT_SPECS: PassportSpec[] = [
|
|
// Americas
|
|
{
|
|
code: "US",
|
|
name: "United States",
|
|
flag: "🇺🇸",
|
|
region: "americas",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "US Passport",
|
|
width: 51,
|
|
height: 51,
|
|
dpi: 300,
|
|
headHeightMin: 0.5,
|
|
headHeightMax: 0.69,
|
|
eyeLineFromBottom: 0.56,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "CA",
|
|
name: "Canada",
|
|
flag: "🇨🇦",
|
|
region: "americas",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Canadian Passport",
|
|
width: 50,
|
|
height: 70,
|
|
dpi: 300,
|
|
headHeightMin: 0.44,
|
|
headHeightMax: 0.51,
|
|
eyeLineFromBottom: 0.55,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "BR",
|
|
name: "Brazil",
|
|
flag: "🇧🇷",
|
|
region: "americas",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Brazilian Passport",
|
|
width: 50,
|
|
height: 70,
|
|
dpi: 300,
|
|
headHeightMin: 0.5,
|
|
headHeightMax: 0.69,
|
|
eyeLineFromBottom: 0.56,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "MX",
|
|
name: "Mexico",
|
|
flag: "🇲🇽",
|
|
region: "americas",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Mexican Passport",
|
|
width: 35,
|
|
height: 45,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
// Europe
|
|
{
|
|
code: "GB",
|
|
name: "United Kingdom",
|
|
flag: "🇬🇧",
|
|
region: "europe",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "UK Passport",
|
|
width: 35,
|
|
height: 45,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#D4D4D4",
|
|
bgColors: ["#D4D4D4"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "EU",
|
|
name: "European Union",
|
|
flag: "🇪🇺",
|
|
region: "europe",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "EU Passport (ICAO)",
|
|
width: 35,
|
|
height: 45,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF", "#D4D4D4"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "DE",
|
|
name: "Germany",
|
|
flag: "🇩🇪",
|
|
region: "europe",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "German Passport",
|
|
width: 35,
|
|
height: 45,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#D4D4D4",
|
|
bgColors: ["#D4D4D4"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "FR",
|
|
name: "France",
|
|
flag: "🇫🇷",
|
|
region: "europe",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "French Passport",
|
|
width: 35,
|
|
height: 45,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#D4D4D4",
|
|
bgColors: ["#D4D4D4", "#BFDBFE"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "RU",
|
|
name: "Russia",
|
|
flag: "🇷🇺",
|
|
region: "europe",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Russian Passport",
|
|
width: 35,
|
|
height: 45,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "TR",
|
|
name: "Turkey",
|
|
flag: "🇹🇷",
|
|
region: "europe",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Turkish Passport",
|
|
width: 50,
|
|
height: 60,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "IE",
|
|
name: "Ireland",
|
|
flag: "\u{1F1EE}\u{1F1EA}",
|
|
region: "europe",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Irish Passport",
|
|
width: 35,
|
|
height: 45,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "IT",
|
|
name: "Italy",
|
|
flag: "\u{1F1EE}\u{1F1F9}",
|
|
region: "europe",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Italian Passport",
|
|
width: 35,
|
|
height: 45,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "ES",
|
|
name: "Spain",
|
|
flag: "\u{1F1EA}\u{1F1F8}",
|
|
region: "europe",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Spanish Passport",
|
|
width: 26,
|
|
height: 32,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "NL",
|
|
name: "Netherlands",
|
|
flag: "\u{1F1F3}\u{1F1F1}",
|
|
region: "europe",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Dutch Passport",
|
|
width: 35,
|
|
height: 45,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "PL",
|
|
name: "Poland",
|
|
flag: "\u{1F1F5}\u{1F1F1}",
|
|
region: "europe",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Polish Passport",
|
|
width: 35,
|
|
height: 45,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "SE",
|
|
name: "Sweden",
|
|
flag: "\u{1F1F8}\u{1F1EA}",
|
|
region: "europe",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Swedish Passport",
|
|
width: 35,
|
|
height: 45,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
// Asia
|
|
{
|
|
code: "IN",
|
|
name: "India",
|
|
flag: "🇮🇳",
|
|
region: "asia",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Indian Passport",
|
|
width: 51,
|
|
height: 51,
|
|
dpi: 300,
|
|
headHeightMin: 0.5,
|
|
headHeightMax: 0.69,
|
|
eyeLineFromBottom: 0.56,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "CN",
|
|
name: "China",
|
|
flag: "🇨🇳",
|
|
region: "asia",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Chinese Passport",
|
|
width: 33,
|
|
height: 48,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "JP",
|
|
name: "Japan",
|
|
flag: "🇯🇵",
|
|
region: "asia",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Japanese Passport",
|
|
width: 35,
|
|
height: 45,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "KR",
|
|
name: "South Korea",
|
|
flag: "🇰🇷",
|
|
region: "asia",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Korean Passport",
|
|
width: 35,
|
|
height: 45,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "TH",
|
|
name: "Thailand",
|
|
flag: "🇹🇭",
|
|
region: "asia",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Thai Passport",
|
|
width: 35,
|
|
height: 45,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "PH",
|
|
name: "Philippines",
|
|
flag: "🇵🇭",
|
|
region: "asia",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Philippine Passport",
|
|
width: 35,
|
|
height: 45,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "ID",
|
|
name: "Indonesia",
|
|
flag: "🇮🇩",
|
|
region: "asia",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Indonesian Passport",
|
|
width: 30,
|
|
height: 40,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#EF4444",
|
|
bgColors: ["#EF4444"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "SG",
|
|
name: "Singapore",
|
|
flag: "\u{1F1F8}\u{1F1EC}",
|
|
region: "asia",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Singapore Passport",
|
|
width: 35,
|
|
height: 45,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "MY",
|
|
name: "Malaysia",
|
|
flag: "\u{1F1F2}\u{1F1FE}",
|
|
region: "asia",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Malaysian Passport",
|
|
width: 35,
|
|
height: 50,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "VN",
|
|
name: "Vietnam",
|
|
flag: "\u{1F1FB}\u{1F1F3}",
|
|
region: "asia",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Vietnamese Passport",
|
|
width: 40,
|
|
height: 60,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "PK",
|
|
name: "Pakistan",
|
|
flag: "\u{1F1F5}\u{1F1F0}",
|
|
region: "asia",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Pakistani Passport",
|
|
width: 35,
|
|
height: 45,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF", "#BFDBFE"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "BD",
|
|
name: "Bangladesh",
|
|
flag: "\u{1F1E7}\u{1F1E9}",
|
|
region: "asia",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Bangladeshi Passport",
|
|
width: 35,
|
|
height: 45,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
// Oceania
|
|
{
|
|
code: "AU",
|
|
name: "Australia",
|
|
flag: "🇦🇺",
|
|
region: "oceania",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Australian Passport",
|
|
width: 35,
|
|
height: 45,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "NZ",
|
|
name: "New Zealand",
|
|
flag: "\u{1F1F3}\u{1F1FF}",
|
|
region: "oceania",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "New Zealand Passport",
|
|
width: 35,
|
|
height: 45,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
// Middle East
|
|
{
|
|
code: "SA",
|
|
name: "Saudi Arabia",
|
|
flag: "🇸🇦",
|
|
region: "middle-east",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Saudi Passport",
|
|
width: 40,
|
|
height: 60,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "AE",
|
|
name: "United Arab Emirates",
|
|
flag: "\u{1F1E6}\u{1F1EA}",
|
|
region: "middle-east",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "UAE Passport",
|
|
width: 43,
|
|
height: 55,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
// Africa
|
|
{
|
|
code: "NG",
|
|
name: "Nigeria",
|
|
flag: "🇳🇬",
|
|
region: "africa",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Nigerian Passport",
|
|
width: 35,
|
|
height: 45,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "EG",
|
|
name: "Egypt",
|
|
flag: "\u{1F1EA}\u{1F1EC}",
|
|
region: "africa",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "Egyptian Passport",
|
|
width: 40,
|
|
height: 60,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
code: "ZA",
|
|
name: "South Africa",
|
|
flag: "\u{1F1FF}\u{1F1E6}",
|
|
region: "africa",
|
|
documents: [
|
|
{
|
|
type: "passport",
|
|
label: "South African Passport",
|
|
width: 35,
|
|
height: 45,
|
|
dpi: 300,
|
|
headHeightMin: 0.7,
|
|
headHeightMax: 0.8,
|
|
eyeLineFromBottom: 0.63,
|
|
bgColor: "#FFFFFF",
|
|
bgColors: ["#FFFFFF"],
|
|
},
|
|
],
|
|
},
|
|
];
|
|
|
|
export interface PrintLayout {
|
|
id: string;
|
|
label: string;
|
|
width: number; // mm
|
|
height: number; // mm
|
|
}
|
|
|
|
export const PRINT_LAYOUTS: PrintLayout[] = [
|
|
{ id: "4x6", label: "4x6 inch", width: 102, height: 152 },
|
|
{ id: "a4", label: "A4", width: 210, height: 297 },
|
|
{ id: "none", label: "None", width: 0, height: 0 },
|
|
];
|
|
|
|
export const APP_VERSION = "2.1.0";
|
|
|
|
/**
|
|
* Tool IDs that require the Python sidecar (AI/ML tools).
|
|
* Used by the frontend for progress/timeout behavior.
|
|
*/
|
|
export const PYTHON_SIDECAR_TOOLS = [
|
|
"remove-background",
|
|
"remove-gif-background",
|
|
"upscale",
|
|
"blur-faces",
|
|
"erase-object",
|
|
"ocr",
|
|
"ocr-pdf",
|
|
"colorize",
|
|
"enhance-faces",
|
|
"noise-removal",
|
|
"smart-crop",
|
|
"red-eye-removal",
|
|
"restore-photo",
|
|
"passport-photo",
|
|
"transparency-fixer",
|
|
"ai-canvas-expand",
|
|
"transcribe-audio",
|
|
"auto-subtitles",
|
|
"background-replace",
|
|
"blur-background",
|
|
] as const;
|