A native canvas with an AI co-pilot
built right in.
Artists needed a fast, native tool for concept art that integrates AI editing without leaving their canvas. InkForge is that app — pure Swift, GPU-backed, Procreate-inspired, and built in close collaboration with the art team to fit real production workflows.
Watch it in action
Screen recording of the full app — layered painting, AI inpainting, the neumorphic toolbar, and QuickShape detection in use.
Design system
Studio Slate dark tokens, the steel-blue single accent, neumorphic raised/recessed controls, and the icon mark — the full, code-truthful spec.
Under the hood
Swift · AppKit · CoreGraphics · Gemini & Replicate APIs. Pure native, GPU-accelerated bitmap rendering. No Electron, no web views — fast by design.
Concept artists switch between five apps to do what one should handle.
The art team's workflow was a patchwork: sketch in one app, clean up in another, run AI generation in a browser tab, paste the result back. Every round-trip cost flow state — the creative moment breaks when you're hunting for an export button. The ask was a single native canvas where you paint, smudge, select, and ask the AI to fill a region — without leaving the drawing surface once.
One canvas, five stages. The AI lives in step four, not a separate app.
I sketched the session loop on paper first — to confirm that AI editing could slot in naturally without breaking the rhythm of building up a piece layer by layer.
background preset
blend modes
magic wand
style transfer
custom DPI
The decisions that shaped the whole app.
"Integrated AI editing" is easy to say and hard to make feel native. Three early bets turned it into a real experience — how the AI fits into the layer model, how the UI stays out of the way, and what kind of control surface belongs on a drawing app.
AI results land as layers, not replacements.
When an inpaint or generate call returns, the result arrives as a new layer above your work — not baked onto the canvas. You can blend it, mask it, tweak its opacity, or discard it entirely. The AI proposes; the artist decides. That framing made the feature safe to use mid-piece, not just as a last step.
The canvas is the only saturated thing.
The entire UI runs on a five-stop dark grey scale. No saturated colour anywhere in the chrome — not on icons, panels, or hover states. The steel-blue accent appears in exactly one role: the active tool. Everything else is monochromatic, so colour decisions on the canvas read true. An artist picking a warm neutral shouldn't see it compete with an orange toolbar button.
Neumorphic controls: feel pressable without hover.
InkForge is a tablet-first app — hover is unreliable on Wacom surfaces. Controls signal affordance through form: buttons are raised pads with a top-left highlight, slider tracks are recessed grooves. A user can tell at a glance — without any pointer — what is pressable and what is a readout. That clarity turns out to matter even on a non-tablet display.
Small calls that change how the whole thing feels.
Most of what makes a drawing app feel right is a pile of invisible decisions. Here are the six I'd defend in a critique.
Monospaced digits for all numeric readouts.
Brush size, opacity, and knob values use monospacedDigitSystemFont so the control doesn't jitter laterally as numbers tick. A "99" and a "100" take up the same horizontal space. Tiny detail, zero visual noise.
QuickShape snaps on a held stroke, not a button.
Hold the pen still at the end of a stroke for 300ms and the rough line snaps to a clean line, ellipse, or rectangle. No mode to switch, no shape tool to pick up — the gesture is the trigger. Artists use it constantly without thinking about it.
Alpha Lock preserves transparency without a clipping layer.
Alpha Lock saves and restores the layer's alpha channel around every draw call, so you paint inside an existing shape without creating a new clipping mask layer. It collapses a two-layer workflow into a single toggle — the shortcut Procreate users consider table-stakes.
The AI sheet opens over the canvas, not over a menu.
Cmd+Shift+A opens the AI sheet as a floating panel anchored to the top-right while the selection stays live on the canvas behind it. You see exactly what region you're inpainting while you type the prompt — the spatial context remains visible throughout.
Six procedural brush textures, no bitmap files.
Round, Dry Brush, Ink, Charcoal, Stipple, and Noise tips are generated at runtime from BrushTipGenerator — no PNG assets to pack. That keeps the build tiny and lets jitter parameters (size, opacity, angle, rotation mode) work continuously across the full pressure range.
Reference Layer — fills without flood overflow.
Mark any layer as the Reference Layer and the Fill tool uses it as the boundary source while painting on a different layer above. Clean fills on a flat sketch layer, painted colour on a separate layer — no masking required. One toggle that eliminates the most common flood-fill frustration.
One dark system, used everywhere.
InkForge runs on the "Studio Slate" system — a five-stop dark grey hierarchy with a single steel-blue accent. No warm tints, no saturated hues in the chrome. Colour in this app belongs to the artwork. Here's the short version; the full spec lives on the Design page.
One hue in the whole interface.
Five greys build the surface hierarchy — each step ~4 points lighter than the last. Steel blue #4874B0 marks the active tool, focused control, and selected layer. Nothing else is coloured. The user's artwork is the only saturated thing on screen.
SF Pro at system scale, mono digits for readouts.
Crisp and system-native. Headings use weight 700 only at section scale — weight 500 handles everything below. No custom display face competes with the artwork.
Medium weight at 12–16px across all controls. Low optical footprint — the chrome reads without shouting over the canvas.
Monospaced digits prevent knob readouts from jittering as values tick. Also used for hex inputs, section eyebrows, and the spec voice you're reading now.
Small radii for a precision tool.
Drawing apps fight for canvas space. Radii are tighter than in consumer apps — large rounded corners read as "friendly app", not "precision instrument". Four steps cover everything from a count badge to a toolbar button.
The icon is a pen nib with an AI spark.
The icon combines a pen nib — the founding metaphor of digital drawing — with a small sparkle glyph in steel blue, representing the AI feature. The dark background matches the app's own dark workspace, so the icon on a macOS dock reads as a window into the app itself. In-product glyphs are SF Symbols line icons at system stroke weight, keeping chrome and OS continuous.
Purposeful feedback, nothing decorative.
The cuts I'd defend.
A solo native app has to be focused. Here's what was explicitly deferred — each cut keeps the app fast, offline-capable, and clear in its purpose as a drawing tool first.
Files live on disk, not a backend. Cloud sync requires a server, a login system, and conflict resolution for a binary bitmap format. Deferring it means the app opens instantly, works fully offline, and the user controls their files. The trade-off is no cross-device access — acceptable for a v1 professional tool used at a fixed desk.
No third-party brush or filter plugins in v1. A plugin architecture requires a stable, versioned API surface — expensive to maintain correctly. The six procedural brush tips and twelve blend modes cover the production use-cases the art team actually needed. Extension points are stubbed in the architecture but not exposed.
Frame-by-frame animation and timeline are out of scope. Adding a frame timeline would require rearchitecting the layer model into a two-dimensional structure (layer × frame). That's a v2 feature. For v1 the goal was making a single-frame workflow feel complete and fast — which it does.
Mobile port is deferred. The neumorphic controls, Wacom pressure integration, and AppKit-specific coordinate system were built for macOS first. An iOS version would need a ground-up UIKit rethink of the layer panel and toolbar. That's a separate project, not a port.
Built solo, on the native macOS stack.
Pure Swift and AppKit — no game engine, no cross-platform framework, no web view. Each layer is its own CGContext bitmap composited at render time. Wacom pressure flows directly into brush dab size and opacity via NSEvent.pressure.