README.md

June 23, 2026 · View on GitHub

darkly

Discord Patreon Blog

Rust Svelte WebAssembly WebGPU Tests Coverage

Important

Darkly is in beta! Features are being added daily. Please report bugs so we can squash them.

Darkly is a GPU-native editor written in Rust and geared towards digital artists. It aims to have everything you expect from a paint program, plus some special dark arts to help you rage against the machine.

Darkly pledges to:

  • 🛐 Honor human imagination
  • ⚛️ Run offline and without a login
  • ☯️ Never steal or license your art
  • ☮️ Stay free and open source forever

Do you suffer from the oppressive sanity of rulers, guides, and nondestructive workflows? Break free with Darkly, where messes are made and happy accidents emerge. Madness isn't a bug, it's a feature.

Try the demo here.

darkly

Features

Node-Based Brush Engine

brush-engine-screenshot

Darkly features a unified node-based brush system. Every brush type -- clone, liquify, watercolor, etc. -- all live in a single engine. This enables infinite customizability, mixing and matching of brush features, and on-the-fly creation of custom brushes.

Familiar Hotkeys

On first launch, Darkly will ask you which editor preset you want. Currently we support GIMP, Krita, and Photoshop. I come from Krita, so that one's gotten the most TLC. But we want everyone to feel at home no matter which editor they come from. If you find any gaps, please let us know!

Hotkey Cheatsheet

Darkly also comes with a searchable hotkey cheatsheet, which opens in a separate window, handy for printing or putting on a second screen.

Dark Arts

Veils

https://github.com/user-attachments/assets/ee281ac2-37a8-4e52-91b3-78d564420e9d

Veils are where Darkly gets its name; "For now we see through a glass, darkly". They're a special type of layer that sits overtop the viewport, visible only to the artist. By shrouding your art behind a mysterious pane, they invite you to see something that maybe wasn't there before.

Veils have practical uses too:

  • By hiding fine details, they can prevent premature fixation on detail, freeing you to focus on composition.
  • During the sketching / ideation phase, they can help with blank page syndrome and destructive self-criticism by giving you permission to be messy, and explore freely.
  • They can also help remedy art fatigue (losing eyes for a piece by staring at it for too long) by helping you view it through a fresh lens.

Note

Veils live in their own group, but within it you can stack and order them however you like. Remember that adding too many can drain your battery, due to the heavy load on your GPU.

Voids

https://github.com/user-attachments/assets/43dac748-d79f-403f-8456-10dad779a6f9

Voids are a type of layer that specializes in pulling inspiration from outside sources.

You can use the Noise void to inject entropy, or Screenshare to stream another app (3D software, movie, or video game) directly into a layer. This is great for hybrid workflows, and situations where you want to try out different lighting or camera angles, without having to pose, render and paste over and over.

Voids can live anywhere in your layer stack -- over or underneath any other layer. They support masks and blend modes. They are the natural compliment to veils, and a natural integration point for other art programs like Blender, which may have dedicated voids in the future 🧡

Feature Roadmap

These features are ordered roughly by importance. They will be implemented mostly in order from top to bottom, prioritizing ones most requested by the community.

For a feature to count, it must be:

  1. Implemented in Rust backend
  2. Have a proper frontend action, with a menu path and hotkey in each editor preset, if applicable

Essential / Must-Have

  • Node-based brush engine
  • Brushes
    • Simple round
    • Ink pen
    • Charcoal (Pencil still TODO)
    • Smudge
    • Watercolor
    • Liquify
    • Clone
    • Blur
    • Dodge/burn
    • Calligraphy
    • Oil / Impasto
  • Brush tool, eraser, fill (flood), gradient (linear), color picker
  • Pressure / tilt / spacing / distance / angle inputs
  • Laplacian stabilizer
  • HSV picker, foreground/background swatches
  • Color picker (Ctrl-held temporary pick)
  • Raster layers + groups, drag‑reorder, visibility, lock, opacity, name, collapse, passthrough
  • 16 blend modes
  • Layer masks
  • Rect, ellipse, lasso, polygon, magic wand selection
  • Selection Replace / Add / Subtract / Intersect modes
  • Pan / zoom / rotate view
  • Undo / redo (configurable depth, defaults 100)
  • New document (custom canvas size + background color)
  • Open image from file
  • Save / Open native .darkly document
  • Export to PNG / JPEG / WebP file
  • Clipboard copy / cut / paste (PNG via browser clipboard)

Important — expected for serious work

  • Generic transform tool (translate / scale / rotate gizmo — floating content + transformable voids)
  • Merge down
  • Duplicate layer / group
  • Crop to selection
  • Canvas resize
  • Image rescale
  • Select All / Deselect / Invert as menu+hotkey actions
  • Command palette (Ctrl+Shift+P)
  • Application menu (File/Edit/Select/… , pinnable to top bar)
  • Autosave + crash recovery
  • Filter layers (non-destructive; isolate to one layer via a group)
  • [ ] Brightness / Contrast
    
  • [ ] Hue / Saturation / Lightness
    
  • [ ] Levels
    
  • [ ] Curves
    
  • [x] Invert colors
    
  • [ ] Desaturate
    
  • Clipping mask
  • Feather + antialias
  • Grow / Shrink / Border / Smooth as discrete commands
  • Flip canvas H / V
  • Rotate canvas 90° CW / CCW / 180°
  • Flip layer / selection H / V
  • Text tool / text layers
  • Recent colors
  • Saved swatches / palettes
  • History panel UI
  • Mirror view
  • Fit to screen
  • 100% / zoom presets
  • Symmetry / mirror painting (X, Y, radial)
  • Installable PWA — offline app shell, add to home screen
  • Krita / Photoshop / GIMP hotkey presets
  • Settings modal (8 config sections, typed widgets), theme system
  • Hotkey system + searchable cheatsheet (80+ rebindable actions)
  • Floating layers (transient paste / transform)

Advanced & specialized — power-user, niche, and polish

  • Veils (stackable viewport post-process effects: frozen, grain, lens blur, monochrome, painting, pixelate, rainy glass, VHS, watercolor)
  • Veil picker with live animated previews
  • Void layers (domain‑warped FBM noise)
  • Camera void (live webcam, positioned with the on-canvas transform gizmo)
  • Screenshare void (live getDisplayMedia capture, positioned with the on-canvas transform gizmo)
  • Group blend mode / opacity (isolated + passthrough compositing)
  • Brush save/load + editable nodes/wires (e.g. YAML)
  • Recent files
  • PSD / XCF / KRA import
  • Perspective, skew, free distort
  • Warp / mesh transform
  • Gradient map
  • Color balance
  • Channel mixer
  • Threshold
  • Posterize
  • Color harmonies
  • Palette file import (.aco, .gpl)
  • Palette Popup
  • Navigator / overview window
  • Trim to content / autocrop
  • Stroke selection (paint along marching ants)
  • Save / load selection to channel
  • Snap canvas to right angles (0, 90, 180, 270)
  • Branched history

Getting started

Prerequisites

# Install all workspace dependencies (frontend + website + shared styles)
npm install

# Build the WASM package
wasm-pack build frontend/wasm --target web

# Start the frontend dev server
npm --prefix frontend run dev

Open the URL printed by vite (typically https://localhost:5173). Requires a browser with WebGPU support (Chrome 113+, Edge 113+, Firefox Nightly with flag).

GPU backend configuration (Linux): Chrome's WebGPU defaults to a software rasterizer on many Linux setups. Launch Chromium with GPU and Vulkan support:

chromium --enable-features=Vulkan --enable-unsafe-webgpu

You can verify the active backend at chrome://gpu - look for "Vulkan" under Graphics Feature Status. On macOS and Windows this is generally not needed (Metal and D3D12 are used by default).

Use of AI

It's acceptable to use AI for this codebase, but careless vibe coding is strictly forbidden.

I (TheTechromancer) learned to code before AI, and have spent much of my career maintaining large codebases. The danger of feature creep and architectural bloat is real, which is why whenever a feature is implemented in Darkly, a human must first understand the changes and their long-term implications for the codebase.

Great care is being taken to keep Darkly lean and clean. This means enforcing modularity, guarding vigilantly against duplicate/dead code, and writing a shit ton of unit tests, including at least one regression test for every bug. See AGENTS.md for how we avoid AI slop.

Note that while we allow AI for coding, we are unlikely to accept any PR implementing generative AI in Darkly itself. AI features are not off the table; however they must run fully offline and without any reliance on third party APIs. Additionally, any feature that speeds up generation while sacrificing creative input or control from the artist, will be immediately rejected.

Every PR must open with a short human-written description explaining why the effort was undertaken and who it's useful to, above the AI-generated technical description. PRs that look entirely machine-generated will be closed.

We are not sensitive to AI-related questions. If you're unsure, please ask!

Acknowledgments

Darkly stands on the shoulders of giants. Three programs in particular have influenced this project, and we love them dearly.

GIMP (source) - originally written by Spencer Kimball and Peter Mattis in 1995, and maintained today by Michael Natterer and Jehan Pagès, with decades of contributions from a community far too large to list here (see the upstream AUTHORS file).

Krita (source) - led by Halla Rempt, with core contributions over the years from Dmitry Kazakov, Cyrille Berger, Sven Langkamp, Wolthera van Hövell tot Westerflier, L. E. Segovia, Scott Petrovic, and many more (see the upstream developers.txt).

Graphite (source) - founded by Keavon Chambers (@Keavon), with the core team of Dennis Kobert (@TrueDoctor), Timon Schelling (@timon-schelling), and Adam Gerhant (@pendapia), plus heroic contributions from Hypercube (@0HyperCube), James Lindsay, and hundreds more. Graphite is a pioneer in bringing serious 2D graphics tooling to Rust + WebAssembly + WebGPU.

While Darkly's architecture is fundamentally different, it was really insightful to see how these tools tackled many of the same hard problems, and their unique and smart approaches that made them pillars of open source!

Veils & Voids

Some of Darkly's veil and void shaders are ports or adaptations of work originally published on Shadertoy. I suck at shaders and the creators of these shaders are true artists. Please go see them in their native habitat!