* feat(security): implement CSRF protection * chore: clean up CSRF implementation - Remove unused generateCsrfToken export from security.ts - Remove redundant /csrf-token path check (GET already exempt) - Restore defineConfig wrapper in vitest.config.ts for type safety * add K8S note in README, fix broken e2e * feat/upload-bar (#30) * feat/upload-bar: add a upload bar when user upload file, indicate the upload process * feat/save-loading-status: add save status when click back button from editor * fix: address PR review issues in upload and save features - Replace deprecated substr() with substring() in UploadContext - Fix broken error handling that checked stale task status - Fix missing useEffect dependency in UploadStatus - Fix CSS class conflict in progress bar styling - Add error recovery for save state in Editor (reset on failure) - Use .finally() instead of .then() to ensure refresh on upload failure - Fix inconsistent indentation in UploadContext * fix e2e tests --------- Co-authored-by: Zimeng Xiong <zxzimeng@gmail.com> * chore: pre-release v0.2.1-dev * Update backend/src/security.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * fix filename/math random UUID generation --------- Co-authored-by: AdrianAcala <adrianacala017@gmail.com> Co-authored-by: adamant368 <60790941+Yiheng-Liu@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
11 KiB
ExcaliDash Developer Guide
What is ExcaliDash?
ExcaliDash is a full-stack dashboard application for managing and organizing Excalidraw drawings. It provides a interface for creating, organizing, and collaborating on diagrams with features like collections, real-time collaboration, file import/export, and bulk operations.
Project Overview
Core Features
- Drawing Management: Create, edit, and organize Excalidraw drawings
- Collections: Organize drawings into folders/categories
- Real-time Collaboration: Multiple users can edit drawings simultaneously
- Import/Export: Support for .excalidraw and .json file formats
- Bulk Operations: Multi-select drawings for delete, duplicate, and move operations
- Search & Sort: Find drawings by name with sorting by name, created date, or modified date
- Trash System: Soft delete with permanent delete option
- Drag & Drop: Intuitive file dragging and drawing reordering
- Dark/Light Theme: Automatic theme detection with manual toggle
Tech Stack
Frontend:
- React 18 + TypeScript
- Vite (build tool)
- Tailwind CSS (styling)
- Excalidraw (drawing canvas)
- Socket.io Client (real-time features)
- React Router (navigation)
- Lucide React (icons)
Backend:
- Node.js + Express
- TypeScript
- Prisma ORM
- SQLite database
- Socket.io (real-time server)
Infrastructure:
- Docker (containerization)
- Docker Compose (multi-container orchestration)
Project Structure
ExcaliDash/
├── README.md # Project overview
├── AGENTS.md # This file - developer guide
├── DOCKER.md # Docker documentation
├── .gitignore # Git ignore rules
├── .dockerignore # Docker ignore rules
├── docker-compose.yml # Production Docker setup
├── docker-compose.prod.yml # Additional production config
├── publish-docker.sh # Docker deployment script
│
├── backend/ # Node.js/Express backend
│ ├── src/
│ │ ├── index.ts # Main server file
│ │ └── generated/ # Prisma generated client
│ ├── prisma/
│ │ ├── schema.prisma # Database schema
│ │ ├── migrations/ # Database migrations
│ │ └── dev.db # SQLite database (development)
│ ├── package.json # Backend dependencies
│ ├── Dockerfile # Backend container config
│ ├── .env.example # Environment variables template
│ └── docker-entrypoint.sh # Container startup script
│
└── frontend/ # React frontend application
├── src/
│ ├── components/ # Reusable UI components
│ ├── pages/ # Route components
│ ├── hooks/ # Custom React hooks
│ ├── context/ # React context providers
│ ├── types/ # TypeScript type definitions
│ ├── utils/ # Utility functions
│ ├── api/ # API client functions
│ └── assets/ # Static assets
├── public/ # Public assets
├── package.json # Frontend dependencies
├── Dockerfile # Frontend container config
├── vite.config.ts # Vite configuration
├── tailwind.config.js # Tailwind CSS configuration
└── nginx.conf # Nginx configuration for production
Getting Started
Prerequisites
- Node.js 18+ and npm
- Docker and Docker Compose (for containerized development)
- Git
Development Setup
Option 1: Local Development (Recommended)
-
Install Backend Dependencies
cd backend npm install -
Install Frontend Dependencies
cd ../frontend npm install -
Setup Environment Variables
cd ../backend cp .env.example .env # Edit .env if needed -
Initialize Database
npx prisma generate npx prisma db push -
Start Backend Development Server
cd backend npm run dev # Server runs on http://localhost:8000 -
Start Frontend Development Server (in a new terminal)
cd frontend npm run dev # Frontend runs on http://localhost:5173
Environment Variables
Backend (.env):
DATABASE_URL="file:./dev.db"
PORT=8000
NODE_ENV=development
Frontend (.env.example):
VITE_API_URL=http://localhost:8000
Making Changes
Development Workflow
-
Create a Feature Branch
git checkout -b feature/your-feature-name -
Make Your Changes
- Follow the existing code style and patterns
- Add TypeScript types for new features
- Update database schema if needed (see Database section)
-
Test Your Changes
- Test both locally and with Docker
- Check that existing functionality still works
-
Commit and Push
git add . git commit -m "feat: add your feature description" git push origin feature/your-feature-name
Code Style and Standards
- TypeScript: Use strict TypeScript typing
- Component Structure: Follow the existing component patterns in
frontend/src/components/ - API Design: RESTful endpoints in
backend/src/index.ts - Database: Use Prisma migrations for schema changes
- Styling: Tailwind CSS classes with the existing design system
File Organization Guidelines
- Frontend Components: Keep related components together
- Custom Hooks: Place in
frontend/src/hooks/ - Utilities: Place in
frontend/src/utils/ - API Routes: Add to
backend/src/index.ts - Database Models: Update
backend/prisma/schema.prisma
Database
Schema Overview
The application uses two main models:
Collection:
id(String, UUID) - Primary keyname(String) - Collection namedrawings(Relation) - Related drawingscreatedAt,updatedAt(DateTime) - Timestamps
Drawing:
id(String, UUID) - Primary keyname(String) - Drawing nameelements(String, JSON) - Excalidraw elementsappState(String, JSON) - Excalidraw application statefiles(String, JSON) - Associated filespreview(String, SVG) - Thumbnail previewversion(Int) - Version number for conflict detectioncollectionId(String, nullable) - Foreign key to CollectioncreatedAt,updatedAt(DateTime) - Timestamps
Making Database Changes
-
Modify the Schema Edit
backend/prisma/schema.prisma -
Create a Migration
cd backend npx prisma migrate dev --name your_migration_name -
Update TypeScript Types
npx prisma generate -
Test the Changes
npx prisma db push # Apply to development database
Database Commands
# Generate Prisma client
npx prisma generate
# Create and apply migration
npx prisma migrate dev --name migration_name
# Reset database (development only)
npx prisma migrate reset
# View database in Prisma Studio
npx prisma studio
# Deploy migrations to production
npx prisma migrate deploy
API Documentation
Base URL
- Development:
http://localhost:8000 - Production: Configured via environment variables
Endpoints
Drawings
GET /drawings- List drawings (supports search and collection filtering)GET /drawings/:id- Get single drawingPOST /drawings- Create new drawingPUT /drawings/:id- Update drawingDELETE /drawings/:id- Delete drawing permanentlyPOST /drawings/:id/duplicate- Duplicate drawing
Collections
GET /collections- List all collectionsPOST /collections- Create new collectionPUT /collections/:id- Update collectionDELETE /collections/:id- Delete collection (moves drawings to unorganized)
System
GET /health- Health check endpoint
Real-time Events (Socket.io)
Client → Server
join-room- Join drawing room for collaborationcursor-move- Broadcast cursor positionelement-update- Broadcast drawing changesuser-activity- Update user active status
Server → Client
presence-update- User presence in roomcursor-move- Other user's cursor positionelement-update- Other user's drawing changes
Environment Setup
Production Environment Variables:
DATABASE_URL- SQLite database pathPORT- Backend server portNODE_ENV- Set to "production"
Troubleshooting
Common Issues
-
Database Connection Error
- Check that the database file exists in
backend/prisma/dev.db - Ensure proper permissions on the database file
- Verify DATABASE_URL in .env
- Check that the database file exists in
-
Prisma Client Issues
- Run
npx prisma generateto regenerate client - Clear
node_modulesand reinstall dependencies
- Run
-
Port Already in Use
- Change PORT in backend/.env
- Update frontend API URL accordingly
-
Docker Build Failures
- Check Dockerfile syntax
- Ensure all dependencies are listed in package.json
- Verify build context in docker-compose.yml
-
Frontend Not Loading
- Check browser console for errors
- Verify API_URL in frontend environment
- Check network connectivity to backend
Architecture Details
Frontend Architecture
The frontend follows a component-based architecture with:
- Pages: Route-level components (
src/pages/) - Components: Reusable UI components (
src/components/) - Hooks: Custom React hooks for state management (
src/hooks/) - Context: Global state providers (
src/context/) - Utils: Utility functions (
src/utils/)
Key patterns:
- State management using React hooks and context
- API calls centralized in
src/api/ - TypeScript for type safety throughout
- Tailwind CSS for styling with custom design tokens
Backend Architecture
The backend follows a traditional MVC pattern:
- Routes: API endpoints in
src/index.ts - Models: Prisma schema definitions
- Services: Business logic (can be extracted to separate files)
- Middleware: CORS, JSON parsing, etc.
Real-time features:
- Socket.io for WebSocket connections
- Room-based collaboration
- Presence tracking
- Cursor position broadcasting
Data Flow
- Drawing Creation: Frontend → API → Database
- Real-time Updates: Frontend → Socket.io → Other Frontends
- Data Persistence: Regular API calls for saving state
- File Management: Frontend → API → Database (as JSON)
Contributing
Pull Request Process
- Ensure all tests pass
- Update documentation if needed
- Add commit messages following conventional commits
- Request review from maintainers
Commit Message Format
type(scope): description
feat(auth): add user authentication
fix(editor): resolve drawing save issue
docs(api): update endpoint documentation
Types: feat, fix, docs, style, refactor, test, chore
Resources
- Excalidraw Documentation
- Prisma Documentation
- React Documentation
- Socket.io Documentation
- Tailwind CSS Documentation
- Vite Documentation
This documentation is maintained alongside the codebase. Please update it when making significant architectural changes.