Rewrite with modern stack
Major refactor from simple HTML/JS app to modern full-stack TypeScript application: ## Architecture Changes - Migrated to monorepo structure with workspaces (backend, frontend, shared) - Backend: Node.js + Express + TypeScript + Socket.IO - Frontend: Next.js 15.5 + React 19 + TypeScript + Tailwind CSS - Shared: Common types and utilities across packages ## Key Features Implemented - Real-time WebSocket collaboration via Socket.IO - Virtual canvas with chunked loading for performance - Modern UI with dark mode and responsive design - Mock database system for easy development (Redis/PostgreSQL compatible) - Comprehensive error handling and rate limiting - User presence and cursor tracking - Infinite canvas support with zoom/pan controls ## Performance Optimizations - Canvas virtualization - only renders visible viewport - Chunked pixel data loading (64x64 pixel chunks) - Optimized WebSocket protocol - Memory-efficient state management with Zustand ## Development Experience - Full TypeScript support across all packages - Hot reload for both frontend and backend - Docker support for production deployment - Comprehensive linting and formatting - Automated development server startup ## Fixed Issues - Corrected start script paths - Updated environment configuration - Fixed ESLint configuration issues - Ensured all dependencies are properly installed - Verified build process works correctly 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
5eb7a1482e
commit
98f290a662
69 changed files with 17771 additions and 1589 deletions
44
shared/src/utils/canvas.ts
Normal file
44
shared/src/utils/canvas.ts
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
import { CANVAS_CONFIG } from '../constants/canvas';
|
||||
|
||||
export function getChunkCoordinates(x: number, y: number, chunkSize = CANVAS_CONFIG.DEFAULT_CHUNK_SIZE) {
|
||||
return {
|
||||
chunkX: Math.floor(x / chunkSize),
|
||||
chunkY: Math.floor(y / chunkSize),
|
||||
};
|
||||
}
|
||||
|
||||
export function getPixelKey(x: number, y: number): string {
|
||||
return `${x},${y}`;
|
||||
}
|
||||
|
||||
export function parsePixelKey(key: string): { x: number; y: number } {
|
||||
const [x, y] = key.split(',').map(Number);
|
||||
return { x, y };
|
||||
}
|
||||
|
||||
export function getChunkKey(chunkX: number, chunkY: number): string {
|
||||
return `${chunkX},${chunkY}`;
|
||||
}
|
||||
|
||||
export function parseChunkKey(key: string): { chunkX: number; chunkY: number } {
|
||||
const [chunkX, chunkY] = key.split(',').map(Number);
|
||||
return { chunkX, chunkY };
|
||||
}
|
||||
|
||||
export function getChunkBounds(chunkX: number, chunkY: number, chunkSize = CANVAS_CONFIG.DEFAULT_CHUNK_SIZE) {
|
||||
return {
|
||||
minX: chunkX * chunkSize,
|
||||
minY: chunkY * chunkSize,
|
||||
maxX: (chunkX + 1) * chunkSize - 1,
|
||||
maxY: (chunkY + 1) * chunkSize - 1,
|
||||
};
|
||||
}
|
||||
|
||||
export function isValidColor(color: string): boolean {
|
||||
const hexRegex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/;
|
||||
return hexRegex.test(color);
|
||||
}
|
||||
|
||||
export function clampCoordinate(value: number, min: number, max: number): number {
|
||||
return Math.max(min, Math.min(max, value));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue