# gpt-image-canvas puts image generation on a tldraw board

> gpt-image-canvas is a local-first workspace for prompt-to-image work, combining tldraw, a Hono API and SQLite with GPT Image 2, so images are arranged on a canvas, reused as references, and planned as a dependency graph. The trade is a Node version pinned to a single minor version, a tldraw licence key that has to be baked in at build time, and an image model that still costs money per call.

**mrslimslim/gpt-image-canvas** — Local professional AI canvas built with tldraw.

- Repository: https://github.com/mrslimslim/gpt-image-canvas
- Website: https://github.com/mrslimslim/gpt-image-canvas
- Stars: 737 · Forks: 94
- Language: TypeScript
- License: MIT
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/mrslimslim-gpt-image-canvas

## The canvas is the interface, not a settings dialog

The idea is that the working surface is a drawing board rather than a form. The README describes the project as a local AI image canvas for prompt-to-image generation, reference-image generation and multi-step Agent planning, combining tldraw, Hono, SQLite and GPT Image 2 into a local-first creative workspace. The consequences of that choice show up in the right-side panel, which has two flows. Manual lets you enter a prompt, choose size, quality and format and generate, and selecting one image shape on the board switches the flow into reference-image generation, which is the mechanic that makes the canvas more than a gallery. The second flow, Agent, is for planning a multi-image task, optionally selecting up to three canvas images, reviewing a generated plan node and then executing it. Project state, generation history and generated assets are saved locally, so the board is a document you own rather than a session in someone else's browser.```text
apps/api         Hono API, SQLite storage, provider selection, Agent planning/execution
apps/web         Vite + React + tldraw web app
packages/shared  Shared contracts and constants
docs             Project docs and preview assets
data             Local runtime data, ignored by Git
```

## Three provider routes, tried in a fixed order

Getting an image model configured is where most similar projects get complicated, and this one resolves it with a documented priority list. The default provider order is first the environment OpenAI-compatible config from .env or runtime variables, then a local OpenAI-compatible config saved in the app, and finally a Codex login fallback. For the plain API key case you edit .env, and the .env.example file shows exactly which variables exist:```env
OPENAI_API_KEY=
OPENAI_BASE_URL=
OPENAI_IMAGE_MODEL=gpt-image-2
OPENAI_IMAGE_TIMEOUT_MS=1200000
CODEX_RESPONSES_MODEL=gpt-5.5
```Leaving OPENAI_BASE_URL empty points at the official OpenAI API, and setting it to an OpenAI-compatible /v1 endpoint lets you point the same code at a different provider, with OPENAI_IMAGE_MODEL changed if that endpoint expects a different image model name. The Codex path is the third route, and there the CODEX_RESPONSES_MODEL variable controls the mainline Responses model for the ChatGPT OAuth bridge while OPENAI_IMAGE_MODEL remains the image generation tool model. One behaviour is worth knowing: environment values are read-only in the provider dialog, so changing .env means restarting the API or the Docker container.

## Agent planning is a separate chat configuration with a vision switch

The Agent tab does not reuse the image provider's configuration. Agent planning uses a separate OpenAI-compatible chat configuration, saved in the Agent LLM settings with an API key, Base URL, model, timeout and a flag called supportsVision. When supportsVision is enabled, selected images are attached to the planning request as multimodal inputs, and when it is disabled the selected images are passed only as reference handles for later image generation, which is a cheaper way to let a plan refer to an existing image without shipping the pixels to the planner. The planning request and the image request are therefore two different calls to two different models, and you configure them separately. Two limitations are stated in the README: agent messages are not persisted in this version, and plan nodes already on the canvas are saved with the normal canvas snapshot, so the conversation is not the durable artefact, the plan is.

## Plan execution is a DAG with a 16 image cap

The execution model is the part that makes the Agent tab more than a prompt box. Plan execution is DAG-based: independent jobs can run in parallel, jobs that reference generated outputs wait for their dependencies, and the Retry failed control reruns failed or blocked jobs while keeping successful upstream outputs. That last detail is what makes the retry usable, since a plan that produced four good anchors and one broken image does not have to be thrown away. A single plan is capped at 16 generated images, including intermediate anchors, which bounds the cost of a runaway plan and is the number to keep in mind when you ask for a large set of variants. The repository includes smoke commands for the pieces, one to check Agent plan validation fixtures, one to check Agent config and WebSocket basics, and one to check Agent DAG execution with a fake image provider, which is the cheapest way to see the executor work without generating anything.

## Four routes, and only one of them needs credentials

The routing table is unusually honest about what works without a provider. The root path is the credential-aware homepage, which offers Codex login and the API connection options when no provider is available. The canvas route is the working canvas, and without a provider it redirects back to the root. The pool route is the bundled Prompt Pool for browsing, searching, favoriting, copying and reusing curated prompts, with the pool JSON bundled from the prompt-pool-data directory. The gallery route remains available even without credentials, so local work can still be viewed. The app can start without credentials at all: without a usable provider, the root shows the credential-aware homepage and generation requests return missing_provider until one is configured. That is a deliberate design choice, and it means the tool opens on a laptop with no API key and does not fail with a stack trace. The scripts the repository defines are:```text
| `pnpm dev` | Start API and web dev servers. |
| `pnpm api:dev` | Start the API dev workflow. |
| `pnpm web:dev` | Start the Vite web dev workflow. |
| `pnpm typecheck` | Typecheck shared, web, and API packages. |
| `pnpm build` | Build shared, web, and API packages. |
| `pnpm start` | Start the built API package. |
| `pnpm --filter @gpt-image-canvas/api smoke:planner` | Check Agent plan validation fixtures. |
| `pnpm --filter @gpt-image-canvas/api smoke:agent` | Check Agent config and WebSocket basics. |
| `pnpm --filter @gpt-image-canvas/api smoke:executor` | Check Agent DAG execution with a fake image provider
```

## Local first, with cloud backup as a second copy

Generated images are always saved locally first, and cloud storage is an optional extra rather than the primary path. If Tencent Cloud COS or Cloudflare R2 and other S3-compatible storage is enabled from the in-app cloud storage dialog, new images are also uploaded under a key prefix followed by the year and month and the asset identifier with its extension. The COS fields are prefilled from environment variables for the default bucket, region and key prefix, and the S3 and R2 fields from a longer list that includes the R2 account identifier and an S3 endpoint. Saving cloud storage settings performs a test upload and a delete before the config is persisted, which is a good habit for credentials. Failure handling is explicit too: cloud upload failures do not fail image generation, the image remains available locally, and the history item shows the upload failure.

## The tldraw licence key is embedded at build time

There is a licensing wrinkle that catches people out, and the README is explicit about it. The canvas uses tldraw's supported development mode on localhost and over HTTP while VITE_TLDRAW_LICENSE_KEY is blank, and for a deployment that requires a tldraw hobby or commercial licence you set that variable before running pnpm build, or pass it as a Docker build argument. The catch is stated plainly: the value is embedded in the public web bundle, so changing it requires a rebuild, and it is not a secret in the usual sense. The Docker Compose file passes it through as a build argument and the GHCR workflow reads the optional TLDRAW_LICENSE_KEY repository secret. The project's own licence is MIT, and the package metadata states it directly, but the canvas component is tldraw, and a deployment that serves it beyond local development has to sort that out first.

## The build is pinned tight, on Node, pnpm and mirrors

The runtime requirements are stricter than most projects, and that has consequences for where you can deploy. Node.js 24.15.0 is the requirement, with .nvmrc and .node-version in the repository, and the package manifest narrows the engine range to greater than or equal to 24.15.0 and less than 25. pnpm 9.14.2 is pinned in package.json and activated through Corepack. The Dockerfile defaults to node:24.15.0-bookworm-slim, and the build stage installs python3, make and g++ from the Debian mirror, which is a hint that some dependency compiles native code. The mirror defaults point at the npmmirror registry and the Tsinghua Debian mirrors, and both are overridable through build arguments. The compose file then sets the runtime environment, with the API on port 8787, a data directory mounted from the host, and SQLite journal and locking modes set to DELETE and EXCLUSIVE, which is worth knowing if you ever run two instances against the same volume. To start the local services you install, copy the env file and run the dev command:```sh
pnpm install
cp .env.example .env
pnpm dev
```

## Conclusion

gpt-image-canvas suits an individual artist or a small studio that wants a local board for iterating on images, keeps project state in a local SQLite file rather than a cloud service, and wants the Agent tab to plan a multi-image job as a dependency graph before spending money on generations. It does not suit a team that needs a hosted multi-user product, since the app is local-first with a single DATA_DIR holding the credentials, and it does not suit a deployment that has to avoid the tldraw licence, since the key has to be supplied before the build and is embedded in the public bundle. Before adopting, check the Node and pnpm versions your machine has against the pinned ones, decide which of the three provider routes you will use, and note that the last push to the repository was on 2026-08-27 with the newest tagged release v0.4.0 from 2026-05-21.

## FAQ

### How do I install and start gpt-image-canvas?

Install the dependencies with `pnpm install`, copy `.env.example` to `.env`, and run `pnpm dev`. On Windows PowerShell the copy step is `Copy-Item .env.example .env`, and the web app is then at http://localhost:5173 with the API on http://127.0.0.1:8787.

### What do I need to configure before gpt-image-canvas can generate an image?

One of three things: an OpenAI API key with access to gpt-image-2 in .env, an OpenAI-compatible image endpoint through OPENAI_BASE_URL, or a Codex login completed inside the app. The provider order is environment config, then a local config saved in the app, then the Codex login fallback.

### Does gpt-image-canvas need a Docker setup to run?

No. Docker Desktop or a compatible Docker Engine is only needed for the Docker workflow, and the app runs locally with pnpm dev. The repository includes a Dockerfile, a docker-compose.yml and a docker-compose.ghcr.yml for containerised deployment.

### What is the limit on an Agent plan in gpt-image-canvas?

A single plan is capped at 16 generated images, including intermediate anchors. Execution is DAG-based, so independent jobs run in parallel, jobs referencing generated outputs wait for their dependencies, and Retry failed reruns failed or blocked jobs while keeping successful upstream outputs.

### What licence does gpt-image-canvas use, and what about tldraw?

The project is licensed under the MIT Licence, and the package manifest states it. The canvas itself is built on tldraw, and the README says a deployment requiring a tldraw hobby or commercial licence must set VITE_TLDRAW_LICENSE_KEY before the build, since the value is embedded in the public web bundle.

## Sources

- [License: MIT](https://github.com/mrslimslim/gpt-image-canvas/blob/main/LICENSE)
- [mrslimslim/gpt-image-canvas on GitHub](https://github.com/mrslimslim/gpt-image-canvas)
- [Project website](https://github.com/mrslimslim/gpt-image-canvas)
- [README](https://github.com/mrslimslim/gpt-image-canvas/blob/main/README.md)
- [Releases](https://github.com/mrslimslim/gpt-image-canvas/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/mrslimslim-gpt-image-canvas
