코딩, 디자인, 미디어 편집과 보정까지.
그 모든 것을 한 곳에서.
당신을 위한, 당신의 곁에 — LabelStudio.
LabelStudio는 FIG 호환 디자인 편집기, 로컬 미디어 보정 도구, 실시간 협업 서버, Figma Cloud import, 코드 핸드오프를 하나의 작업공간으로 묶습니다.
- Repository:
https://github.com/hslcrb/LabelStudio - Product:
LabelStudio - Current version:
1.1.0 - Package name:
labelstudio - App ID:
com.hslcrb.labelstudio - Default server port:
8787 - Default Vite port:
5173
- FIG ZIP import/save with additional files preserved
- Frames, rectangles, ellipses, text, lines, sections
- Multi-select, marquee select, move, resize, align, distribute
- Group/ungroup, components, instances, detach
- Auto Layout: horizontal/vertical, gap, padding, alignment, Hug/Fill subset
- Constraints-based resize
- Pen tool with line and cubic Bezier anchors
- Limited Union/Subtract for two sibling shapes
- Prototype Preview with Navigate and Back
- Undo/redo and keyboard movement
- PNG, JPEG, WebP import
- Media Library and canvas placement
- Original asset bytes stored in FIG ZIP extra files
- Crop, Fit, Stretch
- Non-destructive brightness, contrast, saturation, grayscale, blur
- Asset metadata, alt text and handoff warnings
- Design, Media and Code workspace modes
- HTML, React, CSS, token CSS and JSON manifest
- Deterministic handoff ZIP
- Semantic HTML, accessible name and component import contract
- Blocker/warning/info readiness report
- SVG, PNG and JSON export
- Optional local/server-authoritative real-time room sync over WebSocket
- Snapshot broadcast with reconnect-safe client connection status
- REST health and document snapshot endpoints
- Figma Cloud read/import through a server-side
FIGMA_ACCESS_TOKEN - Figma access tokens never belong in the Vite client bundle
New board or .fig import
|
v
D Design workspace -----> M Media workspace -----> C Code workspace
| | |
+-------- Canvas <-------+------ Inspector -------+
|
v
FIG / JSON / SVG / PNG / Handoff ZIP
Keyboard modes:
D: Design workspaceM: Media workspaceC: Code workspaceV: SelectF: FrameR: RectangleO: EllipseT: TextP: PenEnter: Finish an open Pen pathEscape: Cancel Pen draft or leave PreviewCtrl/Cmd+S: Save.figCtrl/Cmd+O: Open.figCtrl/Cmd+Z: UndoCtrl/Cmd+Shift+ZorCtrl/Cmd+Y: RedoCtrl/Cmd+D: Duplicate selectionDelete/Backspace: Delete selection- Arrow keys: Move 1px
Shift+ Arrow: Move 10px
The .fig file is a ZIP archive. The document model is a recursive JSON tree, not a relational database. The ERD below describes the persisted relationships and IDs.
erDiagram
FIG_ARCHIVE ||--|| FIGMA_DOCUMENT : contains
FIG_ARCHIVE ||--o{ ASSET_BYTES : stores
FIGMA_DOCUMENT ||--|| FIGMA_NODE : owns_root
FIGMA_NODE ||--o{ FIGMA_NODE : children
FIGMA_DOCUMENT ||--o{ DESIGN_TOKEN : labelTokens
DESIGN_TOKEN ||--o{ FIGMA_NODE : labelFillTokenId
FIGMA_DOCUMENT ||--o{ MEDIA_ASSET : labelAssets
MEDIA_ASSET ||--o{ ASSET_BYTES : path
FIGMA_NODE ||--o| LABEL_MEDIA : labelMedia
LABEL_MEDIA }o--|| MEDIA_ASSET : assetId
FIGMA_NODE ||--o| LABEL_PATH : labelPath
LABEL_PATH ||--o{ PATH_POINT : points
FIGMA_DOCUMENT ||--o{ PROTOTYPE_INTERACTION : labelPrototype
PROTOTYPE_INTERACTION }o--|| FIGMA_NODE : nodeId
PROTOTYPE_INTERACTION }o--o| FIGMA_NODE : destinationId
FIGMA_DOCUMENT ||--o{ CODE_COMPONENT_BINDING : labelCodeComponents
CODE_COMPONENT_BINDING }o--|| FIGMA_NODE : nodeId
FIGMA_NODE }o--o| FIGMA_NODE : INSTANCE_TO_COMPONENT
COLLAB_ROOM ||--o{ COLLAB_CLIENT : has
COLLAB_ROOM ||--o| FIGMA_DOCUMENT : canonical_snapshot
COLLAB_CLIENT }o--|| ACTOR : identifies
COLLAB_ROOM ||--o{ SNAPSHOT_MESSAGE : broadcasts
FigmaDocument
name: string
version?: string
lastModified?: string
schemaVersion?: number
labelTokens?: DesignToken[]
labelAssets?: Record<string, MediaAsset>
labelCodeComponents?: CodeComponentBinding[]
labelPrototype?: PrototypeInteraction[]
labelSync?: { source, fileKey, remoteVersion, importedAt }
FigmaNode
type, id, name
x, y, width, height, rotation
visible, opacity
fills, strokes, effects
constraints, layoutMode, itemSpacing, padding*
children?
labelPath?
labelMedia?
labelSemantic?, labelAccessibleName?
labelComponentId?, labelComponentName?, labelImportPath?
studioGlass?
MediaAsset
id: asset-<hash>
path: images/<hash>.<extension>
originalName: string
mimeType: image/png | image/jpeg | image/webp
width: number
height: number
byteLength: number
LabelMedia
assetId: string
crop: { x, y, width, height } // normalized 0..1
adjustments: { brightness, contrast, saturation, grayscale, blur }
alt?: string
LabelPath
version: 1
fillRule: NONZERO | EVENODD
closed: boolean
points: PathPoint[]
subpaths?: PathPoint[][]
Path handles are relative vectors: handleIn and handleOut are not absolute document coordinates.
LabelStudio intentionally uses only lime, light yellow, charcoal, white and black for its own product language. Imported FIG paint values are preserved for file compatibility; new LabelStudio boards and UI use the palette below.
| Role | Hex | Usage |
|---|---|---|
| Black | #050505 |
App background, primary dark |
| Charcoal 900 | #111111 |
Canvas and code surface |
| Charcoal 850 | #1B1B1B |
Deep panel surface |
| Charcoal 800 | #242424 |
Glass panel base |
| Charcoal 700 | #333333 |
Elevated surface |
| White | #FFFFFF |
Primary text and light surfaces |
| Light yellow | #FFF4A3 |
Secondary text, warnings, highlight |
| Lime | #D9FF4A |
Focus, selection, primary action, LIVE state |
Defined in src/styles.css:
--ink-950: #050505;
--ink-900: #111111;
--ink-850: #1B1B1B;
--ink-800: #242424;
--ink-700: #333333;
--mist-100: #FFFFFF;
--mist-200: #FFF4A3;
--mist-300: #FFFFFF;
--muted: #FFF4A3;
--quiet: #FFFFFF;
--sea: #D9FF4A;
--sea-strong: #D9FF4A;
--clay: #FFF4A3;
--sun: #FFF4A3;
--danger: #D9FF4A;
--glass: rgba(36, 36, 36, 0.9);
--glass-soft: rgba(51, 51, 51, 0.7);Defined in src/types/design.ts and persisted as FigmaDocument.labelTokens:
| ID | Name | Type | Value | Export variable |
|---|---|---|---|---|
color-ink |
color.ink |
COLOR | #111111 |
--ls-color-ink |
color-charcoal |
color.charcoal |
COLOR | #292929 |
--ls-color-charcoal |
color-lime |
color.lime |
COLOR | #D9FF4A |
--ls-color-lime |
color-yellow |
color.lightYellow |
COLOR | #FFF4A3 |
--ls-color-lightyellow |
color-white |
color.white |
COLOR | #FFFFFF |
--ls-color-white |
space-4 |
space.4 |
NUMBER | 4px |
--ls-space-4 |
space-8 |
space.8 |
NUMBER | 8px |
--ls-space-8 |
space-16 |
space.16 |
NUMBER | 16px |
--ls-space-16 |
radius-12 |
radius.12 |
NUMBER | 12px |
--ls-radius-12 |
UI variables and document tokens are intentionally separate. UI variables define LabelStudio itself; document tokens define the user design being exported.
- Windows, macOS or Linux
- Node.js
20.19+or22.12+ - npm
10+ - Internet connection for first dependency install and Electron builder downloads
npm ciUse npm install only when intentionally changing dependencies or the lockfile.
npm run devOpen http://localhost:5173.
Use another Vite port:
npm run dev -- --port 5174npm run build
npm run previewvite preview serves the generated dist/ directory, normally at http://localhost:4173.
npm run build
npm run lint
npm test
npm run server:typecheckTerminal 1:
npm run server:devTerminal 2:
npm run devThe renderer's LIVE button connects to ws://localhost:8787 by default. Health check:
Invoke-RestMethod http://localhost:8787/healthzRun the server without file watching:
npm run serverThe P0 server is an in-memory, server-authoritative snapshot room. It is intended for local/LAN development and must be backed by a database, authentication and object storage before public deployment.
The cross-platform script uses cross-env:
npm run dev
npm run electron:devEquivalent explicit PowerShell flow:
$env:VITE_DEV_SERVER_URL = "http://localhost:5173"Packaged local run:
Remove-Item Env:VITE_DEV_SERVER_URL -ErrorAction SilentlyContinue
npm run build
npm exec electron -- .Installer EXE:
npm run dist:winExpected output:
release/LabelStudio Setup 1.1.0.exe
Windows ZIP:
npm run dist:win:zipPortable EXE:
npm run dist:win:portableThe generated binaries are unsigned unless CSC_LINK and CSC_KEY_PASSWORD are configured. Windows SmartScreen may show a warning for unsigned builds.
npm run dist:linuxCheck the version first:
$version = node -p "require('./package.json').version"
Write-Output $versionAfter committing and pushing the tag:
git tag v1.1.0
git push origin main
git push origin v1.1.0
npm run dist:win
gh release create v1.1.0 (Get-ChildItem -LiteralPath .\release -Filter *.exe | Select-Object -ExpandProperty FullName) --title "LabelStudio v1.1.0" --notes "LabelStudio code-first design, media editing and collaboration release."For a release with multiple artifacts:
gh release upload v1.1.0 .\release\*.exe .\release\*.blockmap --clobberDo not publish tokens or signing credentials. gh auth status must show an account with release permission.
These values may be included in the Vite bundle and must not contain secrets.
VITE_DEV_SERVER_URL=http://localhost:5173
VITE_API_BASE_URL=http://localhost:8787
VITE_COLLAB_WS_URL=ws://localhost:8787These values belong only to the Node server environment.
PORT=8787
ALLOWED_ORIGINS=http://localhost:5173
FIGMA_ACCESS_TOKEN=your-server-side-tokenNever create VITE_FIGMA_ACCESS_TOKEN. Any VITE_* value is visible to the renderer.
Figma Cloud import:
$env:FIGMA_ACCESS_TOKEN = "..."
npm run server:devThen use Cloud in the LabelStudio toolbar and enter a Figma file key.
- There is no automatic local save to
localStorageor IndexedDB. - Unsaved changes live in memory until
.figsave or another export. .figis a ZIP with.fig.jsonand optional asset bytes.- The collaboration server currently keeps canonical snapshots in memory.
- Collaboration messages are full-document snapshots in v1.1.0, not CRDT operations.
- Do not expose Figma tokens or signing keys in the Vite renderer.
- Public collaboration deployment requires authentication, authorization, persistence, asset storage, rate limits and audit logging.
- Figma Cloud support is read/import and manual refresh; writing back to Figma requires a Figma Plugin bridge.
The Code workspace and Toolbar export generate:
<document>-handoff.zip
├── index.html
├── styles.css
├── tokens.css
├── components/LabelStudioBoard.tsx
├── handoff.manifest.json
├── README.md
└── assets/*
The package is deterministic for the same document metadata and includes only referenced assets. Code is read-only output; edit the source design or use an external codebase mapping rather than treating generated code as a second source of truth.
src/
├── components/
│ ├── CanvasView.tsx
│ ├── CodeHandoffView.tsx
│ ├── Inspector.tsx
│ ├── LayersPanel.tsx
│ ├── MediaPanel.tsx
│ ├── PreviewView.tsx
│ └── Toolbar.tsx
├── domain/
│ ├── AutoLayoutEngine.ts
│ ├── CodeExporter.ts
│ ├── DesignExporter.ts
│ ├── EditorSession.ts
│ └── MediaAssetService.ts
├── infra/
│ ├── CollaborationClient.ts
│ └── FigmaCloudClient.ts
├── lib/
│ ├── boolean.ts
│ ├── figma.ts
│ ├── matrix.ts
│ ├── path.ts
│ ├── render.ts
│ └── zip.ts
├── store/editor.ts
└── types/
├── collaboration.ts
├── design.ts
└── figma.ts
server/
└── index.ts
electron/
└── main.mjs
Implemented in v1.1.0:
- Pen/Bezier path creation and persistence
- Limited Boolean Path composition
- Local media edit and non-destructive correction
- Code-first export
- Optional local collaboration room
- Server-side Figma Cloud read/import adapter
Not yet a production collaboration platform:
- No CRDT or field-level conflict resolution
- No persistent collaboration database
- No OAuth login or multi-tenant permissions
- No Figma write-back without a Plugin bridge
- No real-time cursor/presence service
These limitations are deliberate boundaries of the v1.1.0 local-first release.