Boxy Project Guide
Tech Stack
- •Backend: Rust + Actix-web 4
- •Frontend: Vanilla JS + HTML (embedded)
- •Real-time: WebSocket broadcast
- •Tests: Playwright e2e
- •Deploy: Docker multi-stage
Project Structure
code
boxy/ ├── src/main.rs # Backend (all handlers) ├── static/ │ ├── index.html # Main app (HTML + JS) │ └── css/styles.css # Extracted CSS ├── data/ # App data (gitignored) │ ├── boards.json # Kanban boards + tasks │ ├── tiles.json # Dashboard tiles │ └── credentials.json # Stored credentials ├── uploads/ # File storage (gitignored) ├── tests/ui.spec.ts # Playwright e2e tests ├── docs/ # Architecture docs ├── Cargo.toml # Rust config └── package.json # Playwright config
Backend Patterns (src/main.rs)
Architecture
- •Single-file design - all handlers in main.rs
- •AppState holds: broadcaster, upload_dir, data_dir, max_upload_bytes
- •Settings from env:
BOX_PORT,BOX_UPLOAD_DIR,BOX_DATA_DIR,BOX_MAX_UPLOAD_BYTES
Security (CRITICAL)
rust
// Always use resolve_path_safe for user-provided paths
let filepath = resolve_path_safe(&state.upload_dir, Some(&user_path))
.ok_or_else(|| actix_web::error::ErrorForbidden("Invalid path"))?;
- •
clean_relative_path()- strips..and empty segments - •
resolve_path_safe()- canonicalizes and verifies path stays within base directory (prevents symlink attacks) - •Never trust user-provided paths directly
Handler Pattern
rust
#[get("/api/endpoint")]
async fn handler(
state: web::Data<AppState>,
query: web::Query<Params>,
) -> impl Responder {
// 1. Extract and sanitize input
// 2. Perform operation
// 3. Broadcast if mutation
// 4. Return JSON response
}
WebSocket Broadcasting
rust
// Broadcast all file mutations broadcast_update(&state.broadcaster, "upload", &path); // Actions: upload, rename, move, delete, folder
API Endpoints
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /api/files?path= | List directory |
| GET | /api/search?q= | Recursive file search |
| GET | /api/folders | All folder paths |
| GET | /api/download?path= | Download/preview file |
| GET | /api/health | Healthcheck |
| GET | /api/data/{type} | Load app data (boards, tiles, credentials) |
| POST | /api/upload?path= | Upload (multipart, supports folders) |
| POST | /api/folder | Create folder |
| POST | /api/rename | Rename item |
| POST | /api/move | Move item |
| POST | /api/delete | Delete item |
| POST | /api/data/{type} | Save app data with WebSocket broadcast |
Kanban Board System (Frontend)
Data Structure
javascript
// Server-side storage: data/boards.json
// Board structure
{
id: 'abc123',
name: 'My Board',
columns: [{ id: 'todo', name: 'Todo', order: 0 }, ...],
tasks: [{ id, title, description, status, priority, dueDate, tags, createdAt }, ...],
createdAt: 1705400000000
}
Key Functions
- •
loadBoards()- Async, loads from server API, auto-migrates localStorage on first run - •
saveBoards()- Async, persists to server, broadcasts via WebSocket - •
saveCurrentBoard()- Sync workingtasks/columnsto active board - •
loadTiles()/saveTiles()- Dashboard tiles (data/tiles.json) - •
loadCredentials()/saveCredentials()- Stored keys (data/credentials.json)
Working Variables
javascript
let boards = []; // All boards array let currentBoardId = null; // Active board let tasks = []; // Current board's tasks (working copy) let columns = []; // Current board's columns (working copy)
Cross-Browser Sync
- •Data stored server-side in
data/directory - •WebSocket broadcasts
data_syncevents on save - •All connected browsers auto-update when data changes
Quick Commands
bash
cargo run # Dev server (port 8086) cargo build --release # Production build npm run test:e2e # Playwright tests docker compose up --build # Docker deployment
Rules
- •Keep backend in single main.rs (no module splitting unless >1000 lines)
- •CSS is extracted to
static/css/styles.css, JS remains in index.html - •Always sanitize paths before filesystem access
- •Broadcast all mutations via WebSocket (including
data_syncfor app data) - •Use env vars for config with sensible defaults
- •Use TLDR before reading files — see tldr-first skill
Related Skills
- •tldr-first: Token-efficient exploration (TLDR commands first)
- •ui-patterns: Frontend CSS/JS patterns
- •quality-checklist: Pre-commit verification