Files
datacenter-designer/CLAUDE.md
Stefano Manfredi 3431a121a9 First commit
2025-10-27 11:57:38 +00:00

828 lines
26 KiB
Markdown

# CLAUDE.md - Developer Documentation
## Project Overview
**Datacenter Designer** is a web-based visual design tool for datacenter infrastructure. It allows users to create, manage, and visualize rack layouts, network devices, and their interconnections in both physical and logical views.
### Core Purpose
- Visual rack layout planning (physical positioning)
- Device placement within racks (U1-U42 slots with multi-unit form factors)
- Network connection mapping between devices
- Logical topology view (independent of physical layout)
- Export/import for data portability
### Technology Stack
- **Frontend**: Vanilla JavaScript (ES6 modules), Konva.js (canvas library), ag-Grid (tables), SheetJS (Excel export)
- **Backend**: Node.js, Express 4.x
- **Database**: SQLite3
- **No build process**: Direct ES6 modules, no bundler required
---
## Architecture
### High-Level Structure
```
┌─────────────────────────────────────────────────┐
│ Browser │
│ ┌────────────────────────────────────────────┐ │
│ │ app.js (Main Controller) │ │
│ │ - Orchestrates all managers │ │
│ │ - Handles modals and UI │ │
│ │ - API client │ │
│ │ - View switching (Physical/Logical) │ │
│ └────────────────────────────────────────────┘ │
│ │ │ │ │ │
│ ▼ ▼ ▼ ▼ │
│ ┌────────┐ ┌─────────┐ ┌─────────┐ ┌────────┐ │
│ │ Rack │ │ Device │ │Connect │ │ Table │ │
│ │Manager │ │Manager │ │Manager │ │Manager │ │
│ └────────┘ └─────────┘ └─────────┘ └────────┘ │
│ │ │ │ │ │
│ └──────────┴───────────┴──────────┘ │
│ │ │
│ Konva.js Canvas │
└────────────────────│──────────────────────────────┘
│ HTTP/REST API
┌────────────────────▼──────────────────────────────┐
│ Server │
│ ┌──────────────────────────────────────────────┐│
│ │ server.js (Express Router) ││
│ │ - RESTful endpoints ││
│ │ - Request/response handling ││
│ └──────────────────────────────────────────────┘│
│ │ │
│ ┌──────────────────▼──────────────────────────┐ │
│ │ db.js (Database Layer) │ │
│ │ - Promise-wrapped SQLite operations │ │
│ │ - Schema management │ │
│ └──────────────────────────────────────────────┘ │
│ │ │
│ SQLite Database File │
└───────────────────────────────────────────────────┘
```
### File Organization
```
datacenter-designer/
├── server/
│ ├── server.js (276 LOC) - Express routes
│ └── db.js (547 LOC) - Database operations
├── public/
│ ├── index.html (193 LOC) - Main HTML structure
│ ├── css/
│ │ └── style.css (741 LOC) - All styles
│ └── js/
│ ├── app.js (1719 LOC) - Main controller
│ ├── rack-manager.js (488 LOC) - Rack rendering/interaction
│ ├── device-manager.js (513 LOC) - Device rendering/interaction
│ ├── connection-manager.js (901 LOC) - Connection lines/waypoints
│ └── table-manager.js (792 LOC) - ag-Grid table views
├── database/
│ └── datacenter.db (Created at runtime)
├── package.json
└── README.md
Total: ~5,236 lines of code
```
---
## Critical Review
### ✅ Strengths
1. **Clean Separation of Concerns**: Manager pattern isolates rack, device, connection, and table logic
2. **Simple Tech Stack**: No build process, direct ES6 modules, minimal dependencies
3. **RESTful API**: Clear HTTP API with predictable endpoints
4. **SQLite Persistence**: Appropriate for local/desktop deployment
5. **Konva.js Integration**: Good choice for canvas-based diagramming
6. **Dual View System**: Physical (rack-based) and logical (topology) views
### ❌ Issues & Anti-Patterns
#### 1. **Monolithic `app.js` (1719 lines)**
- **Violation**: Single Responsibility Principle
- **Contains**: API client, modal management, zoom/pan, view switching, event coordination, export/import
- **Should be**: Split into smaller modules (API client, ModalManager, StateManager, UIController)
#### 2. **Repetitive Code (DRY Violations)**
```javascript
// Repeated everywhere in server.js:
try {
// ... logic
} catch (err) {
res.status(500).json({ error: err.message });
}
// Repeated modal patterns in app.js
modal.classList.remove('hidden');
// ...setup
modal.classList.add('hidden');
```
#### 3. **Database Layer Issues**
- **Callback-based sqlite3**: Manually wrapping every query in Promises
- **No migration system**: Schema changes via ALTER TABLE with error swallowing (lines 106-140 in db.js)
- **Verbose**: Every CRUD operation is 10-15 lines of boilerplate
- **Better alternative**: `better-sqlite3` (synchronous, simpler, faster)
#### 4. **Hard-Coded Magic Numbers**
```javascript
// Scattered throughout codebase:
const maxSlots = 42; // Rack slots
const rackWidth = 520; // Rack dimensions
const rackHeight = 1510;
const gridSize = 600; // Grid spacing
const deviceHeight = 32;
const deviceSpacing = 2;
const topMargin = 10;
```
**Should be**: Centralized in `config.js` with semantic names
#### 5. **API Client Design**
```javascript
class API {
// One method per endpoint - not scalable
getRacks() { return this.request('/api/racks?projectId=...'); }
createRack(...) { return this.request(...); }
updateRackPosition(...) { return this.request(...); }
// ... 30+ methods
}
```
**Should be**: Generic resource methods or use a library
#### 6. **CSS Organization**
- **741 lines in one file**: No modularity
- **Hard-coded colors**: `#4A90E2`, `#f5f5f5`, etc. repeated
- **No CSS variables**: Should use `--primary-color`, `--bg-color`, etc.
- **No responsiveness**: No media queries, fixed dimensions
- **No dark mode support**: Hard-coded light theme only
#### 7. **State Management**
- **Scattered state**: Each manager holds its own state in Maps
- **DOM as state**: Using localStorage without versioning
- **No synchronization**: Manual `canvas-data-changed` events
- **No undo/redo**: No state history
#### 8. **Input Validation**
- **Server**: Minimal validation (trusts client)
- **Client**: No form validation, uses `prompt()` for input
- **No schema validation**: No Zod, Joi, or similar
#### 9. **Error Handling**
```javascript
// Current:
catch (err) {
console.error('Failed:', err);
alert('Failed: ' + err.message);
}
```
**Should be**: Toast notifications, user-friendly messages, error boundaries
#### 10. **Export/Import**
- **No versioning**: Export format has version field but isn't checked properly
- **Monolithic**: One giant JSON blob
- **No incremental import**: All-or-nothing
### ⚠️ Over-Engineering
1. **View-Specific Waypoints**: `waypoints_physical` and `waypoints_logical` stored separately
- **Better**: Store once, transform with view matrix
2. **Separate `rack_units` column**: Could be derived from `device_type`
3. **Multiple modal patterns**: Overlapping modal handling code
### ⚠️ Under-Engineering
1. **No undo/redo**: Critical for a design tool
2. **No keyboard shortcuts**: Only `Esc` and `Del` supported
3. **No search/filter**: As data grows, navigation becomes difficult
4. **No loading states**: UI freezes during operations
5. **No optimistic updates**: Waits for server before updating UI
6. **No batch operations**: Can't select multiple racks/devices
7. **No auto-save**: Only manual saves via export
---
## Better Technologies / Alternatives
### Database
**Current**: `sqlite3` (callback-based)
**Better**: `better-sqlite3`
- Synchronous API (simpler code)
- 2-3x faster
- No callback hell
```javascript
// Current:
return new Promise((resolve, reject) => {
this.db.get('SELECT * FROM racks WHERE id = ?', [id], (err, row) => {
if (err) reject(err);
else resolve(row);
});
});
// With better-sqlite3:
return db.prepare('SELECT * FROM racks WHERE id = ?').get(id);
```
### State Management
**Current**: Scattered Maps in each manager
**Better Options**:
1. **Zustand** (100 lines, minimal API)
2. **Valtio** (proxy-based reactivity)
3. **Nanostores** (atomic stores)
### API Client
**Current**: Custom 30+ method API class
**Better**: **ky** or **axios** with interceptors
```javascript
// Generic resource client:
const api = {
get: (url) => ky.get(url).json(),
post: (url, data) => ky.post(url, { json: data }).json(),
// ... + error handling in interceptors
};
```
### CSS Organization
**Current**: 741-line monolithic file
**Better**: Split by concern + CSS variables
```css
/* config.css */
:root {
--primary-color: #4A90E2;
--bg-color: #f5f5f5;
--rack-width: 520px;
--rack-height: 1510px;
}
/* components/rack.css */
/* components/device.css */
/* layout.css */
/* theme.css */
```
### Configuration
**Current**: Hard-coded everywhere
**Better**: `config.js`
```javascript
export const RACK_CONFIG = {
WIDTH: 520,
HEIGHT: 1510,
SLOTS: 42,
MARGIN: { top: 10, right: 10, bottom: 10, left: 10 }
};
export const GRID_CONFIG = {
HORIZONTAL: 600,
VERTICAL: 1610
};
```
### Validation
**Current**: None
**Better**: **Zod** for schema validation
```javascript
const RackSchema = z.object({
name: z.string().min(1).max(50),
x: z.number().finite(),
y: z.number().finite()
});
```
---
## Recommended Refactoring Strategy
### Option A: In-Place Refactoring (Direct Edit)
**Pros**:
- Keep git history
- Incremental changes
- Can test at each step
**Cons**:
- Risk of breaking working features
- Harder to compare old vs new
- No fallback
### Option B: Release Candidate Approach (Recommended)
**Pros**:
- Clean slate while keeping original
- Can compare side-by-side
- Easy to revert
- Clear migration path
**Cons**:
- Duplicated files temporarily
- Need to sync any new features
**Proposed Structure**:
```
datacenter-designer/
├── rc/ # New refactored version
│ ├── server/
│ │ ├── config.js # NEW: Configuration
│ │ ├── db.js # REFACTORED: better-sqlite3
│ │ ├── routes/ # NEW: Split routes
│ │ │ ├── projects.js
│ │ │ ├── racks.js
│ │ │ ├── devices.js
│ │ │ └── connections.js
│ │ └── server.js # SIMPLIFIED: Just setup
│ ├── public/
│ │ ├── index.html # UPDATED: More semantic
│ │ ├── css/
│ │ │ ├── config.css # NEW: CSS variables
│ │ │ ├── layout.css
│ │ │ ├── components.css
│ │ │ └── theme.css
│ │ └── js/
│ │ ├── config.js # NEW: Constants
│ │ ├── lib/
│ │ │ ├── api.js # REFACTORED: Simplified
│ │ │ ├── state.js # NEW: State manager
│ │ │ └── ui.js # NEW: UI utilities
│ │ ├── managers/
│ │ │ ├── rack-manager.js
│ │ │ ├── device-manager.js
│ │ │ ├── connection-manager.js
│ │ │ └── table-manager.js
│ │ └── app.js # SLIMMED: Orchestrator only
│ └── database/
│ └── .gitkeep
├── server/ # OLD: Keep during transition
├── public/ # OLD: Keep during transition
├── .gitignore
├── CLAUDE.md # This file
├── README.md
└── package.json
```
---
## Refactoring Checklist
### Phase 1: Foundation (Day 1-2)
- [ ] Create `rc/` directory structure
- [ ] Setup `.gitignore` properly
- [ ] Create `rc/server/config.js` with all constants
- [ ] Create `rc/public/js/config.js` with frontend constants
- [ ] Port database to `better-sqlite3`
- [ ] Create migration system
- [ ] Split CSS into modules with CSS variables
- [ ] Make layout responsive (media queries)
### Phase 2: Backend (Day 3)
- [ ] Split routes into separate files
- [ ] Add input validation (Zod or similar)
- [ ] Implement error middleware
- [ ] Add request logging
- [ ] Create API documentation (OpenAPI/Swagger)
### Phase 3: Frontend Core (Day 4-5)
- [ ] Extract API client to `lib/api.js`
- [ ] Extract state management to `lib/state.js`
- [ ] Extract UI utilities to `lib/ui.js` (modal manager, toast, etc.)
- [ ] Slim down `app.js` to orchestration only
- [ ] Refactor managers to use new state system
### Phase 4: Features & UX (Day 6-7)
- [ ] Add toast notifications (replace `alert()`)
- [ ] Add loading states
- [ ] Add keyboard shortcuts
- [ ] Add undo/redo system
- [ ] Add search/filter
- [ ] Add batch operations
- [ ] Improve error messages
### Phase 5: Testing & Documentation (Day 8)
- [ ] Add unit tests for backend
- [ ] Add integration tests
- [ ] Update README.md
- [ ] Update CLAUDE.md
- [ ] Add inline JSDoc comments
- [ ] Performance testing
### Phase 6: Migration (Day 9-10)
- [ ] Test thoroughly
- [ ] Migrate data from old DB if needed
- [ ] Move `rc/` to root
- [ ] Archive old code to `old/`
- [ ] Update package.json scripts
- [ ] Final testing
---
## Key Principles to Follow
### KISS (Keep It Simple, Stupid)
- Avoid abstractions unless proven necessary
- Prefer composition over inheritance
- Use vanilla JS unless library provides clear value
### DRY (Don't Repeat Yourself)
- Extract repeated patterns (error handling, modal management)
- Use constants instead of magic numbers
- Create reusable utility functions
### SOLID Principles
- **S**: Single Responsibility - Each module does one thing
- **O**: Open/Closed - Extend without modifying
- **L**: Liskov Substitution - Subtypes must be substitutable
- **I**: Interface Segregation - Many specific interfaces > one general
- **D**: Dependency Inversion - Depend on abstractions
### WORM (Write Once, Read Many)
- Optimize for read performance
- Use indices on frequently queried columns
- Cache frequently accessed data
- Minimize database writes
### Additional Principles
- **Fail Fast**: Validate early, throw errors quickly
- **Convention over Configuration**: Sensible defaults
- **Progressive Enhancement**: Works without JS, enhanced with it
- **Accessibility**: Keyboard navigation, ARIA labels, screen reader support
---
## Responsive Design Strategy
### Breakpoints
```css
/* Mobile: < 768px */
@media (max-width: 767px) {
/* Stack toolbar items, hide non-essential controls */
}
/* Tablet: 768px - 1024px */
@media (min-width: 768px) and (max-width: 1024px) {
/* Optimize for touch, larger buttons */
}
/* Desktop: > 1024px */
@media (min-width: 1025px) {
/* Full feature set */
}
```
### Layout Strategies
1. **Toolbar**: Collapse to hamburger menu on mobile
2. **Canvas**: Always full viewport minus toolbar
3. **Tables**: Horizontal scroll on mobile, fixed on desktop
4. **Modals**: Full-screen on mobile, centered on desktop
5. **Context Menus**: Bottom sheet on mobile, popup on desktop
### Touch Support
- Increase hit targets to 44x44px minimum
- Add touch gestures (pinch-zoom, two-finger pan)
- Show hover states on touch as active states
- Use native select/input elements on mobile
---
## Performance Considerations
### Canvas Rendering
- Use `batchDraw()` instead of `draw()` for multiple updates
- Implement viewport culling (don't render off-screen items)
- Use `cache()` for static shapes
- Debounce pan/zoom updates
### Database
- Add indices on foreign keys
- Use transactions for bulk operations
- Implement connection pooling (if moving to client-server)
- Lazy-load connections (don't load all at startup)
### Network
- Implement request debouncing for auto-save
- Use HTTP caching headers
- Compress API responses (gzip)
- Implement pagination for large datasets
---
## Security Considerations
### SQL Injection
- ✅ Already using parameterized queries
- [ ] Add input sanitization layer
- [ ] Validate all inputs on server
### XSS (Cross-Site Scripting)
- [ ] Sanitize user input before displaying
- [ ] Use `textContent` instead of `innerHTML` where possible
- [ ] Add Content Security Policy headers
### CSRF (Cross-Site Request Forgery)
- [ ] Add CSRF tokens for state-changing operations
- [ ] Use SameSite cookies
### File Upload
- If adding import from file:
- [ ] Validate file size
- [ ] Validate file type
- [ ] Scan for malicious content
---
## .gitignore Strategy
To avoid pushing sensitive or generated files:
```gitignore
# Dependencies
node_modules/
package-lock.json # Optional: some include, some exclude
# Database (user data)
database/*.db
database/*.db-shm
database/*.db-wal
*.db
*.db-shm
*.db-wal
# Logs
logs/
*.log
npm-debug.log*
# Environment variables
.env
.env.local
.env.*.local
# IDE
.vscode/
.idea/
*.swp
*.swo
*~
.DS_Store
# Build outputs (if added later)
dist/
build/
.cache/
# Temporary files
tmp/
temp/
*.tmp
# OS files
Thumbs.db
.DS_Store
# Claude-specific (optional)
.claude/
```
**Important**: If database contains sample data for demonstrations, create a separate `database/sample.db` and explicitly include it:
```gitignore
# Ignore user databases
database/*.db
# But include sample
!database/sample.db
```
---
## Testing Strategy
### Unit Tests
- Test database operations in isolation
- Test utility functions
- Test state management
- Use: **Vitest** or **Jest**
### Integration Tests
- Test API endpoints
- Test full CRUD workflows
- Use: **Supertest** + **Vitest**
### E2E Tests
- Test critical user journeys
- Test cross-browser compatibility
- Use: **Playwright** or **Cypress**
### Test Structure
```javascript
// Example: tests/db.test.js
import { describe, it, expect, beforeEach } from 'vitest';
import db from '../server/db.js';
describe('Database - Racks', () => {
beforeEach(() => {
// Reset database to known state
});
it('should create a rack', () => {
const rack = db.createRack(1, 'RACK01', 0, 0);
expect(rack.id).toBeDefined();
expect(rack.name).toBe('RACK01');
});
it('should not create duplicate rack names in same project', () => {
db.createRack(1, 'RACK01', 0, 0);
expect(() => db.createRack(1, 'RACK01', 100, 0)).toThrow();
});
});
```
---
## Future Enhancements Roadmap
### Phase 1: Core UX Improvements
- [ ] Undo/redo system
- [ ] Enhanced keyboard shortcuts
- [ ] Toast notifications (replace browser alerts)
- [ ] Loading states
- [ ] Search and filter functionality
- [ ] Batch operations (select multiple items)
- [ ] Auto-save functionality
### Phase 2: Multi-User Support
- [ ] User management system
- [ ] Authentication and authorization
- [ ] OIDC-compatible external SSO integration
- [ ] Project sharing between users
- [ ] Role-based access control (view/edit/admin)
- [ ] User profile management
### Phase 3: Collaboration
- [ ] Real-time collaborative editing (WebSocket)
- [ ] Concurrent access management
- [ ] User presence indicators
- [ ] Change notifications
- [ ] Conflict resolution
- [ ] Version history / snapshots
- [ ] Activity audit logging
### Phase 4: Advanced Features
- [ ] Custom device types (user-defined)
- [ ] Cable labeling and management
- [ ] VLAN visualization
- [ ] IP address management
- [ ] Documentation generation (diagrams, BOMs)
- [ ] Import from other formats (Visio, Lucidchart)
- [ ] PostgreSQL/MySQL support
### Phase 5: Platform Enhancements
- [ ] Dark mode
- [ ] Mobile/tablet responsive design
- [ ] 3D rack visualization
- [ ] Cable routing visualization
- [ ] Enhanced export formats
- [ ] API for 3rd party integrations
- [ ] Backup/restore automation
---
## Common Gotchas & Pitfalls
### Konva-Specific
1. **Coordinate Systems**: Konva uses top-left origin, racks use bottom-up slot numbering (U1 at bottom)
2. **Event Bubbling**: Events on canvas can propagate unexpectedly - use `e.cancelBubble = true`
3. **Memory Leaks**: Always destroy unused layers/shapes
4. **Performance**: Too many shapes? Use `virtualizer` pattern
### SQLite-Specific
1. **Foreign Keys**: Must enable explicitly with `PRAGMA foreign_keys = ON`
2. **Concurrency**: Only one write at a time - queue writes or use WAL mode
3. **Migrations**: No built-in system - roll your own or use library
4. **Type System**: Dynamic typing can surprise you (stores as INTEGER, returns as Number)
### CSS/Canvas Interaction
1. **Canvas Size**: Must set both CSS size and Konva stage size
2. **DPI Scaling**: High-DPI displays may need pixel ratio adjustment
3. **Touch Events**: Handle both mouse and touch events separately
---
## Contributing Guidelines
### Code Style
- **Indentation**: 2 spaces
- **Quotes**: Single quotes for strings
- **Semicolons**: Required
- **Naming**: camelCase for variables/functions, PascalCase for classes
- **Line Length**: 100 characters max
- **Comments**: JSDoc for public APIs, inline for complex logic
### Commit Messages
Follow Conventional Commits:
```
feat: add undo/redo system
fix: correct device positioning in logical view
docs: update CLAUDE.md with testing strategy
refactor: extract API client to separate file
test: add unit tests for database operations
chore: update dependencies
```
### Pull Request Process
1. Create feature branch from `main`
2. Make changes with tests
3. Update documentation
4. Run linter and tests
5. Submit PR with description
6. Address review comments
7. Merge when approved
---
## Debugging Tips
### Backend Debugging
```bash
# Enable SQLite query logging
DEBUG=sqlite3 npm start
# Enable Express debug logging
DEBUG=express:* npm start
# Enable all debug logging
DEBUG=* npm start
```
### Frontend Debugging
```javascript
// Enable Konva debugging
Konva.showWarnings = true;
// Log all API calls
api.request = new Proxy(api.request, {
apply(target, thisArg, args) {
console.log('[API]', args[0], args[1]);
return target.apply(thisArg, args);
}
});
```
### Common Issues
1. **Canvas not updating**: Call `.batchDraw()` on layer
2. **Events not firing**: Check if shape is `listening(true)`
3. **Drag not working**: Check if shape is `draggable(true)` and parent layer is listening
4. **Database locked**: Close all connections, check for transactions
5. **CORS errors**: Ensure frontend and backend are on same origin or CORS is enabled
---
## Glossary
- **Rack**: Physical equipment cabinet with 42U slots
- **U / Rack Unit**: Standard height measurement (1U = 1.75 inches)
- **Slot**: Position within a rack (U1 at bottom, U42 at top)
- **Device**: Network equipment (switch, router, firewall, etc.)
- **Form Factor**: Device height in rack units (1U, 2U, 4U, etc.)
- **Connection**: Network link between two device ports
- **Waypoint**: Intermediate point in a connection line for routing
- **Physical View**: Rack-based layout showing physical positioning
- **Logical View**: Topology view ignoring physical constraints
- **Project**: Isolated workspace containing racks, devices, connections
- **Canvas**: Konva.js drawing surface
- **Stage**: Top-level Konva container
- **Layer**: Konva organizational unit (rack layer, device layer, connection layer)
- **Shape**: Individual Konva element (rectangle, text, line, etc.)
---
## Links & Resources
### Dependencies
- [Konva.js Documentation](https://konvajs.org/docs/)
- [ag-Grid Documentation](https://www.ag-grid.com/javascript-data-grid/)
- [SheetJS Documentation](https://docs.sheetjs.com/)
- [SQLite Documentation](https://www.sqlite.org/docs.html)
- [better-sqlite3](https://github.com/WiseLibs/better-sqlite3)
### Design Patterns
- [JavaScript Design Patterns](https://www.patterns.dev/)
- [SOLID Principles](https://www.digitalocean.com/community/conceptual_articles/s-o-l-i-d-the-first-five-principles-of-object-oriented-design)
- [Martin Fowler - Refactoring](https://refactoring.com/)
### Best Practices
- [Airbnb JavaScript Style Guide](https://github.com/airbnb/javascript)
- [Clean Code JavaScript](https://github.com/ryanmcdermott/clean-code-javascript)
- [Web Performance Best Practices](https://web.dev/fast/)
---
## Revision History
| Version | Date | Author | Changes |
|---------|------|--------|---------|
| 0.1.0 | 2025-10-26 | Claude | Initial release - comprehensive documentation |
---
## License
MIT License - See LICENSE file for details