mirror of
https://github.com/Dvorinka/excalidraw-full.git
synced 2026-06-03 13:52:56 +00:00
feat: full project sync - CI fixes, frontend, workspace API, and all changes
This commit is contained in:
@@ -1,182 +1,201 @@
|
||||
# Excalidraw Full: Your Self-Hosted, Cloud-Ready Collaboration Platform
|
||||
# Excalidraw FULL
|
||||
|
||||
[中文说明](./README_zh.md)
|
||||
A self-hosted visual workspace for drawing, planning, mapping, charting, and lightweight project management built around a fast collaborative canvas.
|
||||
|
||||
Excalidraw Full has evolved. It's no longer just a simple wrapper for Excalidraw, but a powerful, self-hosted collaboration platform with a "Bring Your Own Cloud" (BYOC) philosophy. It provides user authentication, multi-canvas management, and the unique ability to connect directly to your own cloud storage from the frontend.
|
||||
## What It Is
|
||||
|
||||
The core idea is to let the backend handle user identity while giving you, the user, full control over where your data is stored.
|
||||
Excalidraw FULL is a production-grade visual workspace platform. It is no longer a simple drawing wrapper — it is a full product with backend-owned persistence, team collaboration, permissions, and structured file management.
|
||||
|
||||
## Core Differences from Official Excalidraw
|
||||
- **Visual canvas first** — freeform drawing remains central
|
||||
- **Backend-owned persistence only** — no browser/local save modes
|
||||
- **Team collaboration native** — real-time editing with presence
|
||||
- **File/folder/project management built in** — hierarchical organization via `/folder/:folderId/drawing/:drawingId`
|
||||
- **Secure sharing and permissioning** — explicit grants with inheritance
|
||||
- **Activity history and auditability** — every action is tracked
|
||||
- **Templates and structured productivity** — system + team + personal templates
|
||||
- **Rich linking between canvases** — embeds, references, knowledge graph
|
||||
- **AI chat integration** — OpenAI proxy for diagram generation assistance
|
||||
- **Command palette** — global `Cmd/Ctrl+K` for power users
|
||||
- **Fulltext search** — find drawings from anywhere
|
||||
- **Revision browser** — time-travel through drawing history with one-click restore
|
||||
- **Dark mode** — persistent theme preference across sessions
|
||||
- **Presenter notes** — add notes to any drawing for presentations
|
||||
- **Responsive layout** — mobile sidebar toggle, adaptive grids
|
||||
- **Accessibility** — ARIA labels, roles, keyboard navigation
|
||||
- **Self-hosting** — single Docker image, healthchecks, volume mounts
|
||||
|
||||
- **Fully Self-Hosted Collaboration & Sharing**: Unlike the official version, all real-time collaboration and sharing features are handled by your own self-hosted backend, ensuring complete data privacy and control.
|
||||
- **Advanced Multi-Canvas Management**: Seamlessly create, save, and manage multiple canvases. Store your work on the server's backend (e.g., SQLite, S3) or connect the frontend directly to your personal cloud storage (e.g., Cloudflare KV) for true data sovereignty.
|
||||
- **Zero-Config AI Features**: Instantly access integrated OpenAI features like GPT-4 Vision after logging in—no complex client-side setup required. API keys are securely managed by the backend.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Key Features
|
||||
|
||||
- **GitHub Authentication**: Secure sign-in using GitHub OAuth.
|
||||
- **Multi-Canvas Management**: Users can create, save, and manage multiple drawing canvases.
|
||||
- **Flexible Data Storage (BYOC)**:
|
||||
- **Default Backend Storage**: Out-of-the-box support for saving canvases on the server's storage (SQLite, Filesystem, S3).
|
||||
- **Direct Cloud Connection**: The frontend can connect directly to your own cloud services like **Cloudflare KV** or **Amazon S3** for ultimate data sovereignty. Your credentials never touch our server.
|
||||
- **Real-time Collaboration**: The classic Excalidraw real-time collaboration is fully supported.
|
||||
- **Secure OpenAI Proxy**: An optional backend proxy for using OpenAI's GPT-4 Vision features, keeping your API key safe.
|
||||
- **All-in-One Binary**: The entire application, including the patched frontend and backend server, is compiled into a single Go binary for easy deployment.
|
||||
|
||||
## Frontend Canvas Storage Strategies
|
||||
|
||||
- **IndexedDB**: A fast, secure, and scalable key-value store. No need to configure anything. Not login required.
|
||||
- **Backend Storage**: The backend can save the canvas to the server's storage (SQLite, Filesystem, S3). Synchronized in different devices.
|
||||
- **Cloudflare KV**: A fast, secure, and scalable key-value store. This requires deploying a companion Worker to your Cloudflare account. See the [**Cloudflare Worker Deployment Guide**](./cloudflare-worker/README.md) for detailed instructions.
|
||||
- **Amazon S3**: A reliable, scalable, and inexpensive object storage service.
|
||||
|
||||
## Installation & Running
|
||||
|
||||
One Click Docker run [Excalidraw-Full](https://github.com/BetterAndBetterII/excalidraw-full).
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Example for Linux
|
||||
git clone https://github.com/BetterAndBetterII/excalidraw-full.git
|
||||
cd excalidraw-full
|
||||
mv .env.example .env
|
||||
touch ./excalidraw.db # IMPORTANT: Initialize the SQLite DB, OTHERWISE IT WILL NOT START
|
||||
docker compose up -d
|
||||
cp .env.example .env
|
||||
# Edit .env and set JWT_SECRET (required)
|
||||
# openssl rand -base64 32
|
||||
make build # Build frontend + Go binary
|
||||
make test # Run all tests
|
||||
make docker-up # Or run via Docker Compose
|
||||
```
|
||||
|
||||
The server will start, and you can access the application at `http://localhost:3002`.
|
||||
The application will be available at `http://localhost:3002`.
|
||||
|
||||
## Requirements
|
||||
|
||||
<!-- Summary Folded -->
|
||||
<details>
|
||||
<summary>Use Simple Password Authentication(Dex OIDC)</summary>
|
||||
|
||||
```bash
|
||||
# Example for Linux
|
||||
git clone https://github.com/BetterAndBetterII/excalidraw-full.git
|
||||
cd excalidraw-full
|
||||
mv .env.example.dex .env
|
||||
touch ./excalidraw.db # IMPORTANT: Initialize the SQLite DB, OTHERWISE IT WILL NOT START
|
||||
docker compose -f docker-compose.dex.yml up -d
|
||||
```
|
||||
|
||||
Change your password in `.env` file.
|
||||
|
||||
```bash
|
||||
# apt install apache2-utils
|
||||
# Generate the password hash
|
||||
echo YOUR_NEW_PASSWORD | htpasswd -BinC 10 admin | cut -d: -f2 > .htpasswd
|
||||
# Update your .env file
|
||||
sed -i "s|ADMIN_PASSWORD_HASH=.*|ADMIN_PASSWORD_HASH='$(cat .htpasswd)'|" .env
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
- Go 1.25+
|
||||
- Node.js 20+ (for frontend build)
|
||||
- Make (optional, for convenience commands)
|
||||
- Docker (optional, for containerized deployment)
|
||||
|
||||
## Configuration
|
||||
|
||||
Configuration is managed via environment variables. For a full template, see the `.env.example` section below.
|
||||
All configuration is via environment variables. See `.env.example` for the full reference.
|
||||
|
||||
### 1. Backend Configuration (Required)
|
||||
| Variable | Required | Description |
|
||||
|----------|----------|-------------|
|
||||
| `JWT_SECRET` | Yes | Secure random string for session signing (min 32 chars) |
|
||||
| `STORAGE_TYPE` | No | `postgres` (default), `memory`, `filesystem`, `s3` |
|
||||
| `DATABASE_URL` | Yes for Postgres | PostgreSQL connection string |
|
||||
| `GITHUB_CLIENT_ID` | No* | GitHub OAuth app client ID |
|
||||
| `GITHUB_CLIENT_SECRET` | No* | GitHub OAuth app client secret |
|
||||
| `OIDC_ISSUER_URL` | No* | Generic OIDC issuer for SSO |
|
||||
| `OIDC_CLIENT_ID` | No* | OIDC client ID |
|
||||
| `OIDC_CLIENT_SECRET` | No* | OIDC client secret |
|
||||
| `OPENAI_API_KEY` | No | Enables AI chat/completion proxy |
|
||||
| `OPENAI_BASE_URL` | No | OpenAI-compatible API base URL |
|
||||
| `ALLOWED_ORIGINS` | No | Comma-separated CORS origins |
|
||||
| `LISTEN_ADDR` | No | Server bind address (default `:3002`) |
|
||||
|
||||
You must configure GitHub OAuth and a JWT secret for the application to function.
|
||||
\* At least one external auth provider (GitHub OAuth or OIDC) OR use built-in password authentication. Password auth works out of the box.
|
||||
|
||||
- `GITHUB_CLIENT_ID`: Your GitHub OAuth App's Client ID.
|
||||
- `GITHUB_CLIENT_SECRET`: Your GitHub OAuth App's Client Secret.
|
||||
- `GITHUB_REDIRECT_URL`: The callback URL. For local testing, this is `http://localhost:3002/auth/callback`.
|
||||
- `JWT_SECRET`: A strong, random string for signing session tokens. Generate one with `openssl rand -base64 32`.
|
||||
- `OPENAI_API_KEY`: Your secret key from OpenAI.
|
||||
- `OPENAI_BASE_URL`: (Optional) For using compatible APIs like Azure OpenAI.
|
||||
## Architecture
|
||||
|
||||
### 2. Default Storage (Optional, but Recommended)
|
||||
- **Backend**: Go 1.25, Chi router, PostgreSQL (pgx)
|
||||
- **Frontend**: React 18, Vite, TypeScript, Zustand, react-router-dom, react-i18next
|
||||
- **Real-time**: Socket.IO for collaborative canvas sync
|
||||
- **Auth**: Session cookies (httpOnly, SameSite=Lax) + bcrypt password hashing + OAuth/OIDC
|
||||
- **Storage**: PostgreSQL default, with legacy filesystem/S3 options for canvas storage
|
||||
- **API spec**: OpenAPI 3.0 in `api/openapi.yaml`; TypeScript client via `make generate-api-client`
|
||||
|
||||
This configures the server's built-in storage, used by default.
|
||||
## API
|
||||
|
||||
- `STORAGE_TYPE`: `memory` (default), `sqlite`, `filesystem`, or `s3`.
|
||||
- `DATA_SOURCE_NAME`: Path for the SQLite DB (e.g., `excalidraw.db`).
|
||||
- `LOCAL_STORAGE_PATH`: Directory for filesystem storage.
|
||||
- `S3_BUCKET_NAME`, `AWS_REGION`, etc.: For S3 storage.
|
||||
The workspace API is mounted at `/api` and requires session authentication. Key endpoints:
|
||||
|
||||
### 3. OpenAI Proxy (Optional)
|
||||
- `POST /api/auth/signup` / `POST /api/auth/login` / `POST /api/auth/logout`
|
||||
- `GET /api/auth/me` — current user
|
||||
- `GET /api/teams`, `POST /api/teams`, `GET /api/teams/:id/members`
|
||||
- `GET /api/drawings`, `POST /api/drawings`, `GET /api/drawings/:id`
|
||||
- `PATCH /api/drawings/:id`, `DELETE /api/drawings/:id`
|
||||
- `GET /api/drawings/:id/revisions`, `POST /api/drawings/:id/revisions`
|
||||
- `GET /api/drawings/:id/permissions`, `POST /api/drawings/:id/permissions`
|
||||
- `GET /api/drawings/:id/share-links`, `POST /api/drawings/:id/share-links`
|
||||
- `GET /api/search?q=` — fulltext search
|
||||
- `GET /api/folders`, `POST /api/folders`
|
||||
- `GET /api/projects`, `POST /api/projects`
|
||||
- `GET /api/templates` — system, team, and personal templates
|
||||
- `GET /api/activity` — audit trail with actor hydration
|
||||
- `GET /api/stats` — workspace statistics (counts + storage)
|
||||
- `GET /api/health` — readiness probe
|
||||
|
||||
To enable AI features, set your OpenAI API key.
|
||||
|
||||
- `OPENAI_API_KEY`: Your secret key from OpenAI.
|
||||
- `OPENAI_BASE_URL`: (Optional) For using compatible APIs like Azure OpenAI.
|
||||
|
||||
### 4. Frontend Configuration
|
||||
|
||||
Frontend storage adapters (like Cloudflare KV, S3) are configured directly in the application's UI settings after you log in. This is by design: your private cloud credentials are only ever stored in your browser's session and are never sent to the backend server.
|
||||
|
||||
### Example `.env.example`
|
||||
|
||||
Create a `.env` file in the project root and add the following, filling in your own values.
|
||||
|
||||
```env
|
||||
# Backend Server Configuration
|
||||
# Get from https://github.com/settings/developers
|
||||
GITHUB_CLIENT_ID=your_github_client_id
|
||||
GITHUB_CLIENT_SECRET=your_github_client_secret
|
||||
GITHUB_REDIRECT_URL=http://localhost:3002/auth/callback
|
||||
|
||||
# Generate with: openssl rand -base64 32
|
||||
JWT_SECRET=your_super_secret_jwt_string
|
||||
|
||||
# Default Storage (SQLite)
|
||||
STORAGE_TYPE=sqlite
|
||||
DATA_SOURCE_NAME=excalidraw.db
|
||||
|
||||
# Optional OpenAI Proxy
|
||||
OPENAI_API_KEY=sk-your_openai_api_key
|
||||
```
|
||||
|
||||
## Building from Source
|
||||
|
||||
The process is similar to before, but now requires the Go backend to be built.
|
||||
|
||||
### Using Docker (Recommended)
|
||||
## Development
|
||||
|
||||
```bash
|
||||
# Clone the repository with submodules
|
||||
git clone https://github.com/PatWie/excalidraw-complete.git --recursive
|
||||
cd excalidraw-complete
|
||||
# Terminal 1: Go backend with auto-reload (requires air)
|
||||
make dev-backend
|
||||
|
||||
# Build the Docker image
|
||||
# This handles the frontend build, patching, and Go backend compilation.
|
||||
docker build -t excalidraw-complete -f excalidraw-complete.Dockerfile .
|
||||
# Terminal 2: Vite dev server
|
||||
make dev-frontend
|
||||
|
||||
# Run the container, providing the environment variables
|
||||
docker run -p 3002:3002 \
|
||||
-e GITHUB_CLIENT_ID="your_id" \
|
||||
-e GITHUB_CLIENT_SECRET="your_secret" \
|
||||
-e GITHUB_REDIRECT_URL="http://localhost:3002/auth/callback" \
|
||||
-e JWT_SECRET="your_jwt_secret" \
|
||||
-e STORAGE_TYPE="sqlite" \
|
||||
-e DATA_SOURCE_NAME="excalidraw.db" \
|
||||
-e OPENAI_API_KEY="your_openai_api_key" \
|
||||
excalidraw-complete
|
||||
# Or run both manually:
|
||||
go run main.go # backend on :3002
|
||||
cd frontend && npm run dev # frontend on :5173
|
||||
```
|
||||
|
||||
### Manual Build
|
||||
## Building
|
||||
|
||||
1. **Build Frontend**: Follow the steps in the original README to patch and build the Excalidraw frontend inside the `excalidraw/` submodule.
|
||||
2. **Copy Frontend**: Ensure the built frontend from `excalidraw/excalidraw-app/build` is copied to the `frontend/` directory in the root.
|
||||
3. **Build Go Backend**:
|
||||
```bash
|
||||
go build -o excalidraw-complete main.go
|
||||
```
|
||||
4. **Run**:
|
||||
```bash
|
||||
# Set environment variables first
|
||||
./excalidraw-complete
|
||||
```
|
||||
---
|
||||
```bash
|
||||
make build # Full production build (frontend + Go binary)
|
||||
make build-frontend # React build only
|
||||
make build-backend # Go binary only
|
||||
make build-docker # Docker image locally
|
||||
make test # Run Go + frontend tests
|
||||
make test-backend # Go unit tests
|
||||
make test-frontend # Vitest unit tests
|
||||
make test-e2e # Playwright E2E tests
|
||||
make lint # Run all linters
|
||||
make fmt # Format all code
|
||||
make generate-api-client # TS client from openapi.yaml
|
||||
make clean # Remove build artifacts
|
||||
make docker-up # Docker Compose local run
|
||||
make docker-down # Stop Docker Compose
|
||||
make docker-logs # Tail Docker logs
|
||||
make help # Show all targets
|
||||
```
|
||||
|
||||
Excalidraw is a fantastic tool. This project aims to make a powerful, data-secure version of it accessible to everyone. Contributions are welcome!
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
.
|
||||
├── main.go # Go server entrypoint
|
||||
├── workspace/ # Core domain: models, store, HTTP handlers, tests
|
||||
│ ├── models.go
|
||||
│ ├── store.go # PostgreSQL persistence + migrations
|
||||
│ ├── store_sharing.go # Permissions, share links, embeds
|
||||
│ ├── http.go # API route handlers
|
||||
│ ├── http_extra.go # Search, stats, activity
|
||||
│ ├── stats.go # Workspace statistics
|
||||
│ ├── rate_limiter.go # Auth endpoint rate limiting
|
||||
│ └── *_test.go # Go unit tests
|
||||
├── middleware/ # Auth, security headers
|
||||
├── handlers/ # Legacy firebase, kv, openai, auth
|
||||
├── frontend/ # React + Vite frontend
|
||||
│ ├── src/
|
||||
│ │ ├── pages/ # Dashboard, Editor, Auth, Settings, etc.
|
||||
│ │ ├── components/ # Reusable UI (Button, Card, CommandPalette, etc.)
|
||||
│ │ ├── stores/ # Zustand state management
|
||||
│ │ ├── services/ # API client + OpenAI proxy
|
||||
│ │ ├── i18n/ # Translation files (en.json)
|
||||
│ │ └── styles/ # Global SCSS + CSS variables
|
||||
│ └── package.json
|
||||
├── api/
|
||||
│ └── openapi.yaml # Full OpenAPI 3.0 spec
|
||||
├── excalidraw-full.Dockerfile # Multi-stage production build
|
||||
├── docker-compose.yml # Local Docker Compose
|
||||
├── Makefile # Build, test, dev automation
|
||||
└── .env.example # Environment reference
|
||||
```
|
||||
|
||||
## Security
|
||||
|
||||
- bcrypt(cost=12) password hashing
|
||||
- httpOnly, SameSite=Lax session cookies
|
||||
- CSRF-like same-origin mutation checks on state-changing requests
|
||||
- URL sanitization for embeds (blocks file://, javascript:, private IPs)
|
||||
- Content-Security-Policy headers with strict defaults
|
||||
- Rate limiting on auth endpoints (10 req / 15 min per IP)
|
||||
- Permission matrix with explicit grants + inheritance
|
||||
- All mutations require authenticated session
|
||||
|
||||
## Internationalization
|
||||
|
||||
Frontend uses `react-i18next` with `i18next-browser-languagedetector`. All UI strings are externalized to `frontend/src/i18n/locales/en.json`. Add new keys there and reference via `t('key')`.
|
||||
|
||||
## Roadmap
|
||||
|
||||
See `plus-roadmap.md` for upcoming features. Shipped highlights:
|
||||
|
||||
- Archive (trash) instead of delete
|
||||
- Activity feed with full audit trail
|
||||
- Command palette for whole app (`Cmd/Ctrl+K`)
|
||||
- Fulltext search
|
||||
- Versioning with revision browser
|
||||
- Public API (OpenAPI + TS client generation)
|
||||
- Self-hosting via Docker
|
||||
- Presenter notes
|
||||
- Scene filtering and sorting
|
||||
- Template gallery with apply flow
|
||||
- Dark mode sync with canvas
|
||||
- Mobile-responsive navigation
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
Reference in New Issue
Block a user