Files
SnapOtter/packages/shared/src/constants.ts
T
SnapOtterandGitHub e7ffb37e98 feat(image): add rounded-square and squircle crop tool (#602)
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
2026-07-21 16:48:48 +08:00

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;