- Canvas: Infinite zoomable workspace with LOD and navigation - Spotlight: Fuzzy search with type filters and view shortcuts - Krate: Window group container with non-overlapping placement - Detail Window: YAML/Describe/Logs/Shell views with maximize - Top Bar: Cluster info, user presence, admin toggle - Admin Drawer: Multi-user presence and spectate functionality - Minimap: Browse and navigate canvas overview - Collection Window: List/tree views with filtering and sorting - Shell/Logs: Real-time terminal and log streaming - Backend: Go service with K8s API, WebSocket handlers, CRDT sync - Architecture: Full project structure and tech stack
313 lines
7.9 KiB
Markdown
313 lines
7.9 KiB
Markdown
# Top-Level Application Architecture
|
|
|
|
## Tech Stack Recommendations
|
|
|
|
### Frontend
|
|
- **Framework**: React 18 + TypeScript
|
|
- **Styling**: CSS-in-JS (styled-components or vanilla-extract) or Tailwind CSS
|
|
- **Terminal**: xterm.js
|
|
- **Real-Time**: Yjs + y-websocket (CRDT collaboration)
|
|
- **Build Tool**: Vite
|
|
- **Fonts**: IBM Plex Sans + IBM Plex Mono (Google Fonts or self-hosted)
|
|
- **State Management**: Zustand or React Context (keep it simple)
|
|
|
|
### Backend
|
|
- **Language**: Go
|
|
- **Kubernetes Client**: kubernetes/client-go
|
|
- **WebSockets**: gorilla/websocket
|
|
- **CRDT Backend**: Redis (single-node) or y-leveldb/y-mongodb (multi-node)
|
|
- **Build/Deployment**: Docker, Kubernetes
|
|
|
|
## Project Structure
|
|
|
|
```
|
|
krates/
|
|
├── client/ # Frontend application
|
|
│ ├── src/
|
|
│ │ ├── components/ # React components
|
|
│ │ │ ├── canvas/ # Canvas and world layer
|
|
│ │ │ │ ├── WorldLayer.tsx
|
|
│ │ │ │ ├── GridOverlay.tsx
|
|
│ │ │ │ └── Minimap.tsx
|
|
│ │ │ ├── krate/ # Krate and windows
|
|
│ │ │ │ ├── Krate.tsx
|
|
│ │ │ │ ├── KrateHeader.tsx
|
|
│ │ │ │ ├── DetailWindow.tsx
|
|
│ │ │ │ └── CollectionWindow.tsx
|
|
│ │ │ ├── Spotlight.tsx
|
|
│ │ │ ├── TopBar.tsx
|
|
│ │ │ ├── AdminDrawer.tsx
|
|
│ │ │ ├── ShellTerminal.tsx # xterm.js wrapper
|
|
│ │ │ └── LogsViewer.tsx
|
|
│ │ ├── hooks/ # Custom React hooks
|
|
│ │ │ ├── useCanvas.ts
|
|
│ │ │ ├── useSpotlight.ts
|
|
│ │ │ ├── useWebSocket.ts
|
|
│ │ │ └── useKubernetes.ts
|
|
│ │ ├── state/ # State management
|
|
│ │ │ ├── canvasStore.ts
|
|
│ │ │ ├── krateStore.ts
|
|
│ │ │ └── spotlightStore.ts
|
|
│ │ ├── utils/
|
|
│ │ │ ├── fuzzy.ts # Fuzzy search algorithm
|
|
│ │ │ ├── crdt.ts # Yjs setup
|
|
│ │ │ ├── keyboard.ts # Keyboard handling
|
|
│ │ │ └── math.ts # Canvas math helpers
|
|
│ │ ├── App.tsx
|
|
│ │ └── main.tsx
|
|
│ ├── public/ # Static assets
|
|
│ └── package.json
|
|
│
|
|
├── server/ # Backend service
|
|
│ ├── cmd/
|
|
│ │ └── server/
|
|
│ │ └── main.go
|
|
│ ├── internal/
|
|
│ │ ├── api/ # HTTP endpoints
|
|
│ │ │ ├── handlers/
|
|
│ │ │ └── routes.go
|
|
│ │ ├── ws/ # WebSocket handlers
|
|
│ │ │ ├── shell.go
|
|
│ │ │ ├── logs.go
|
|
│ │ │ └── watch.go
|
|
│ │ ├── k8s/ # Kubernetes client wrappers
|
|
│ │ │ ├── client.go
|
|
│ │ │ ├── resources.go
|
|
│ │ │ └── watch.go
|
|
│ │ ├── crdt/ # Yjs integration
|
|
│ │ │ └── provider.go
|
|
│ │ └── auth/ # Authentication/authorization
|
|
│ │ └── token.go
|
|
│ ├── pkg/ # Reusable packages
|
|
│ └── go.mod
|
|
│
|
|
├── design/ # This folder
|
|
│ ├── canvas.md
|
|
│ ├── spotlight.md
|
|
│ ├── krate.md
|
|
│ ├── detail-window.md
|
|
│ ├── top-bar.md
|
|
│ ├── admin-drawer.md
|
|
│ ├── minimap.md
|
|
│ ├── backend.md
|
|
│ └── architecture.md
|
|
│
|
|
└── README.md
|
|
```
|
|
|
|
## State Management Strategy
|
|
|
|
### Global State (Zustand)
|
|
```typescript
|
|
// canvasStore.ts
|
|
interface CanvasState {
|
|
camX: number;
|
|
camY: number;
|
|
zoom: number;
|
|
flying: boolean;
|
|
dragging: boolean;
|
|
collapsed: boolean;
|
|
spacePanning: boolean;
|
|
}
|
|
|
|
// krateStore.ts
|
|
interface KrateStore {
|
|
krates: Map<string, Krate>;
|
|
selectedKrateId: string | null;
|
|
}
|
|
|
|
// spotlightStore.ts
|
|
interface SpotlightStore {
|
|
open: boolean;
|
|
query: string;
|
|
filterType: string | null;
|
|
sel: number;
|
|
navigated: boolean;
|
|
}
|
|
|
|
// userStore.ts
|
|
interface UserStore {
|
|
currentUser: User;
|
|
presence: Map<string, UserPresence>;
|
|
}
|
|
```
|
|
|
|
### Collection State (Per-Window)
|
|
```typescript
|
|
// stored in krate.windows[].state or separate map
|
|
interface CollectionState {
|
|
search: string;
|
|
view: 'list' | 'tree';
|
|
sel: number;
|
|
}
|
|
```
|
|
|
|
## WebSocket Architecture
|
|
|
|
### Connection Setup
|
|
```
|
|
1. Connect to /ws/sync (CRDT + awareness)
|
|
2. Connect to /ws/watch (resource updates)
|
|
3. On-demand connections:
|
|
- /ws/shell (when shell window opened)
|
|
- /ws/logs (when logs window opened)
|
|
```
|
|
|
|
### Message Format
|
|
```
|
|
// CRDT sync
|
|
{
|
|
type: 'sync',
|
|
payload: Uint8Array // Yjs update encoded
|
|
}
|
|
|
|
// Awareness presence
|
|
{
|
|
type: 'awareness',
|
|
updates: UserPresence[]
|
|
}
|
|
|
|
// Resource watch
|
|
{
|
|
type: 'resource',
|
|
action: 'add' | 'update' | 'delete',
|
|
kind: string, // 'Pod', 'Deployment', etc.
|
|
resource: K8sObject
|
|
}
|
|
|
|
// Shell output
|
|
{
|
|
type: 'shell:output',
|
|
data: string // stdout/stderr
|
|
}
|
|
|
|
// Shell input
|
|
{
|
|
type: 'shell:input',
|
|
data: string // keypresses, etc.
|
|
}
|
|
```
|
|
|
|
## Build & Deployment
|
|
|
|
### Development
|
|
```
|
|
# Frontend
|
|
cd client
|
|
npm install
|
|
npm run dev # Vite dev server
|
|
|
|
# Backend
|
|
cd server
|
|
go run cmd/server/main.go
|
|
```
|
|
|
|
### Production
|
|
```
|
|
# Backend
|
|
cd server
|
|
go build -o krates-server
|
|
./krates-server --config config.yaml
|
|
|
|
# Frontend
|
|
cd client
|
|
npm run build
|
|
# Serve static files with nginx or similar
|
|
```
|
|
|
|
### Docker
|
|
```dockerfile
|
|
# Backend Dockerfile
|
|
FROM golang:1.21-alpine
|
|
WORKDIR /app
|
|
COPY go.mod go.sum ./
|
|
RUN go mod download
|
|
COPY . .
|
|
RUN go build -o /krates ./cmd/server
|
|
CMD ["/krates"]
|
|
|
|
# Frontend Dockerfile
|
|
FROM node:20-alpine
|
|
WORKDIR /app
|
|
COPY package*.json ./
|
|
RUN npm ci --only=production
|
|
COPY . .
|
|
RUN npm run build
|
|
CMD ["npm", "start"]
|
|
```
|
|
|
|
## Performance Optimization
|
|
|
|
### Frontend
|
|
1. **Virtualization**: Don't render off-screen krates if world is large
|
|
2. **Debounce**: 16ms debouncing on all frequent events
|
|
3. **Web Workers**: Fuzzy search in worker for large datasets
|
|
4. **Memoization**: Reuse expensive calculations (transforms, layouts)
|
|
5. **CSS optimization**: Use transforms, avoid layout thrashing
|
|
|
|
### Backend
|
|
1. **Caching**: Cache static resource lists (with watch for updates)
|
|
2. **Connection pooling**: Reuse k8s API connections
|
|
3. **Rate limiting**: Per-user limits on WebSocket connections
|
|
4. **Compression**: WebSocket message compression
|
|
5. **Batching**: Batch resource updates when possible
|
|
|
|
## Testing Strategy
|
|
|
|
### Unit Tests
|
|
- Fuzzy search algorithm
|
|
- Coordinate transformations
|
|
- CRDT conflict resolution
|
|
- WebSocket message formatting
|
|
|
|
### Integration Tests
|
|
- Kubernetes API integration
|
|
- WebSocket connection lifecycle
|
|
- Multi-user presence sync
|
|
|
|
### E2E Tests
|
|
- User flows: search → spotlight → krate creation
|
|
- Multi-user: user A creates krate, user B sees it
|
|
- Drag/drop and resize interactions
|
|
|
|
## Security Checklist
|
|
|
|
### Authentication
|
|
- [ ] JWT or session-based auth on all WebSocket connections
|
|
- [ ] Token validation on every message
|
|
- [ ] Expire inactive sessions
|
|
|
|
### Authorization
|
|
- [ ] Namespace-level RBAC enforcement
|
|
- [ ] Block access to unauthorized resources
|
|
- [ ] Audit logging
|
|
|
|
### Data Protection
|
|
- [ ] Never log sensitive data (especially decoded secrets)
|
|
- [ ] Sanitize user inputs
|
|
- [ ] Escape HTML in text display
|
|
- [ ] CSP headers on frontend
|
|
|
|
### Network
|
|
- [ ] TLS/HTTPS for all connections
|
|
- [ ] WSS for WebSocket connections
|
|
- [ ] Origin validation on WebSocket upgrade
|
|
|
|
## Future Enhancements (Backlog)
|
|
|
|
### Already Identified
|
|
- Tile layout presets (logs hero, split, grid)
|
|
- Port-forwarding window
|
|
- Events window
|
|
- Diff view (compare YAMLs)
|
|
- Multi-cluster support
|
|
|
|
### Additional Ideas
|
|
- Keyboard shortcuts customization
|
|
- Workspace presets (save/restore layouts)
|
|
- Annotations/markers on canvas
|
|
- Shared annotations (multi-user notes)
|
|
- History/undo stack
|
|
- Keyboard macro recording
|
|
- Export workspace (screenshots, layouts)
|