Utilizziamo i cookie per migliorare la tua esperienza sul sito
CodeWorlds
Torna alle collezioni
Guide26 min read

Excalidraw

Excalidraw is a virtual whiteboard for drawing hand-drawn style diagrams with real-time collaboration and SVG/PNG export.

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

  1. Hand-drawn style - Naturalny, nieformalny wygląd zachęcający do iteracji
  2. Instant start - Zero konfiguracji, działa w przeglądarce
  3. Real-time collaboration - Współpraca w czasie rzeczywistym
  4. Open-source - Darmowy, można hostować samemu
  5. Privacy-first - End-to-end encryption dla współdzielonych sesji
  6. Libraries ecosystem - Gotowe zestawy ikon i kształtów
  7. Export flexibility - PNG, SVG, JSON, clipboard
  8. VS Code integration - Natywne rozszerzenie do edycji

Excalidraw vs inne narzędzia

CechaExcalidrawdraw.ioLucidchartMiro
StylHand-drawnClean/FormalFormalMix
CenaFree/OSSFree$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

Code
TEXT
┌─────────────────────────────────────────────────────────────────┐
│  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

Code
TEXT
Rectangle (R):
┌────────────────┐
│                │
│   Prostokąt    │
│                │
└────────────────┘

Diamond (D):
     ╱ ╲
    ╱   ╲
   ◇ Romb ◇
    ╲   ╱
     ╲ ╱

Ellipse (O):
    ╭──────────╮
   ╱            ╲
  │    Elipsa    │
   ╲            ╱
    ╰──────────╯

Arrow (A):
────────────────────►

Line (L):
────────────────────

Text (T):
  Dowolny tekst

Skróty klawiszowe

Code
TEXT
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 PNG

Tworzenie diagramów

Diagram architektury systemu

Code
TEXT
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

Code
TEXT
┌─────────────────────────────────────────────────────────────────┐
│                           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

Code
TEXT
┌─────────┐     ┌─────────────┐     ┌─────────────┐     ┌─────────┐
│  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

Code
TEXT
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 diagrams

Tworzenie własnej biblioteki

Code
TypeScript
// 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

Code
Bash
# VS Code Marketplace
code --install-extension pomdtr.excalidraw-editor

# Lub przez GUI:
# Extensions → Search "Excalidraw" → Install

Użycie

Code
TEXT
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.md

Embedowanie w Markdown

Code
Markdown
<!-- W README.md lub dokumentacji -->

## Architektura Systemu

![System Architecture](./docs/architecture.excalidraw.svg)

## Database Schema

![Database](./docs/database-schema.excalidraw.svg)

## User Flow

<img src="./docs/user-flow.excalidraw.svg" alt="User Flow" width="800">

Excalidraw API i integracja

React Component

Code
TypeScript
// 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

Code
TypeScript
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

Code
TypeScript
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

Code
DOCKERFILE
# 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 --from=builder /app/build /usr/share/nginx/html

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]
docker-compose.yml
YAML
# 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=80

Kubernetes

excalidraw-deployment.yaml
YAML
# 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: 80

Excalidraw+ (Premium)

Funkcje premium

Code
TEXT
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 backupy

Zastosowania praktyczne

1. Dokumentacja techniczna

Code
Markdown
# System Architecture

## Overview

Nasz system składa się z trzech głównych komponentów:

![Architecture Overview](./diagrams/architecture.excalidraw.svg)

### Frontend

Aplikacja Next.js hostowana na Vercel...

### Backend

API NestJS na Railway...

### Database

PostgreSQL na Neon z branching...

2. Code review diagrams

Code
TEXT
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

Code
TEXT
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) - @david

4. Onboarding dokumentacja

Code
TEXT
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

Code
TEXT
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

Code
TEXT
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 diagram

Canvas organization

Code
TEXT
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?

  1. Export do pliku .excalidraw - Pełna edytowalność, można otworzyć później
  2. Export do SVG - Wektor, można edytować w Figma/Illustrator
  3. Export do PNG - Raster, do dokumentacji
  4. 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?

  1. Kliknij "Live collaboration" w menu
  2. Udostępnij wygenerowany link
  3. Każdy z linkiem może edytować
  4. 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

  1. Hand-drawn style - Natural, informal look that encourages iteration
  2. Instant start - Zero configuration, works in the browser
  3. Real-time collaboration - Work together in real time
  4. Open-source - Free, can be self-hosted
  5. Privacy-first - End-to-end encryption for shared sessions
  6. Libraries ecosystem - Ready-made icon and shape sets
  7. Export flexibility - PNG, SVG, JSON, clipboard
  8. VS Code integration - Native extension for editing

Excalidraw vs other tools

FeatureExcalidrawdraw.ioLucidchartMiro
StyleHand-drawnClean/FormalFormalMix
PriceFree/OSSFree$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

Code
TEXT
┌─────────────────────────────────────────────────────────────────┐
│  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

Code
TEXT
Rectangle (R):
┌────────────────┐
│                │
│   Rectangle    │
│                │
└────────────────┘

Diamond (D):
     ╱ ╲
    ╱   ╲
   ◇ Diamond ◇
    ╲   ╱
     ╲ ╱

Ellipse (O):
    ╭──────────╮
   ╱            ╲
  │    Ellipse   │
   ╲            ╱
    ╰──────────╯

Arrow (A):
────────────────────►

Line (L):
────────────────────

Text (T):
  Any text here

Keyboard shortcuts

Code
TEXT
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 PNG

Creating diagrams

System architecture diagram

Code
TEXT
Example architecture diagram:

┌─────────────────────────────────────────────────────────────┐
│                        Internet                              │
└─────────────────────────┬───────────────────────────────────┘
                  ┌───────────────┐
                  │   Cloudflare  │
                  │   (CDN/WAF)   │
                  └───────┬───────┘
          ┌───────────────┴───────────────┐
          ▼                               ▼
  ┌───────────────┐               ┌───────────────┐
  │    Vercel     │               │    Railway    │
  │  (Frontend)   │◄─────────────►│   (Backend)   │
  │   Next.js     │    API        │    NestJS     │
  └───────────────┘               └───────┬───────┘
          ┌───────────────────────────────┼───────────────────┐
          │                               │                   │
          ▼                               ▼                   ▼
  ┌───────────────┐               ┌───────────────┐   ┌───────────────┐
  │   Supabase    │               │     Neon      │   │   Upstash     │
  │    (Auth)     │               │  (PostgreSQL) │   │   (Redis)     │
  └───────────────┘               └───────────────┘   └───────────────┘

Database schema diagram

Code
TEXT
┌─────────────────────────────────────────────────────────────────┐
│                           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

Code
TEXT
┌─────────┐     ┌─────────────┐     ┌─────────────┐     ┌─────────┐
│  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

Code
TEXT
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 diagrams

Creating your own library

Code
TypeScript
{
  "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
Bash
code --install-extension pomdtr.excalidraw-editor

# Or via GUI:
# Extensions → Search "Excalidraw" → Install

Usage

Code
TEXT
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.md

Embedding in Markdown

Code
Markdown
<!-- In README.md or documentation -->

## System architecture

![System Architecture](./docs/architecture.excalidraw.svg)

## Database schema

![Database](./docs/database-schema.excalidraw.svg)

## User flow

<img src="./docs/user-flow.excalidraw.svg" alt="User Flow" width="800">

Excalidraw API and integration

React component

Code
TypeScript
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

Code
TypeScript
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

Code
TypeScript
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

Code
DOCKERFILE
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 --from=builder /app/build /usr/share/nginx/html

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]
Code
YAML
version: '3.8'

services:
  excalidraw:
    build: .
    ports:
      - "8080:80"
    restart: unless-stopped

  excalidraw-room:
    image: excalidraw/excalidraw-room
    ports:
      - "3002:80"
    environment:
      - PORT=80

Kubernetes

Code
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: 80

Excalidraw+ (Premium)

Premium features

Code
TEXT
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 backups

Practical use cases

1. Technical documentation

Code
Markdown
# System Architecture

## Overview

Our system consists of three main components:

![Architecture Overview](./diagrams/architecture.excalidraw.svg)

### Frontend

Next.js application hosted on Vercel...

### Backend

NestJS API on Railway...

### Database

PostgreSQL on Neon with branching...

2. Code review diagrams

Code
TEXT
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

Code
TEXT
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) - @david

4. Onboarding documentation

Code
TEXT
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

Code
TEXT
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

Code
TEXT
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 diagram

Canvas organization

Code
TEXT
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?

  1. Export to a .excalidraw file - Fully editable, can be opened later
  2. Export to SVG - Vector format, can be edited in Figma/Illustrator
  3. Export to PNG - Raster format, great for documentation
  4. 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?

  1. Click "Live collaboration" in the menu
  2. Share the generated link
  3. Anyone with the link can edit
  4. 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.