Comprehensive file and folder management with tree view, CRUD operations, drag-and-drop, and real-time file watching for auto-refresh.
- Tree view navigation
- Expandable folders
- File type icons
- Context menu actions
- Drag & drop support
- Create files and folders
- Rename files/folders
- Delete with confirmation
- Move/Copy files
- File upload
- Auto-detect file changes
- Real-time editor refresh
- External editor sync
- 300ms debounce
- Smart conflict resolution
- Quick file search
- Filter by name
- Filter by extension
- Recent files list
# Create new file
Right-click in Explorer β New File
Enter filename β Press Enter
# Create new folder
Right-click β New Folder
Enter folder name β Press Enter
# Rename
Right-click file β Rename
Edit name β Press Enter
# Delete
Right-click file β Delete
Confirm deletion
# Open file
Click file in explorer
Or double-click to open in new tab| Action | Shortcut |
|---|---|
| New File | Ctrl+N |
| Save File | Ctrl+S |
| Close File | Ctrl+W |
| Delete | Delete key |
| Rename | F2 |
| Search Files | Ctrl+P |
frontend/src/components/FileExplorer.jsx # Tree view UI
frontend/src/services/fileService.js # API client
backend/src/controllers/file.controller.js # REST endpoints
backend/src/services/fileWatcher.service.js # File monitoring
backend/src/lib/localFileService.js # File operations
GET /api/v1/files/tree/:projectId # Get file tree
POST /api/v1/files/:projectId # Create file/folder
GET /api/v1/files/:projectId/:path # Read file
PUT /api/v1/files/:projectId/:path # Update file
DELETE /api/v1/files/:projectId/:path # Delete file
POST /api/v1/files/:projectId/rename # Rename file
POST /api/v1/files/:projectId/move # Move file{
"name": "my-project",
"type": "directory",
"path": "/",
"children": [
{
"name": "src",
"type": "directory",
"path": "/src",
"children": [
{
"name": "main.py",
"type": "file",
"path": "/src/main.py",
"size": 1024,
"modified": "2025-11-09T10:30:00Z"
}
]
},
{
"name": "README.md",
"type": "file",
"path": "/README.md",
"size": 2048,
"modified": "2025-11-09T09:15:00Z"
}
]
}// Monitor directory
const watcher = chokidar.watch(projectPath, {
ignored: [
/(^|[\/\\])\../, // Hidden files
/node_modules/, // Dependencies
/__pycache__/, // Python cache
/.git/ // Git folder
],
persistent: true,
ignoreInitial: true,
awaitWriteFinish: {
stabilityThreshold: 300, // Wait 300ms after last change
pollInterval: 100
}
});
// Events
watcher
.on('add', path => {
console.log(`File added: ${path}`);
notifyClients({ type: 'add', path });
})
.on('change', path => {
console.log(`File changed: ${path}`);
notifyClients({ type: 'change', path });
})
.on('unlink', path => {
console.log(`File deleted: ${path}`);
notifyClients({ type: 'delete', path });
});const contextMenuItems = [
{ label: 'New File', icon: 'π', action: 'newFile' },
{ label: 'New Folder', icon: 'π', action: 'newFolder' },
{ label: 'Rename', icon: 'βοΈ', action: 'rename' },
{ label: 'Delete', icon: 'ποΈ', action: 'delete' },
{ label: 'Copy Path', icon: 'π', action: 'copyPath' },
{ label: 'Download', icon: 'β¬οΈ', action: 'download' }
];// backend/src/services/fileWatcher.service.js
const ignoredPatterns = [
'**/node_modules/**',
'**/__pycache__/**',
'**/.git/**',
'**/.vscode/**',
'**/*.pyc',
'**/.DS_Store',
'**/Thumbs.db'
];// Maximum file size for reading
const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB
// Maximum upload size
const MAX_UPLOAD_SIZE = 50 * 1024 * 1024; // 50MB// Wait time before triggering watch event
const DEBOUNCE_DELAY = 300; // millisecondsUser Input β Validate Name β Check Conflicts β
Create File β Update Tree β Notify Clients β
Sync to Drive (if enabled)
Editor Change β Debounce (300ms) β Save to Disk β
Update Container β Notify Watcher β Sync to Drive
User Confirms β Delete from Disk β Remove from Tree β
Stop Container Watch β Notify Clients β Sync to Drive
| Extension | Icon | Color |
|---|---|---|
.py |
π | Blue |
.js / .jsx |
βοΈ | Yellow |
.java |
β | Orange |
.cpp / .c |
π§ | Blue |
.html |
π | Red |
.css |
π¨ | Blue |
.json |
π | Green |
.md |
π | Gray |
| Directory | π | Yellow |
// Editor component
useEffect(() => {
const refreshInterval = setInterval(() => {
if (hasExternalChanges) {
reloadFileContent();
}
}, 1000); // Check every second
return () => clearInterval(refreshInterval);
}, []);if (fileModifiedExternally && hasUnsavedChanges) {
showConflictDialog({
options: [
'Keep my changes',
'Use file version',
'Show diff'
]
});
}backend/
workspace/
project-123/
src/
main.py
utils.py
tests/
test_main.py
README.md
{
"projectId": "project-123",
"name": "My Project",
"created": "2025-11-01T10:00:00Z",
"modified": "2025-11-09T14:30:00Z",
"files": 15,
"size": 52428800,
"language": "python"
}Solution:
# Refresh file tree
Click refresh icon in File Explorer
# Check file permissions
ls -la backend/workspace/project-id/
# Restart backend
cd backend
npm run devSolution:
# Check chokidar is installed
npm list chokidar
# Increase file watch limit (Linux)
echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf
sudo sysctl -pSolution:
- Close file in editor first
- Check file is not in use by container
- Verify file permissions
- Try renaming first, then delete