Select a folder, click Organize , and SortForge scans every file, creates category folders, and moves files into their correct locations β directly on your computer.
Before: After:
βββββββββ ββββββ
Project/ Project/
βββ clip1.mp4 βββ Videos/
βββ clip2.mp4 β βββ clip1.mp4
βββ music.mp3 β βββ clip2.mp4
βββ logo.png βββ Audio/
βββ document.pdf β βββ music.mp3
βββ photo.jpg βββ Images/
βββ notes.txt β βββ logo.png
βββ backup.zip β βββ photo.jpg
βββ song.flac βββ Documents/
β βββ document.pdf
β βββ notes.txt
βββ Archives/
β βββ backup.zip
βββ Audio/
βββ song.flac
None. start.bat automatically detects and installs Node.js if it's missing.
Option 1 β Double-click to launch
Auto-installs Node.js if needed, installs dependencies, starts both servers, and opens the browser automatically. Works out of the box for non-technical users.
Option 2 β Manual start (two terminals)
# Terminal 1 β Bridge (backend)
cd apps/bridge
npm run dev
# Terminal 2 β Frontend (UI)
cd apps/web
npm run dev
Then open http://localhost:3000 in your browser.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β β
β 1. Click Browse β Folder picker opens (drives, quick β
β access, visual navigation) β
β 2. Navigate & Select β Choose any folder on your computer β
β 3. Scan β SortForge scans every file recursively β
β 4. Review Summary β See file counts by category β
β 5. Click Organize β Folders created, files moved β
β 6. Watch Live β Real-time folder tree + activity feed β
β 7. Done β Completion summary with stats β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββββββ HTTP/WS ββββββββββββββββββββββββ Filesystem ββββββββββββββββ
β β β β β β
β Frontend (UI) β ββββββββββββββ β Bridge (Server) β ββββββββββββββ β Your Disk β
β Next.js :3000 β β Node.js :43125 β β β
β β β β β β
β ββββββββββββββββ β β ββββββββββββββββ β β β
β β FolderPicker β β GET /scan β β Scanner β β Recursive walk β β
β β Modal β β βββββββββββββββΆβ β + Classify ββββββββββββββββββββββββ β
β ββββββββββββββββ β β ββββββββββββββββ β β β
β β POST /organize β β β
β ββββββββββββββββ β βββββββββββββββΆββββββββββββββββββββ β Create folders β β
β β Event Tree βββββ βββββββββββββ β β Planner + ββββββββββββββββββββββΆβ β
β β View β β WS events β β Executor β β Move files β β
β ββββββββββββββββ β ββββββββββββββββββββ β β β
β β β β β
β ββββββββββββββββ β WS events ββββββββββββββββββββ β β β
β β Activity βββββ βββββββββββββ β WebSocket Server β β β β
β β Feed β β β (real-time) β β β β
β ββββββββββββββββ β ββββββββββββββββββββ β β β
β β β β β
ββββββββββββββββββββββββ βββββββββββββββββββββββββββββββββββ
Browser ββHTTP POSTβββΆ Bridge ββfilesystemβββΆ Disk
Browser βββHTTP 202ββ Bridge (organization started)
Browser βββWS eventsββ Bridge (real-time progress)
Layer Technology Purpose
Frontend Next.js 16 React framework, SSR, routing
UI Library React 19 Component rendering
Language TypeScript 5/6 Type safety across all packages
Styling Tailwind CSS 4 Utility-first CSS
State Zustand 5 Lightweight global state
Icons Lucide React Icon library
Animations Framer Motion UI micro-animations
Data Fetching TanStack Query 5 Async operations, caching
Backend Node.js + Express 5 HTTP server, API endpoints
WebSocket ws 8 Real-time event streaming
Validation Zod 4 Schema validation (shared)
Testing Jest 30 + Vitest Unit tests (bridge + web)
Dev Server tsx TypeScript execution for bridge
SortForge/
βββ apps/
β βββ web/ # Next.js frontend
β β βββ src/
β β β βββ app/
β β β β βββ layout.tsx # Root layout (Geist font, metadata)
β β β β βββ page.tsx # Entry page β OrganizerScreen
β β β β βββ globals.css # Tailwind directives + global styles
β β β β βββ favicon.ico # Application favicon
β β β βββ components/
β β β β βββ organizer-screen.tsx # Main screen composing all UI
β β β β βββ folder-picker-modal.tsx # File Explorer-style modal
β β β β βββ folder-picker.tsx # Basic folder picker
β β β β βββ folder-browser.tsx # Inline folder browser
β β β β βββ scan-summary.tsx # Category count display
β β β β βββ organize-button.tsx # Organize trigger button
β β β β βββ event-tree.tsx # Live folder tree visualization
β β β β βββ activity-feed.tsx # Real-time event log
β β β β βββ summary-panel.tsx # Completion summary stats
β β β β βββ index.ts # Barrel export
β β β βββ hooks/
β β β β βββ use-bridge-connection.ts # Health check polling (5s)
β β β βββ lib/
β β β β βββ bridge-client.ts # HTTP/WS client wrapper
β β β βββ store/
β β β β βββ organizer-store.ts # Zustand global state
β β β βββ types/
β β β βββ organizer.ts # TypeScript interfaces
β β βββ public/ # Static assets
β β β βββ file.svg
β β β βββ globe.svg
β β β βββ next.svg
β β β βββ vercel.svg
β β β βββ window.svg
β β βββ package.json # Next.js + React dependencies
β β βββ tsconfig.json # TypeScript config
β β βββ next.config.ts # Next.js config
β β βββ postcss.config.mjs # PostCSS + Tailwind
β β βββ eslint.config.mjs # ESLint config
β β
β βββ bridge/ # Node.js file organizer server
β βββ src/
β β βββ main.ts # Entry point, starts server
β β βββ ipc/
β β β βββ server.ts # HTTP + WebSocket server
β β β βββ index.ts # Barrel export
β β βββ scanner/
β β β βββ walk.ts # Recursive directory scanner
β β β βββ classify.ts # File extension β category mapper
β β β βββ index.ts # Barrel export
β β βββ organizer/
β β β βββ planner.ts # Builds operation plan from scan
β β β βββ executor.ts # Executes plan, moves files, emits events
β β β βββ index.ts # Barrel export
β β βββ utils/
β β β βββ path-utils.ts # Path traversal safety, relative paths
β β β βββ fs-utils.ts # Filesystem helpers (exists, move, ensure)
β β β βββ name-utils.ts # Duplicate filename resolution
β β β βββ index.ts # Barrel export
β β βββ errors/
β β β βββ organizer-error.ts # Typed error classes
β β β βββ index.ts # Barrel export
β β βββ config/
β β β βββ defaults.ts # Port, WS path, CORS, max file size
β β β βββ index.ts # Barrel export
β β βββ models/
β β βββ index.ts # Model types
β βββ dist/ # Compiled output (committed)
β βββ package.json # Express, ws, zod dependencies
β βββ tsconfig.json # TypeScript config (ES2022, commonjs)
β
βββ packages/
β βββ shared/ # Shared types + Zod schemas
β βββ src/
β β βββ index.ts # All shared schemas and types
β βββ package.json # Zod dependency
β βββ tsconfig.json # TypeScript config
β
βββ start.bat # One-click launcher (auto-installs Node.js)
βββ stop.bat # Server stopper
βββ README.md # This file
βββ .gitignore # Git ignore rules
π API Endpoints (Bridge Server)
Method Endpoint Description Request Response
GET/healthHealth check β { "status": "ok", "timestamp": ... }
GET/list-dirs?path=List drives, quick-access folders, or subdirectories Query: path (or __root__) { currentPath, parentPath, isRoot, separator, drives, quickAccess, directories }
POST/scanScan a folder recursively, classify files by extension { "folderPath": "..." }{ folderPath, files[], categorySummary, totalFiles }
POST/organizeStart organizing files (async, streams events via WS) { "folderPath": "..." }202 { message, folderPath, totalFiles }
WSws://localhost:43125/eventsReal-time organization events β Stream of OrganizerEvent objects
Event Type
Payload Fields
Description
job-started
folderPath, totalOperations
Organization job has begun
folder-created
path, folderName
A category folder was created
file-move-started
sourcePath, targetPath
File move operation began
file-move-completed
sourcePath, targetPath, fileName
File successfully moved
file-skipped
sourcePath, reason
File was skipped (already in correct folder)
duplicate-resolved
originalPath, resolvedPath, fileName
Duplicate filename resolved with (1), (2), etc.
job-completed
filesOrganized, foldersCreated, filesSkipped, duplicatesResolved, duration, errors
Job finished successfully
job-failed
error
Job failed with error
π Supported File Categories
Category Destination Folder Extensions
π¬ Videos Videos/.mp4 .mov .webm .avi .mkv .flv .wmv .m4v .mpg .mpeg
π΅ Audio Audio/.mp3 .wav .flac .ogg .aac .wma .m4a .opus
πΌοΈ Images Images/.png .jpg .jpeg .webp .gif .svg .bmp .tiff .tif .ico .heic .heif
π Documents Documents/.pdf .doc .docx .txt .rtf .odt .xls .xlsx .ppt .pptx .csv .md
π¦ Archives Archives/.zip .rar .7z .tar .gz .bz2 .xz
β Other Other/Everything else
Total: 55+ file extensions recognized across 6 categories.
Component File Description
OrganizerScreen organize-screen.tsxMain composition β assembles all UI sections, manages scan/organize flow, handles WebSocket subscription
FolderPickerModal folder-picker-modal.tsxFile Explorer-style modal with drives sidebar, quick-access folders (Desktop, Downloads, Documents, Pictures, Music, Videos), visual directory navigation, path input bar, back/up/home buttons
FolderBrowser folder-browser.tsxInline folder browser (alternative to modal) with drive detection and directory listing
ScanSummary scan-summary.tsxDisplays file counts per category in a color-coded grid (blue=video, green=audio, purple=image, orange=document, red=archive, gray=other)
OrganizeButton organize-button.tsxGreen action button with loading state β sends POST to bridge, triggers organization
EventTreeView event-tree.tsxLive folder tree visualization β shows folders being created and files being placed in real-time as WebSocket events arrive
ActivityFeed activity-feed.tsxScrollable event log with timestamps β every action (create, move, skip, duplicate, complete) displayed in plain language
SummaryPanel summary-panel.tsxCompletion statistics β status, duration, files organized, folders created, skipped, duplicates resolved, errors list
Module File Responsibilities
Server ipc/server.tsHTTP server (Express-style), CORS handling, route dispatch, WebSocket upgrade, client broadcasting
Scanner scanner/walk.tsRecursive directory traversal, file stat collection, UUID generation, category summary building, skips .sortforge folder
Classifier scanner/classify.tsExtension-to-category mapping (55+ extensions), destination folder name resolution
Planner organizer/planner.tsBuilds operation plan: determines folders to create, files to move, files to skip (already in correct folder)
Executor organizer/executor.ts3-phase execution: (1) create folders, (2) move files with duplicate resolution, (3) handle skips β emits events for every action
Path Utils utils/path-utils.tsPath traversal prevention (isInsideBase), relative path computation, extension extraction
FS Utils utils/fs-utils.tsFilesystem helpers: pathExists, isDirectory, isFile, ensureDir, moveFile, getFileSize, getFileTimestamps
Name Utils utils/name-utils.tsDuplicate filename resolution: appends (1), (2), etc. until unique
Errors errors/organizer-error.tsTyped error classes: invalidSession, bridgeUnavailable, folderAccessDenied, pathTraversalRejected, fileAlreadyExists, folderCreationFailed, fileMoveFailed, fileLocked
Config config/defaults.tsPort (43125), WebSocket path (/events), CORS origin (*), max file size (10GB)
ποΈ Shared Package (packages/shared)
Provides Zod schemas and TypeScript types used by both frontend and bridge:
Schema/Type
Purpose
FileCategorySchema
Enum: video, audio, image, document, archive, other
CATEGORY_FOLDER_NAMES
Maps categories to folder names (video β Videos, etc.)
FileNodeSchema
File metadata: id, name, extension, paths, category, size, timestamps, status
FolderNodeSchema
Recursive folder tree: id, name, path, children (folders + files), status
OrganizeOperationSchema
Operation: create-folder, move-file, rename-file, skip-file
OrganizerEventSchema
WebSocket event: type, jobId, timestamp, payload
ScanResultSchema
Scan output: folderPath, files[], categorySummary, totalFiles
OrganizeRequestSchema
Request body for /organize
ScanRequestSchema
Request body for /scan
JobStatusSchema
Job state: idle, scanning, organizing, completed, failed
JobResultSchema
Final result: jobId, status, filesOrganized, foldersCreated, filesSkipped, duplicatesResolved, errors, duration
Rule
Implementation
Path traversal prevention
isInsideBase() β normalized path comparison ensures target stays inside selected folder
No overwrites
resolveDuplicate() β appends (1), (2), etc. until unique filename found
No deletions
Version 1 only moves files, never deletes
Scope validation
Bridge only operates inside the selected folder tree
Hidden folder skip
Scanner skips .sortforge metadata directory
CORS enabled
Bridge allows all origins for local development
No network exposure
Bridge binds to localhost only (port 43125)
π Organization Pipeline
βββββββββββββββ βββββββββββββββ ββββββββββββββββ ββββββββββββββββ
β Select ββββββΆβ Recursive ββββββΆβ Classify ββββββΆβ Build Plan β
β Folder β β Scan β β by Extensionβ β (operations)β
βββββββββββββββ βββββββββββββββ ββββββββββββββββ ββββββββ¬ββββββββ
β
βΌ
βββββββββββββββ βββββββββββββββ ββββββββββββββββ ββββββββββββββββ
β Job βββββββ Emit βββββββ Move Files βββββββ Create β
β Complete β β Events β β (dedup) β β Folders β
βββββββββββββββ ββββββββ¬βββββββ ββββββββββββββββ ββββββββββββββββ
β
βΌ
ββββββββββββββββ
β Live UI β
β Update β
ββββββββββββββββ
Phase
Action
Events Emitted
Phase 1
Create category folders (mkdir -p)
folder-created for each
Phase 2
Move files one-by-one (renameSync)
file-move-started, file-move-completed (or duplicate-resolved if conflict)
Phase 3
Skip already-correct files
file-skipped for each
Final
Emit completion
job-completed with stats
β‘ Frontend State Management
Zustand store (organizer-store.ts) manages:
State
Type
Description
folderPath
string
Currently selected folder
connected
boolean
Bridge health status
scanResult
ScanResult | null
Last scan results
jobStatus
JobStatus
idle β scanning β organizing β completed/failed
jobId
string | null
Active job identifier
events
OrganizerEvent[]
All received WebSocket events
tree
Map<string, FileNode>
File status tracking map
error
string | null
Current error message
duration
number
Job duration in ms
Command Location Description
start.batRoot One-click launcher β auto-installs Node.js, installs deps, starts servers, opens browser
stop.batRoot Kills processes on ports 43125 and 3000, stops named windows
npm run devapps/bridgeStart bridge in dev mode (tsx watch)
npm run buildapps/bridgeCompile TypeScript to dist/
npm startapps/bridgeRun compiled bridge
npm testapps/bridgeRun Jest tests
npm run typecheckapps/bridgeTypeScript type checking (no emit)
npm run devapps/webStart Next.js dev server
npm run buildapps/webProduction build
npm run lintapps/webESLint checks
npm run buildpackages/sharedCompile shared types
npm run typecheckpackages/sharedType check shared package
Package Framework Test Files What's Tested
apps/bridgeJest 30 + ts-jest *.test.tsScanner, classifier, planner, executor, path utils, name utils, server
apps/webVitest + @testing-library/react β Component rendering, store logic
# Bridge tests
cd apps/bridge
npm test
# Bridge type check
npm run typecheck
# Web lint
cd apps/web
npm run lint
type FileCategory = "video" | "audio" | "image" | "document" | "archive" | "other" ;
interface FileNode {
id : string ; // UUID
name : string ; // filename with extension
extension : string ; // .mp4, .pdf, etc.
absolutePath : string ; // full path on disk
relativePath : string ; // path relative to scan root
category : FileCategory ;
size : number ; // bytes
createdAt : string ; // ISO timestamp
modifiedAt : string ; // ISO timestamp
status : "pending" | "moving" | "done" | "skipped" | "error" ;
}
interface FolderNode {
id : string ;
name : string ;
relativePath : string ;
children : Array < FolderNode | FileNode > ;
status : "pending" | "creating" | "created" | "error" ;
}
interface OrganizerEvent {
type :
| "job-started"
| "folder-created"
| "file-move-started"
| "file-move-completed"
| "file-skipped"
| "duplicate-resolved"
| "job-completed"
| "job-failed" ;
jobId : string ;
timestamp : number ;
payload : Record < string , unknown > ;
}
interface JobResult {
jobId : string ;
status : JobStatus ;
filesOrganized : number ;
foldersCreated : number ;
filesSkipped : number ;
duplicatesResolved : number ;
errors : string [ ] ;
duration : number ; // milliseconds
}
Bridge Config (config/defaults.ts)
Setting
Value
Description
PORT
43125
HTTP/WebSocket server port
WS_PATH
/events
WebSocket endpoint path
CORS_ORIGIN
*
CORS allowed origins
MAX_FILE_SIZE
10 GB
Maximum file size limit
Package
Target
Module
Strict
apps/bridge
ES2022
CommonJS
Yes
apps/web
ES2017
ESNext
Yes
packages/shared
ES2022
CommonJS
Yes
Feature
Implementation
Dark/Light mode
Tailwind dark: class variants on all components
Responsive layout
Mobile-first with sm: breakpoints
Visual folder picker
Drives sidebar, quick-access grid, folder list, path input
Quick Access icons
Custom SVG icons per folder type (Desktop, Downloads, Documents, Pictures, Music, Videos)
Color-coded categories
Blue (video), Green (audio), Purple (image), Orange (document), Red (archive), Gray (other)
Live tree animation
Folders and files appear in real-time as events arrive
Activity feed
Timestamped log with scroll, auto-scroll support
Loading states
Spinner during scan, button state changes during organize
Error display
Red alert box with error message
Back/Up navigation
Folder picker supports back button, up button, home button
Path input
Type any path and press Enter to navigate directly
π§ Non-Goals (Version 1)
The following are intentionally out of scope :
β AI categorization / face detection / scene recognition
β Video editing / media conversion
β Timeline / project management
β Cloud synchronization / team collaboration
β Metadata editing / asset tagging
β Search engine / user accounts
β Duplicate cleanup (files are never deleted)
β Browser-only state as source of truth
Potential features for future versions:
β
Continuous folder monitoring (file watcher)
β
Custom organization rules
β
Project memory / manifest
β
Smart media classification
β
Metadata indexing
β
Asset management dashboard
β
Video editor integration
β
Cross-device synchronization
β
Plugin support
Never mutate state outside the store or bridge command layer
Never move files without validating target scope
Never overwrite files silently
Never rely on browser memory as the source of truth
Never show fake progress when real events are available
Every action must be observable in logs or UI
Every module must have one responsibility
Video editors
Content creators
YouTubers
Freelancers
Social media managers
Photographers
Students
Anyone with messy folders
ISC
Built with β€οΈ using Next.js, Node.js, React, TypeScript, Tailwind CSS, Zustand, Express, WebSocket, and Zod.