A web-based file explorer that enables users to navigate, browse, and manage files and directories on the local filesystem. The application provides a responsive interface for directory navigation, file previews (images and PDFs), file operations (create, delete, rename, move), search functionality, and breadcrumb navigation. Built with React and Tailwind CSS frontend communicating with a Go backend that serves the local filesystem.
Runtime:
- Node.js 22.x LTS+ must be installed on the system for frontend development
- Installation:
winget install OpenJS.NodeJS.LTSorhttps://nodejs.org/
- Installation:
- Go 1.22+ must be installed on the system for backend development
- Installation:
winget install GoLang.Goorhttps://go.dev/dl/
- Installation:
Frontend Dependencies:
- package.json: React 19.x must be added for UI framework
npm install react@19 react-dom@19
- package.json: Tailwind CSS 4.x must be added for styling
npm install -D tailwindcss@4 postcss autoprefixer
- package.json: React Router 7.x must be added for client-side routing
npm install react-router-dom@7
- package.json: React PDF must be added for PDF preview functionality
npm install react-pdf pdfjs-dist
- package.json: Lucide React must be added for icon components
npm install lucide-react
- package.json: Vite must be added as build tool and dev server
npm install -D vite @vitejs/plugin-react
Frontend Configuration:
- vite.config.js: Vite configuration for React development
- Manual creation
- tailwind.config.js: Tailwind CSS configuration with custom theme
npx tailwindcss init
- postcss.config.js: PostCSS configuration for Tailwind
- Manual creation
- tsconfig.json: TypeScript configuration for type safety
- Manual creation
Backend Dependencies:
- go.mod: Go module initialization for backend
go mod init github.com/maxim-ge/seeai0/examples/explorer
- go.mod: Chi router must be added for HTTP routing (lightweight alternative)
go get -u github.com/go-chi/chi/v5
- go.mod: Chi CORS middleware must be added for cross-origin requests
go get -u github.com/go-chi/cors
Project Structure:
- frontend/: React frontend application directory
- Manual creation
- backend/: Go backend application directory
- Manual creation
-
- Root application component with routing configuration
-
- Main page component orchestrating file explorer UI
-
- Navigation breadcrumb showing current path with clickable segments
-
- Grid/list view displaying files and directories with icons
-
- Modal component for previewing images and PDFs
-
- Search input with real-time filtering of files and directories
-
- Context menu for file operations (rename, delete, move, create)
-
- Custom hook managing file explorer state and API calls
-
- Custom hook handling file operation logic (create, delete, rename, move)
-
- HTTP server entry point with Chi router configuration
-
- HTTP handlers for file system operations
-
- Business logic for file system operations and validation
-
- Direct filesystem access layer with OS operations
-
- HTTP client wrapper for backend API calls with error handling
- Used by: useFileExplorer, useFileOperations
-
- Path manipulation utilities (join, normalize, parent directory)
- Used by: BreadcrumbNav, useFileExplorer
-
- File type detection from extensions (image, PDF, text, directory)
- Used by: FileList, FilePreview
-
- File size formatting and date formatting utilities
- Used by: FileList
-
- Path validation and sanitization to prevent directory traversal attacks
- Used by: FileService
-
- Centralized error handling and HTTP error response formatting
- Used by: FileHandler
- [fetch: Web API](browser built-in)
- Browser fetch API for HTTP requests
- Used by: apiClient
- react-pdf: library
- PDF rendering library for preview functionality
- Used by: FilePreview
- lucide-react: library
- Icon library for UI elements
- Used by: FileList, BreadcrumbNav, FileOperationsMenu, SearchBar
- [os: package](Go standard library)
- Operating system file operations
- Used by: FileSystemRepository
- [path/filepath: package](Go standard library)
- File path manipulation utilities
- Used by: FileService, PathValidator
- [net/http: package](Go standard library)
- HTTP server and request handling
- Used by: Server, FileHandler
- chi: package
- HTTP router for RESTful API
- Used by: Server
Frontend State:
- FileExplorerState: interface
- State with currentPath (string), files (FileItem[]), selectedFile (FileItem | null), isLoading (bool), error (string | null)
- FileItem: interface
- File metadata with name (string), path (string), isDirectory (bool), size (number), modifiedAt (ISO8601), extension (string)
- FileOperationState: interface
- Operation state with isProcessing (bool), operationType (enum: CREATE|DELETE|RENAME|MOVE), error (string | null)
API Contracts:
- ListFilesRequest: DTO
- GET /api/files?path={path} with path (string, URL-encoded)
- ListFilesResponse: DTO
- Response with files (FileInfo[]), currentPath (string)
- FileInfo: DTO
- File metadata with name (string), path (string), isDirectory (bool), size (int64), modifiedAt (RFC3339), mimeType (string)
- CreateFileRequest: DTO
- POST /api/files with path (string), isDirectory (bool), content (string, optional)
- DeleteFileRequest: DTO
- DELETE /api/files with path (string)
- RenameFileRequest: DTO
- PUT /api/files/rename with oldPath (string), newPath (string)
- MoveFileRequest: DTO
- PUT /api/files/move with sourcePath (string), destinationPath (string)
- SearchFilesRequest: DTO
- GET /api/files/search?path={path}&query={query} with path (string), query (string)
- FileContentResponse: DTO
- GET /api/files/content?path={path} returns file content as binary stream with Content-Type header
- ErrorResponse: DTO
- Error response with error (string), code (int), details (string, optional)
Domain Models:
- FileEntry: struct
- Domain model with path (string), name (string), isDirectory (bool), size (int64), modTime (time.Time), permissions (os.FileMode)
User clicks on a directory to navigate into it and view its contents.
sequenceDiagram
actor 👤User
participant 🎯FileList
participant 🎯useFileExplorer
participant 🔧apiClient
participant 📦FileHandler
participant 📦FileService
participant 📦FileSystemRepository
👤User->>🎯FileList: clicks directory item
🎯FileList->>🎯useFileExplorer: navigateToDirectory(path)
🎯useFileExplorer->>🎯useFileExplorer: setLoading(true)
🎯useFileExplorer->>🔧apiClient: GET /api/files?path={path}
🔧apiClient->>📦FileHandler: handleListFiles(request)
📦FileHandler->>📦FileService: listFiles(path)
📦FileService->>📦PathValidator: validatePath(path)
alt path is invalid or unsafe
📦PathValidator-->>📦FileService: validation error
📦FileService-->>📦FileHandler: error response
📦FileHandler-->>🔧apiClient: 400 Bad Request
🔧apiClient-->>🎯useFileExplorer: error
🎯useFileExplorer-->>🎯FileList: displays error message
else path is valid
📦PathValidator-->>📦FileService: validation success
📦FileService->>📦FileSystemRepository: readDirectory(path)
📦FileSystemRepository-->>📦FileService: FileEntry[]
📦FileService-->>📦FileHandler: ListFilesResponse
📦FileHandler-->>🔧apiClient: 200 OK with files
🔧apiClient-->>🎯useFileExplorer: files data
🎯useFileExplorer->>🎯useFileExplorer: updateState(files, path)
🎯useFileExplorer-->>🎯FileList: renders file list
end
User clicks on an image or PDF file to preview its content.
sequenceDiagram
actor 👤User
participant 🎯FileList
participant 🎯FilePreview
participant 🔧apiClient
participant 📦FileHandler
participant 📦FileSystemRepository
👤User->>🎯FileList: clicks file (image/PDF)
🎯FileList->>🎯FilePreview: openPreview(fileItem)
🎯FilePreview->>🔧apiClient: GET /api/files/content?path={path}
🔧apiClient->>📦FileHandler: handleGetFileContent(request)
📦FileHandler->>📦FileSystemRepository: readFile(path)
alt file not found or access denied
📦FileSystemRepository-->>📦FileHandler: error
📦FileHandler-->>🔧apiClient: 404 Not Found or 403 Forbidden
🔧apiClient-->>🎯FilePreview: error state
🎯FilePreview-->>👤User: displays error message
else file read success
📦FileSystemRepository-->>📦FileHandler: file content (binary)
📦FileHandler-->>🔧apiClient: 200 OK with content + Content-Type
🔧apiClient-->>🎯FilePreview: file data
alt file is image
🎯FilePreview->>🎯FilePreview: renders <img> with blob URL
else file is PDF
🎯FilePreview->>📦react-pdf: render PDF document
📦react-pdf-->>🎯FilePreview: displays PDF viewer
end
🎯FilePreview-->>👤User: shows preview modal
end
User deletes a file or directory through the context menu.
sequenceDiagram
actor 👤User
participant 🎯FileOperationsMenu
participant 🎯useFileOperations
participant 🔧apiClient
participant 📦FileHandler
participant 📦FileService
participant 📦FileSystemRepository
participant 🎯useFileExplorer
👤User->>🎯FileOperationsMenu: right-clicks file, selects "Delete"
🎯FileOperationsMenu->>🎯FileOperationsMenu: shows confirmation dialog
👤User->>🎯FileOperationsMenu: confirms deletion
🎯FileOperationsMenu->>🎯useFileOperations: deleteFile(path)
🎯useFileOperations->>🎯useFileOperations: setProcessing(true)
🎯useFileOperations->>🔧apiClient: DELETE /api/files with path
🔧apiClient->>📦FileHandler: handleDeleteFile(request)
📦FileHandler->>📦FileService: deleteFile(path)
📦FileService->>📦FileSystemRepository: remove(path)
alt deletion fails
📦FileSystemRepository-->>📦FileService: error (permission denied, not found)
📦FileService-->>📦FileHandler: error response
📦FileHandler-->>🔧apiClient: 403 Forbidden or 404 Not Found
🔧apiClient-->>🎯useFileOperations: error
🎯useFileOperations-->>🎯FileOperationsMenu: displays error message
else deletion succeeds
📦FileSystemRepository-->>📦FileService: success
📦FileService-->>📦FileHandler: success response
📦FileHandler-->>🔧apiClient: 200 OK
🔧apiClient-->>🎯useFileOperations: success
🎯useFileOperations->>🎯useFileExplorer: refreshCurrentDirectory()
🎯useFileExplorer-->>🎯FileOperationsMenu: updates file list
🎯FileOperationsMenu-->>👤User: shows success notification
end
User enters search query to filter files in current directory.
sequenceDiagram
actor 👤User
participant 🎯SearchBar
participant 🎯useFileExplorer
participant 🔧apiClient
participant 📦FileHandler
participant 📦FileService
participant 📦FileSystemRepository
👤User->>🎯SearchBar: types search query
🎯SearchBar->>🎯SearchBar: debounce input (300ms)
🎯SearchBar->>🎯useFileExplorer: searchFiles(query, currentPath)
🎯useFileExplorer->>🔧apiClient: GET /api/files/search?path={path}&query={query}
🔧apiClient->>📦FileHandler: handleSearchFiles(request)
📦FileHandler->>📦FileService: searchFiles(path, query)
📦FileService->>📦FileSystemRepository: readDirectory(path)
📦FileSystemRepository-->>📦FileService: FileEntry[]
📦FileService->>📦FileService: filterByName(entries, query)
📦FileService-->>📦FileHandler: filtered results
📦FileHandler-->>🔧apiClient: 200 OK with filtered files
🔧apiClient-->>🎯useFileExplorer: search results
🎯useFileExplorer-->>🎯SearchBar: updates file list with results
🎯SearchBar-->>👤User: displays filtered files
User creates a new directory through the file operations menu.
sequenceDiagram
actor 👤User
participant 🎯FileOperationsMenu
participant 🎯useFileOperations
participant 🔧apiClient
participant 📦FileHandler
participant 📦FileService
participant 📦FileSystemRepository
participant 🎯useFileExplorer
👤User->>🎯FileOperationsMenu: clicks "New Folder" button
🎯FileOperationsMenu->>🎯FileOperationsMenu: shows input dialog
👤User->>🎯FileOperationsMenu: enters folder name
🎯FileOperationsMenu->>🎯useFileOperations: createDirectory(path, name)
🎯useFileOperations->>🔧apiClient: POST /api/files with path, isDirectory=true
🔧apiClient->>📦FileHandler: handleCreateFile(request)
📦FileHandler->>📦FileService: createDirectory(path)
📦FileService->>📦PathValidator: validatePath(path)
alt path invalid or already exists
📦PathValidator-->>📦FileService: validation error
📦FileService-->>📦FileHandler: error response
📦FileHandler-->>🔧apiClient: 400 Bad Request or 409 Conflict
🔧apiClient-->>🎯useFileOperations: error
🎯useFileOperations-->>🎯FileOperationsMenu: displays error message
else path valid
📦PathValidator-->>📦FileService: validation success
📦FileService->>📦FileSystemRepository: createDirectory(path)
📦FileSystemRepository-->>📦FileService: success
📦FileService-->>📦FileHandler: success response
📦FileHandler-->>🔧apiClient: 201 Created
🔧apiClient-->>🎯useFileOperations: success
🎯useFileOperations->>🎯useFileExplorer: refreshCurrentDirectory()
🎯useFileExplorer-->>🎯FileOperationsMenu: updates file list
🎯FileOperationsMenu-->>👤User: shows new folder in list
end
FileSystemRepository (os.FileInfo) -> FileEntry domain model
-> FileService (validates, enriches with MIME type)
-> FileInfo DTO (JSON serialization)
-> apiClient (HTTP response)
-> FileItem interface (frontend state)
-> FileList component (renders UI)
User clicks file -> FilePreview requests content
-> apiClient GET /api/files/content?path={path}
-> FileHandler streams file content
-> FileSystemRepository reads file as binary
-> HTTP response with Content-Type header
-> Browser receives blob
-> FilePreview creates object URL
-> Renders in <img> or react-pdf component
User input "report" -> SearchBar (debounced)
-> useFileExplorer.searchFiles(query)
-> apiClient GET /api/files/search
-> FileService.searchFiles(path, query)
-> FileSystemRepository.readDirectory()
-> Filter entries by name.contains(query, case-insensitive)
-> Return filtered FileInfo[]
-> Update FileExplorerState.files
-> FileList re-renders with filtered results
FileExplorerPage
├── Header
│ ├── Logo
│ └── SearchBar
│ └── SearchIcon (lucide-react)
├── BreadcrumbNav
│ ├── HomeIcon (lucide-react)
│ ├── PathSegment (clickable)
│ └── ChevronRight (separator)
├── Toolbar
│ ├── NewFolderButton
│ ├── UploadButton
│ └── ViewToggle (grid/list)
├── FileList
│ ├── FileItem (grid or list layout)
│ │ ├── FileIcon (lucide-react: Folder, FileText, Image, FileCode)
│ │ ├── FileName
│ │ ├── FileSize
│ │ └── ModifiedDate
│ └── EmptyState (when no files)
├── FileOperationsMenu (context menu)
│ ├── RenameOption
│ ├── DeleteOption
│ ├── MoveOption
│ └── DownloadOption
└── FilePreview (modal)
├── PreviewHeader
│ ├── FileName
│ └── CloseButton
├── PreviewContent
│ ├── ImagePreview (<img>)
│ └── PDFPreview (react-pdf Document + Page)
└── PreviewFooter
├── DownloadButton
└── PageNavigation (for PDFs)