Excalidraw - Kompletny Przewodnik po Wirtualnej Tablicy do Diagramów
Czym jest Excalidraw?
Excalidraw to open-source'owa wirtualna tablica do rysowania diagramów w charakterystycznym stylu "hand-drawn" (ręcznie rysowanym). W przeciwieństwie do tradycyjnych narzędzi do diagramów jak Lucidchart czy draw.io, Excalidraw celowo produkuje niedoskonałe, "ludzkie" linie i kształty, co sprawia, że diagramy wyglądają naturalnie i nieformalnie - idealnie do szkicowania pomysłów, brainstormingu i komunikacji technicznej.
Excalidraw został stworzony przez Christophera Chedeau (byłego inżyniera Facebook) w 2020 roku i szybko zdobył ogromną popularność w społeczności developerskiej. Narzędzie jest używane przez zespoły w firmach takich jak Meta, Google, Microsoft i Vercel do dokumentacji technicznej, projektowania systemów i wizualizacji architektury.
Dlaczego Excalidraw?
Kluczowe zalety
- Hand-drawn style - Naturalny, nieformalny wygląd zachęcający do iteracji
- Instant start - Zero konfiguracji, działa w przeglądarce
- Real-time collaboration - Współpraca w czasie rzeczywistym
- Open-source - Darmowy, można hostować samemu
- Privacy-first - End-to-end encryption dla współdzielonych sesji
- Libraries ecosystem - Gotowe zestawy ikon i kształtów
- Export flexibility - PNG, SVG, JSON, clipboard
- VS Code integration - Natywne rozszerzenie do edycji
Excalidraw vs inne narzędzia
| Cecha | Excalidraw | draw.io | Lucidchart | Miro |
|---|---|---|---|---|
| Styl | Hand-drawn | Clean/Formal | Formal | Mix |
| Cena | Free/OSS | Free | $7.95+/mo | $8+/mo |
| Self-host | ✅ Tak | ✅ Tak | ❌ Nie | ❌ Nie |
| Real-time collab | ✅ Tak | ✅ Tak | ✅ Tak | ✅ Tak |
| E2E encryption | ✅ Tak | ❌ Nie | ❌ Nie | ❌ Nie |
| VS Code | ✅ Extension | ❌ Nie | ❌ Nie | ❌ Nie |
| Offline | ✅ PWA | ✅ Desktop | ❌ Nie | ❌ Nie |
Podstawy Excalidraw
Interfejs użytkownika
┌─────────────────────────────────────────────────────────────────┐
│ Toolbar (narzędzia) │
│ [Select] [Rectangle] [Diamond] [Ellipse] [Arrow] [Line] [Text] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Canvas (nieskończony) │
│ │
│ ┌──────────────────┐ │
│ │ Twój diagram │────────────────┐ │
│ │ (hand-drawn) │ │ │
│ └──────────────────┘ ▼ │
│ ┌──────────┐ │
│ │ Element │ │
│ └──────────┘ │
│ │
├─────────────────────────────────────────────────────────────────┤
│ [Stroke] [Background] [Fill] [Stroke width] [Sloppiness] [Edge]│
└─────────────────────────────────────────────────────────────────┘Podstawowe kształty
Rectangle (R):
┌────────────────┐
│ │
│ Prostokąt │
│ │
└────────────────┘
Diamond (D):
◇
╱ ╲
╱ ╲
◇ Romb ◇
╲ ╱
╲ ╱
◇
Ellipse (O):
╭──────────╮
╱ ╲
│ Elipsa │
╲ ╱
╰──────────╯
Arrow (A):
────────────────────►
Line (L):
────────────────────
Text (T):
Dowolny tekstSkróty klawiszowe
NARZĘDZIA:
1 lub V - Selection (zaznaczanie)
2 lub R - Rectangle
3 lub D - Diamond
4 lub O - Ellipse (Oval)
5 lub A - Arrow
6 lub L - Line
7 lub P - Draw (wolne rysowanie)
8 lub T - Text
9 - Image
0 lub E - Eraser
EDYCJA:
Ctrl/Cmd + D - Duplicate
Ctrl/Cmd + G - Group
Ctrl/Cmd + Shift + G - Ungroup
Ctrl/Cmd + [ - Send backward
Ctrl/Cmd + ] - Bring forward
Ctrl/Cmd + Shift + [ - Send to back
Ctrl/Cmd + Shift + ] - Bring to front
Delete/Backspace - Delete selected
WIDOK:
Ctrl/Cmd + +/- - Zoom in/out
Ctrl/Cmd + 0 - Reset zoom
Ctrl/Cmd + 1 - Fit to content
Space + drag - Pan canvas
Scroll - Zoom (with Ctrl) / Pan
EKSPORT:
Ctrl/Cmd + S - Save to file
Ctrl/Cmd + Shift + E - Export image
Ctrl/Cmd + Shift + C - Copy to clipboard as PNGTworzenie diagramów
Diagram architektury systemu
Przykładowy diagram architektury:
┌─────────────────────────────────────────────────────────────┐
│ Internet │
└─────────────────────────┬───────────────────────────────────┘
│
▼
┌───────────────┐
│ Cloudflare │
│ (CDN/WAF) │
└───────┬───────┘
│
┌───────────────┴───────────────┐
▼ ▼
┌───────────────┐ ┌───────────────┐
│ Vercel │ │ Railway │
│ (Frontend) │◄─────────────►│ (Backend) │
│ Next.js │ API │ NestJS │
└───────────────┘ └───────┬───────┘
│
┌───────────────────────────────┼───────────────────┐
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Supabase │ │ Neon │ │ Upstash │
│ (Auth) │ │ (PostgreSQL) │ │ (Redis) │
└───────────────┘ └───────────────┘ └───────────────┘Database schema diagram
┌─────────────────────────────────────────────────────────────────┐
│ users │
├─────────────────────────────────────────────────────────────────┤
│ id │ uuid │ PRIMARY KEY │
│ email │ varchar │ UNIQUE NOT NULL │
│ name │ varchar │ NOT NULL │
│ created_at │ timestamp │ DEFAULT now() │
└──────────────────────┬──────────────────────────────────────────┘
│
│ 1:N
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ posts │
├─────────────────────────────────────────────────────────────────┤
│ id │ uuid │ PRIMARY KEY │
│ title │ varchar │ NOT NULL │
│ content │ text │ │
│ author_id │ uuid │ FOREIGN KEY → users.id │
│ published │ boolean │ DEFAULT false │
│ created_at │ timestamp │ DEFAULT now() │
└──────────────────────┬──────────────────────────────────────────┘
│
│ N:M
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ post_tags (junction) │
├─────────────────────────────────────────────────────────────────┤
│ post_id │ uuid │ FOREIGN KEY → posts.id │
│ tag_id │ uuid │ FOREIGN KEY → tags.id │
│ PRIMARY KEY (post_id, tag_id) │
└─────────────────────────────────────────────────────────────────┘User flow diagram
┌─────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────┐
│ Start │────►│ Landing │────►│ Sign Up │────►│ Email │
│ │ │ Page │ │ Form │ │ Verify │
└─────────┘ └─────────────┘ └─────────────┘ └────┬────┘
│ │
│ Already has account │ Verified
▼ ▼
┌─────────────┐ ┌─────────────┐
│ Log In │◄────────────────────────│ Dashboard │
│ Form │ │ (Home) │
└──────┬──────┘ └─────────────┘
│ │
│ Invalid credentials │
▼ ▼
┌─────────────┐ ┌─────────────┐
│ Error │ │ Feature │
│ Message │ │ Pages │
└─────────────┘ └─────────────┘Biblioteki (Libraries)
Korzystanie z bibliotek
1. Kliknij ikonę "Library" (📚) w toolbarze
2. Browse libraries lub importuj własne
3. Przeciągnij elementy na canvas
Popularne biblioteki:
├── Software Architecture
│ ├── AWS icons
│ ├── Azure icons
│ ├── GCP icons
│ └── Kubernetes
│
├── UI/UX
│ ├── Wireframe kit
│ ├── Mobile UI
│ └── Web components
│
├── Business
│ ├── Flowchart
│ ├── Org chart
│ └── Process diagrams
│
└── Technical
├── Network diagrams
├── Database schemas
└── Sequence diagramsTworzenie własnej biblioteki
// Excalidraw library format (.excalidrawlib)
{
"type": "excalidrawlib",
"version": 2,
"source": "https://excalidraw.com",
"libraryItems": [
{
"id": "custom-component-1",
"status": "published",
"elements": [
{
"type": "rectangle",
"x": 0,
"y": 0,
"width": 200,
"height": 100,
"strokeColor": "#1e1e1e",
"backgroundColor": "#a5d8ff",
"fillStyle": "solid"
},
{
"type": "text",
"x": 50,
"y": 40,
"text": "Component",
"fontSize": 16
}
],
"name": "My Custom Component"
}
]
}VS Code Extension
Instalacja
# VS Code Marketplace
code --install-extension pomdtr.excalidraw-editor
# Lub przez GUI:
# Extensions → Search "Excalidraw" → InstallUżycie
1. Utwórz plik z rozszerzeniem .excalidraw lub .excalidraw.svg
2. VS Code automatycznie otworzy edytor Excalidraw
3. Rysuj diagramy bezpośrednio w IDE
4. Zapisz jako SVG (embeddowalne) lub JSON (edytowalne)
Struktura projektu z Excalidraw:
my-project/
├── docs/
│ ├── architecture.excalidraw.svg
│ ├── database-schema.excalidraw
│ └── user-flow.excalidraw.png
├── src/
└── README.mdEmbedowanie w Markdown
<!-- W README.md lub dokumentacji -->
## Architektura Systemu

## Database Schema

## User Flow
<img src="./docs/user-flow.excalidraw.svg" alt="User Flow" width="800">Excalidraw API i integracja
React Component
// Instalacja
npm install @excalidraw/excalidraw
// App.tsx
import { Excalidraw } from '@excalidraw/excalidraw'
function DiagramEditor() {
const [excalidrawAPI, setExcalidrawAPI] = useState(null)
const handleChange = (elements, appState, files) => {
console.log('Elements changed:', elements)
// Zapisz do bazy danych lub localStorage
localStorage.setItem('diagram', JSON.stringify(elements))
}
const handleExport = async () => {
if (!excalidrawAPI) return
// Export jako PNG
const blob = await excalidrawAPI.exportToBlob({
mimeType: 'image/png',
exportWithDarkMode: false,
exportBackground: true
})
// Download
const url = URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = 'diagram.png'
link.click()
}
return (
<div style={{ height: '600px', width: '100%' }}>
<Excalidraw
excalidrawAPI={(api) => setExcalidrawAPI(api)}
onChange={handleChange}
initialData={{
elements: JSON.parse(localStorage.getItem('diagram') || '[]'),
appState: { viewBackgroundColor: '#ffffff' }
}}
UIOptions={{
canvasActions: {
export: { saveFileToDisk: true }
}
}}
/>
<button onClick={handleExport}>Export PNG</button>
</div>
)
}Collaborative mode
import { Excalidraw } from '@excalidraw/excalidraw'
import { useCollaboration } from './useCollaboration'
function CollaborativeDiagram({ roomId }) {
const {
elements,
collaborators,
onPointerUpdate,
onElementsChange
} = useCollaboration(roomId)
return (
<Excalidraw
initialData={{ elements }}
onChange={onElementsChange}
onPointerUpdate={onPointerUpdate}
isCollaborating={true}
renderTopRightUI={() => (
<div className="collaborators">
{collaborators.map(user => (
<Avatar key={user.id} name={user.name} color={user.color} />
))}
</div>
)}
/>
)
}
// Hook do real-time collaboration (przykład z Socket.io)
function useCollaboration(roomId) {
const [elements, setElements] = useState([])
const [collaborators, setCollaborators] = useState([])
const socketRef = useRef(null)
useEffect(() => {
const socket = io('wss://your-server.com')
socketRef.current = socket
socket.emit('join-room', roomId)
socket.on('elements-update', (newElements) => {
setElements(newElements)
})
socket.on('collaborators-update', (users) => {
setCollaborators(users)
})
return () => socket.disconnect()
}, [roomId])
const onElementsChange = useCallback((newElements) => {
setElements(newElements)
socketRef.current?.emit('elements-change', {
roomId,
elements: newElements
})
}, [roomId])
return { elements, collaborators, onElementsChange }
}Export do różnych formatów
import { exportToSvg, exportToBlob, serializeAsJSON } from '@excalidraw/excalidraw'
// Export do SVG
const exportSVG = async (elements, appState) => {
const svg = await exportToSvg({
elements,
appState,
files: null,
exportPadding: 10
})
// SVG jako string
const svgString = new XMLSerializer().serializeToString(svg)
return svgString
}
// Export do PNG/JPEG
const exportImage = async (elements, appState, mimeType = 'image/png') => {
const blob = await exportToBlob({
elements,
appState,
mimeType,
quality: 0.9, // dla JPEG
exportWithDarkMode: false
})
return blob
}
// Export do JSON (do późniejszej edycji)
const exportJSON = (elements, appState) => {
return serializeAsJSON(elements, appState, {}, 'local')
}
// Import z JSON
const importFromJSON = (jsonString) => {
const data = JSON.parse(jsonString)
return {
elements: data.elements,
appState: data.appState
}
}Self-hosting Excalidraw
Docker
# Dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
# Clone Excalidraw
RUN git clone https://github.com/excalidraw/excalidraw.git .
# Install dependencies
RUN yarn install --frozen-lockfile
# Build
RUN yarn build
# Production image
FROM nginx:alpine
COPY /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]# docker-compose.yml
version: '3.8'
services:
excalidraw:
build: .
ports:
- "8080:80"
restart: unless-stopped
# Opcjonalnie: backend dla collaboration
excalidraw-room:
image: excalidraw/excalidraw-room
ports:
- "3002:80"
environment:
- PORT=80Kubernetes
# excalidraw-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: excalidraw
spec:
replicas: 2
selector:
matchLabels:
app: excalidraw
template:
metadata:
labels:
app: excalidraw
spec:
containers:
- name: excalidraw
image: excalidraw/excalidraw:latest
ports:
- containerPort: 80
resources:
limits:
memory: "256Mi"
cpu: "200m"
---
apiVersion: v1
kind: Service
metadata:
name: excalidraw
spec:
selector:
app: excalidraw
ports:
- port: 80
targetPort: 80
type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: excalidraw
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: excalidraw.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: excalidraw
port:
number: 80Excalidraw+ (Premium)
Funkcje premium
Excalidraw+ ($7/miesiąc lub $60/rok):
│
├── End-to-end encryption
│ └── Klucz szyfrujący tylko u użytkownika
│
├── Większy storage
│ └── Unlimited diagrams
│ └── Większe pliki
│
├── Custom fonts
│ └── Import własnych fontów
│
├── Password-protected links
│ └── Dodatkowa warstwa bezpieczeństwa
│
├── Custom branding
│ └── Logo na exportach
│
├── Priority support
│ └── Szybsza pomoc
│
└── Cloud backup
└── Automatyczne backupyZastosowania praktyczne
1. Dokumentacja techniczna
# System Architecture
## Overview
Nasz system składa się z trzech głównych komponentów:

### Frontend
Aplikacja Next.js hostowana na Vercel...
### Backend
API NestJS na Railway...
### Database
PostgreSQL na Neon z branching...2. Code review diagrams
PR #123: Refactor authentication flow
Before:
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Client │────►│ Server │────►│ DB │
└──────────┘ └──────────┘ └──────────┘
│ │
│ Password │ Check password
│ (plain!) │ (slow query!)
└────────────────┘
After:
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ Client │────►│ Server │────►│ Redis │────►│ DB │
└──────────┘ └──────────┘ │ (cache) │ └──────────┘
│ │ └──────────┘
│ Hashed │ Session
│ password │ check first
└────────────────┘3. Meeting notes
Sprint Planning - 2025-01-24
Epic: User Dashboard Redesign
┌─────────────────────────────────────────────────────────┐
│ Dashboard MVP │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Stats │ │ Chart │ │ Recent │ │
│ │ Cards │ │ Widget │ │ Activity │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
│ ┌─────────────────────────────────────────┐ │
│ │ Data Table │ │
│ └─────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
Tasks:
├── [x] Stats cards component (2 pts) - @alice
├── [ ] Chart integration (5 pts) - @bob
├── [ ] Activity feed (3 pts) - @charlie
└── [ ] Data table with pagination (5 pts) - @david4. Onboarding dokumentacja
New Developer Onboarding
Day 1: Setup
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Clone │────►│ Install │────►│ Run │
│ Repo │ │ Deps │ │ Dev │
└─────────┘ └─────────┘ └─────────┘
│
▼
┌─────────────┐
│ Explore UI │
│ on :3000 │
└─────────────┘
Day 2: First PR
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Read │────►│ Pick │────►│ Create │
│ CLAUDE │ │ Issue │ │ Branch │
│ .md │ └─────────┘ └────┬────┘
└─────────┘ │
▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Code │────►│ Test │────►│ Push │
│ Change │ │ Local │ │ PR │
└─────────┘ └─────────┘ └─────────┘Tips & Tricks
Stylizacja elementów
Stroke styles:
├── Solid ────────────
├── Dashed - - - - - -
└── Dotted ············
Fill styles:
├── Solid [■■■■■■■■]
├── Hachure [////////]
├── Cross-hatch [XXXXXXXX]
└── None [ ]
Sloppiness (hand-drawn intensity):
├── Architect (0) - Clean lines
├── Artist (1) - Slight wobble
└── Cartoonist (2) - Very wobbly
Edge style:
├── Sharp ┌─────┐
└── Round ╭─────╮Keyboard workflow
Efektywny workflow:
1. R → Narysuj rectangle
2. T → Dodaj tekst wewnątrz
3. A → Połącz strzałką z innym elementem
4. Ctrl+D → Duplikuj i przesuń
5. Ctrl+G → Grupuj powiązane elementy
6. Ctrl+Shift+E → Eksportuj gotowy diagramCanvas organization
Duże diagramy - organizacja:
┌────────────────────────────────────────────────────────┐
│ TITLE AREA │
│ System Architecture v2.1 │
├────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ SECTION 1 │ │ SECTION 2 │ │
│ │ Frontend │ │ Backend │ │
│ │ │ │ │ │
│ └──────────────┘ └──────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ SECTION 3 │ │ SECTION 4 │ │
│ │ Database │ │ External │ │
│ │ │ │ Services │ │
│ └──────────────┘ └──────────────┘ │
│ │
├────────────────────────────────────────────────────────┤
│ LEGEND: [Component] ──► [Dependency] ···> [Optional] │
└────────────────────────────────────────────────────────┘FAQ - Często zadawane pytania
Czy Excalidraw jest darmowy?
Tak, podstawowa wersja Excalidraw jest całkowicie darmowa i open-source. Możesz używać excalidraw.com bez konta, a także hostować własną instancję. Excalidraw+ to opcjonalna płatna wersja z dodatkowymi funkcjami jak szyfrowanie i większy storage.
Jak zapisać diagram offline?
- Export do pliku .excalidraw - Pełna edytowalność, można otworzyć później
- Export do SVG - Wektor, można edytować w Figma/Illustrator
- Export do PNG - Raster, do dokumentacji
- Copy to clipboard - Szybkie wklejanie do innych aplikacji
Czy mogę używać Excalidraw w VS Code?
Tak, zainstaluj rozszerzenie "Excalidraw" od pomdtr. Umożliwia tworzenie i edycję plików .excalidraw bezpośrednio w IDE.
Jak współpracować w czasie rzeczywistym?
- Kliknij "Live collaboration" w menu
- Udostępnij wygenerowany link
- Każdy z linkiem może edytować
- Sesje są E2E encrypted
Excalidraw vs Mermaid?
- Excalidraw - Wizualny, drag & drop, hand-drawn style
- Mermaid - Tekstowy (code-based), auto-layout, formal style
Oba mają zastosowania - Mermaid do prostych flowcharts w markdown, Excalidraw do bardziej kreatywnych diagramów.
Podsumowanie
Excalidraw to doskonałe narzędzie do:
- Szkicowania architektury - System design, infrastruktura
- Database schemas - Wizualizacja relacji
- User flows - UX documentation
- Wireframes - Szybkie prototypy UI
- Meeting notes - Wizualne notatki
- Technical docs - Diagramy w dokumentacji
- Code reviews - Wyjaśnianie zmian wizualnie
Hand-drawn style sprawia, że diagramy wyglądają nieformalnie, co zachęca do iteracji i dyskusji - idealne dla zespołów agile i dokumentacji technicznej.
Excalidraw - a complete guide to the virtual whiteboard for diagrams
What is Excalidraw?
Excalidraw is an open-source virtual whiteboard for drawing diagrams in a distinctive "hand-drawn" style. Unlike traditional diagramming tools such as Lucidchart or draw.io, Excalidraw intentionally produces imperfect, "human" lines and shapes, making diagrams look natural and informal - perfect for sketching ideas, brainstorming, and technical communication.
Excalidraw was created by Christopher Chedeau (a former Facebook engineer) in 2020 and quickly gained enormous popularity in the developer community. The tool is used by teams at companies like Meta, Google, Microsoft, and Vercel for technical documentation, system design, and architecture visualization.
Why Excalidraw?
Key advantages
- Hand-drawn style - Natural, informal look that encourages iteration
- Instant start - Zero configuration, works in the browser
- Real-time collaboration - Work together in real time
- Open-source - Free, can be self-hosted
- Privacy-first - End-to-end encryption for shared sessions
- Libraries ecosystem - Ready-made icon and shape sets
- Export flexibility - PNG, SVG, JSON, clipboard
- VS Code integration - Native extension for editing
Excalidraw vs other tools
| Feature | Excalidraw | draw.io | Lucidchart | Miro |
|---|---|---|---|---|
| Style | Hand-drawn | Clean/Formal | Formal | Mix |
| Price | Free/OSS | Free | $7.95+/mo | $8+/mo |
| Self-host | ✅ Yes | ✅ Yes | ❌ No | ❌ No |
| Real-time collab | ✅ Yes | ✅ Yes | ✅ Yes | ✅ Yes |
| E2E encryption | ✅ Yes | ❌ No | ❌ No | ❌ No |
| VS Code | ✅ Extension | ❌ No | ❌ No | ❌ No |
| Offline | ✅ PWA | ✅ Desktop | ❌ No | ❌ No |
Excalidraw basics
User interface
┌─────────────────────────────────────────────────────────────────┐
│ Toolbar (tools) │
│ [Select] [Rectangle] [Diamond] [Ellipse] [Arrow] [Line] [Text] │
├─────────────────────────────────────────────────────────────────┤
│ │
│ Canvas (infinite) │
│ │
│ ┌──────────────────┐ │
│ │ Your diagram │────────────────┐ │
│ │ (hand-drawn) │ │ │
│ └──────────────────┘ ▼ │
│ ┌──────────┐ │
│ │ Element │ │
│ └──────────┘ │
│ │
├─────────────────────────────────────────────────────────────────┤
│ [Stroke] [Background] [Fill] [Stroke width] [Sloppiness] [Edge]│
└─────────────────────────────────────────────────────────────────┘Basic shapes
Rectangle (R):
┌────────────────┐
│ │
│ Rectangle │
│ │
└────────────────┘
Diamond (D):
◇
╱ ╲
╱ ╲
◇ Diamond ◇
╲ ╱
╲ ╱
◇
Ellipse (O):
╭──────────╮
╱ ╲
│ Ellipse │
╲ ╱
╰──────────╯
Arrow (A):
────────────────────►
Line (L):
────────────────────
Text (T):
Any text hereKeyboard shortcuts
TOOLS:
1 or V - Selection (select elements)
2 or R - Rectangle
3 or D - Diamond
4 or O - Ellipse (Oval)
5 or A - Arrow
6 or L - Line
7 or P - Draw (freehand drawing)
8 or T - Text
9 - Image
0 or E - Eraser
EDITING:
Ctrl/Cmd + D - Duplicate
Ctrl/Cmd + G - Group
Ctrl/Cmd + Shift + G - Ungroup
Ctrl/Cmd + [ - Send backward
Ctrl/Cmd + ] - Bring forward
Ctrl/Cmd + Shift + [ - Send to back
Ctrl/Cmd + Shift + ] - Bring to front
Delete/Backspace - Delete selected
VIEW:
Ctrl/Cmd + +/- - Zoom in/out
Ctrl/Cmd + 0 - Reset zoom
Ctrl/Cmd + 1 - Fit to content
Space + drag - Pan canvas
Scroll - Zoom (with Ctrl) / Pan
EXPORT:
Ctrl/Cmd + S - Save to file
Ctrl/Cmd + Shift + E - Export image
Ctrl/Cmd + Shift + C - Copy to clipboard as PNGCreating diagrams
System architecture diagram
Example architecture diagram:
┌─────────────────────────────────────────────────────────────┐
│ Internet │
└─────────────────────────┬───────────────────────────────────┘
│
▼
┌───────────────┐
│ Cloudflare │
│ (CDN/WAF) │
└───────┬───────┘
│
┌───────────────┴───────────────┐
▼ ▼
┌───────────────┐ ┌───────────────┐
│ Vercel │ │ Railway │
│ (Frontend) │◄─────────────►│ (Backend) │
│ Next.js │ API │ NestJS │
└───────────────┘ └───────┬───────┘
│
┌───────────────────────────────┼───────────────────┐
│ │ │
▼ ▼ ▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ Supabase │ │ Neon │ │ Upstash │
│ (Auth) │ │ (PostgreSQL) │ │ (Redis) │
└───────────────┘ └───────────────┘ └───────────────┘Database schema diagram
┌─────────────────────────────────────────────────────────────────┐
│ users │
├─────────────────────────────────────────────────────────────────┤
│ id │ uuid │ PRIMARY KEY │
│ email │ varchar │ UNIQUE NOT NULL │
│ name │ varchar │ NOT NULL │
│ created_at │ timestamp │ DEFAULT now() │
└──────────────────────┬──────────────────────────────────────────┘
│
│ 1:N
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ posts │
├─────────────────────────────────────────────────────────────────┤
│ id │ uuid │ PRIMARY KEY │
│ title │ varchar │ NOT NULL │
│ content │ text │ │
│ author_id │ uuid │ FOREIGN KEY → users.id │
│ published │ boolean │ DEFAULT false │
│ created_at │ timestamp │ DEFAULT now() │
└──────────────────────┬──────────────────────────────────────────┘
│
│ N:M
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ post_tags (junction) │
├─────────────────────────────────────────────────────────────────┤
│ post_id │ uuid │ FOREIGN KEY → posts.id │
│ tag_id │ uuid │ FOREIGN KEY → tags.id │
│ PRIMARY KEY (post_id, tag_id) │
└─────────────────────────────────────────────────────────────────┘User flow diagram
┌─────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────┐
│ Start │────►│ Landing │────►│ Sign Up │────►│ Email │
│ │ │ Page │ │ Form │ │ Verify │
└─────────┘ └─────────────┘ └─────────────┘ └────┬────┘
│ │
│ Already has account │ Verified
▼ ▼
┌─────────────┐ ┌─────────────┐
│ Log In │◄────────────────────────│ Dashboard │
│ Form │ │ (Home) │
└──────┬──────┘ └─────────────┘
│ │
│ Invalid credentials │
▼ ▼
┌─────────────┐ ┌─────────────┐
│ Error │ │ Feature │
│ Message │ │ Pages │
└─────────────┘ └─────────────┘Libraries
Using libraries
1. Click the "Library" icon in the toolbar
2. Browse libraries or import your own
3. Drag elements onto the canvas
Popular libraries:
├── Software Architecture
│ ├── AWS icons
│ ├── Azure icons
│ ├── GCP icons
│ └── Kubernetes
│
├── UI/UX
│ ├── Wireframe kit
│ ├── Mobile UI
│ └── Web components
│
├── Business
│ ├── Flowchart
│ ├── Org chart
│ └── Process diagrams
│
└── Technical
├── Network diagrams
├── Database schemas
└── Sequence diagramsCreating your own library
{
"type": "excalidrawlib",
"version": 2,
"source": "https://excalidraw.com",
"libraryItems": [
{
"id": "custom-component-1",
"status": "published",
"elements": [
{
"type": "rectangle",
"x": 0,
"y": 0,
"width": 200,
"height": 100,
"strokeColor": "#1e1e1e",
"backgroundColor": "#a5d8ff",
"fillStyle": "solid"
},
{
"type": "text",
"x": 50,
"y": 40,
"text": "Component",
"fontSize": 16
}
],
"name": "My Custom Component"
}
]
}VS Code extension
Installation
code --install-extension pomdtr.excalidraw-editor
# Or via GUI:
# Extensions → Search "Excalidraw" → InstallUsage
1. Create a file with the .excalidraw or .excalidraw.svg extension
2. VS Code will automatically open the Excalidraw editor
3. Draw diagrams directly in your IDE
4. Save as SVG (embeddable) or JSON (editable)
Project structure with Excalidraw:
my-project/
├── docs/
│ ├── architecture.excalidraw.svg
│ ├── database-schema.excalidraw
│ └── user-flow.excalidraw.png
├── src/
└── README.mdEmbedding in Markdown
<!-- In README.md or documentation -->
## System architecture

## Database schema

## User flow
<img src="./docs/user-flow.excalidraw.svg" alt="User Flow" width="800">Excalidraw API and integration
React component
npm install @excalidraw/excalidraw
// App.tsx
import { Excalidraw } from '@excalidraw/excalidraw'
function DiagramEditor() {
const [excalidrawAPI, setExcalidrawAPI] = useState(null)
const handleChange = (elements, appState, files) => {
console.log('Elements changed:', elements)
localStorage.setItem('diagram', JSON.stringify(elements))
}
const handleExport = async () => {
if (!excalidrawAPI) return
const blob = await excalidrawAPI.exportToBlob({
mimeType: 'image/png',
exportWithDarkMode: false,
exportBackground: true
})
const url = URL.createObjectURL(blob)
const link = document.createElement('a')
link.href = url
link.download = 'diagram.png'
link.click()
}
return (
<div style={{ height: '600px', width: '100%' }}>
<Excalidraw
excalidrawAPI={(api) => setExcalidrawAPI(api)}
onChange={handleChange}
initialData={{
elements: JSON.parse(localStorage.getItem('diagram') || '[]'),
appState: { viewBackgroundColor: '#ffffff' }
}}
UIOptions={{
canvasActions: {
export: { saveFileToDisk: true }
}
}}
/>
<button onClick={handleExport}>Export PNG</button>
</div>
)
}Collaborative mode
import { Excalidraw } from '@excalidraw/excalidraw'
import { useCollaboration } from './useCollaboration'
function CollaborativeDiagram({ roomId }) {
const {
elements,
collaborators,
onPointerUpdate,
onElementsChange
} = useCollaboration(roomId)
return (
<Excalidraw
initialData={{ elements }}
onChange={onElementsChange}
onPointerUpdate={onPointerUpdate}
isCollaborating={true}
renderTopRightUI={() => (
<div className="collaborators">
{collaborators.map(user => (
<Avatar key={user.id} name={user.name} color={user.color} />
))}
</div>
)}
/>
)
}
function useCollaboration(roomId) {
const [elements, setElements] = useState([])
const [collaborators, setCollaborators] = useState([])
const socketRef = useRef(null)
useEffect(() => {
const socket = io('wss://your-server.com')
socketRef.current = socket
socket.emit('join-room', roomId)
socket.on('elements-update', (newElements) => {
setElements(newElements)
})
socket.on('collaborators-update', (users) => {
setCollaborators(users)
})
return () => socket.disconnect()
}, [roomId])
const onElementsChange = useCallback((newElements) => {
setElements(newElements)
socketRef.current?.emit('elements-change', {
roomId,
elements: newElements
})
}, [roomId])
return { elements, collaborators, onElementsChange }
}Exporting to different formats
import { exportToSvg, exportToBlob, serializeAsJSON } from '@excalidraw/excalidraw'
const exportSVG = async (elements, appState) => {
const svg = await exportToSvg({
elements,
appState,
files: null,
exportPadding: 10
})
const svgString = new XMLSerializer().serializeToString(svg)
return svgString
}
const exportImage = async (elements, appState, mimeType = 'image/png') => {
const blob = await exportToBlob({
elements,
appState,
mimeType,
quality: 0.9,
exportWithDarkMode: false
})
return blob
}
const exportJSON = (elements, appState) => {
return serializeAsJSON(elements, appState, {}, 'local')
}
const importFromJSON = (jsonString) => {
const data = JSON.parse(jsonString)
return {
elements: data.elements,
appState: data.appState
}
}Self-hosting Excalidraw
Docker
FROM node:20-alpine AS builder
WORKDIR /app
RUN git clone https://github.com/excalidraw/excalidraw.git .
RUN yarn install --frozen-lockfile
RUN yarn build
FROM nginx:alpine
COPY /app/build /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]version: '3.8'
services:
excalidraw:
build: .
ports:
- "8080:80"
restart: unless-stopped
excalidraw-room:
image: excalidraw/excalidraw-room
ports:
- "3002:80"
environment:
- PORT=80Kubernetes
apiVersion: apps/v1
kind: Deployment
metadata:
name: excalidraw
spec:
replicas: 2
selector:
matchLabels:
app: excalidraw
template:
metadata:
labels:
app: excalidraw
spec:
containers:
- name: excalidraw
image: excalidraw/excalidraw:latest
ports:
- containerPort: 80
resources:
limits:
memory: "256Mi"
cpu: "200m"
---
apiVersion: v1
kind: Service
metadata:
name: excalidraw
spec:
selector:
app: excalidraw
ports:
- port: 80
targetPort: 80
type: ClusterIP
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: excalidraw
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: excalidraw.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: excalidraw
port:
number: 80Excalidraw+ (Premium)
Premium features
Excalidraw+ ($7/month or $60/year):
│
├── End-to-end encryption
│ └── Encryption key stays with the user only
│
├── Larger storage
│ └── Unlimited diagrams
│ └── Larger files
│
├── Custom fonts
│ └── Import your own fonts
│
├── Password-protected links
│ └── Additional security layer
│
├── Custom branding
│ └── Logo on exports
│
├── Priority support
│ └── Faster assistance
│
└── Cloud backup
└── Automatic backupsPractical use cases
1. Technical documentation
# System Architecture
## Overview
Our system consists of three main components:

### Frontend
Next.js application hosted on Vercel...
### Backend
NestJS API on Railway...
### Database
PostgreSQL on Neon with branching...2. Code review diagrams
PR #123: Refactor authentication flow
Before:
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Client │────►│ Server │────►│ DB │
└──────────┘ └──────────┘ └──────────┘
│ │
│ Password │ Check password
│ (plain!) │ (slow query!)
└────────────────┘
After:
┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
│ Client │────►│ Server │────►│ Redis │────►│ DB │
└──────────┘ └──────────┘ │ (cache) │ └──────────┘
│ │ └──────────┘
│ Hashed │ Session
│ password │ check first
└────────────────┘3. Meeting notes
Sprint Planning - 2025-01-24
Epic: User Dashboard Redesign
┌─────────────────────────────────────────────────────────┐
│ Dashboard MVP │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Stats │ │ Chart │ │ Recent │ │
│ │ Cards │ │ Widget │ │ Activity │ │
│ └──────────┘ └──────────┘ └──────────┘ │
│ │
│ ┌─────────────────────────────────────────┐ │
│ │ Data Table │ │
│ └─────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
Tasks:
├── [x] Stats cards component (2 pts) - @alice
├── [ ] Chart integration (5 pts) - @bob
├── [ ] Activity feed (3 pts) - @charlie
└── [ ] Data table with pagination (5 pts) - @david4. Onboarding documentation
New Developer Onboarding
Day 1: Setup
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Clone │────►│ Install │────►│ Run │
│ Repo │ │ Deps │ │ Dev │
└─────────┘ └─────────┘ └─────────┘
│
▼
┌─────────────┐
│ Explore UI │
│ on :3000 │
└─────────────┘
Day 2: First PR
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Read │────►│ Pick │────►│ Create │
│ CLAUDE │ │ Issue │ │ Branch │
│ .md │ └─────────┘ └────┬────┘
└─────────┘ │
▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Code │────►│ Test │────►│ Push │
│ Change │ │ Local │ │ PR │
└─────────┘ └─────────┘ └─────────┘Tips and tricks
Element styling
Stroke styles:
├── Solid ────────────
├── Dashed - - - - - -
└── Dotted ············
Fill styles:
├── Solid [■■■■■■■■]
├── Hachure [////////]
├── Cross-hatch [XXXXXXXX]
└── None [ ]
Sloppiness (hand-drawn intensity):
├── Architect (0) - Clean lines
├── Artist (1) - Slight wobble
└── Cartoonist (2) - Very wobbly
Edge style:
├── Sharp ┌─────┐
└── Round ╭─────╮Keyboard workflow
Efficient workflow:
1. R → Draw a rectangle
2. T → Add text inside it
3. A → Connect with an arrow to another element
4. Ctrl+D → Duplicate and move
5. Ctrl+G → Group related elements
6. Ctrl+Shift+E → Export the finished diagramCanvas organization
Large diagrams - organization:
┌────────────────────────────────────────────────────────┐
│ TITLE AREA │
│ System Architecture v2.1 │
├────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ SECTION 1 │ │ SECTION 2 │ │
│ │ Frontend │ │ Backend │ │
│ │ │ │ │ │
│ └──────────────┘ └──────────────┘ │
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ SECTION 3 │ │ SECTION 4 │ │
│ │ Database │ │ External │ │
│ │ │ │ Services │ │
│ └──────────────┘ └──────────────┘ │
│ │
├────────────────────────────────────────────────────────┤
│ LEGEND: [Component] ──► [Dependency] ···> [Optional] │
└────────────────────────────────────────────────────────┘FAQ - frequently asked questions
Is Excalidraw free?
Yes, the basic version of Excalidraw is completely free and open-source. You can use excalidraw.com without an account, and you can also host your own instance. Excalidraw+ is an optional paid version with additional features like encryption and larger storage.
How do I save a diagram offline?
- Export to a .excalidraw file - Fully editable, can be opened later
- Export to SVG - Vector format, can be edited in Figma/Illustrator
- Export to PNG - Raster format, great for documentation
- Copy to clipboard - Quick pasting into other applications
Can I use Excalidraw in VS Code?
Yes, install the "Excalidraw" extension by pomdtr. It allows you to create and edit .excalidraw files directly in your IDE.
How do I collaborate in real time?
- Click "Live collaboration" in the menu
- Share the generated link
- Anyone with the link can edit
- Sessions are E2E encrypted
Excalidraw vs Mermaid?
- Excalidraw - Visual, drag & drop, hand-drawn style
- Mermaid - Text-based (code-based), auto-layout, formal style
Both have their uses - Mermaid for simple flowcharts in markdown, Excalidraw for more creative and freeform diagrams.
Summary
Excalidraw is an excellent tool for:
- Architecture sketching - System design, infrastructure
- Database schemas - Visualizing relationships
- User flows - UX documentation
- Wireframes - Quick UI prototypes
- Meeting notes - Visual note-taking
- Technical docs - Diagrams in documentation
- Code reviews - Explaining changes visually
The hand-drawn style makes diagrams look informal, which encourages iteration and discussion - ideal for agile teams and technical documentation.