Prompts for image models
Give it an image.
Get the prompt.
A vision model reads the picture and writes the prompt that would generate it. One per image model you run: FLUX, SDXL, Pony, or whatever else you add.
§ How it works
-
01
Ingest
Upload a file, paste a URL, or let the Discord bridge pick up whatever gets posted in the watched channel.
-
02
Analyse
A worker pulls the job off the queue and asks a vision model what is actually in the frame.
-
03
Write prompts
Every image model you have enabled gets its own prompt, written in the format that one expects.
§ The core loop
One image in.
N prompts out.
FLUX takes prose. SDXL takes comma-separated tags. Pony takes score tags and a booru accent.
You get a prompt for each image model you have switched on, each stored on its own, so rewriting the FLUX one leaves SDXL untouched. Each image model carries its own formatting instructions, and those are yours to edit in settings, along with the wording wrapped around all of them.
- The original output is kept. Your edit is stored next to it.
- Edits save as you type. Favourited prompts collect on their own page.
§ Library
Everything you've ever fed it.
Filter by status or favourite, or search across filenames, notes, scene descriptions and the prompt text itself.
§ In the box
- Your own model list
- Image models live in settings, not in the code. Give one a name and the instructions for how its prompts should be written, or switch it off without deleting what it made.
- Backfill
- Add an image model later and generate its prompts for the images you already have. Or regenerate a single one you didn't like.
- Notes that steer the output
- Add a note to an image and it goes into the instructions the vision model gets. Set it when the image arrives or edit it later.
- Discord ingest
- A bot watches one channel and sends image attachments straight in. Caption it
note: …to set the note from Discord. - Prompts without a picture
- Describe what you want in words and get a prompt back for each image model you pick. Sampling is yours to tune, conversations are kept, and any reply can be saved to your favourites.
§ Image models
Three to start with.
Each one has its own instructions, so the same picture comes back written differently for every model on the list. Add or remove them in settings.
fluxFlux.1 DevsdxlStable Diffusion XLponyPony Diffusion+Whatever you're running this month
§ Chat
No picture?
Just ask.
Describe the thing you want instead of feeding it a reference. One reply streams per image model you have ticked, each written to that model's own instructions. Keep a reply and it joins your favourites.
Chat runs on its own system prompt, separate from the extraction one and editable in the same place.
§ Run it
One compose file and an endpoint.
Postgres, Redis and a MinIO bucket all come up with compose. The only thing you bring is an OpenAI-compatible vision model. A local llama.cpp server works, so does a hosted provider.
cp .env.example .env # fill in LLM_*, change the two secrets
docker compose up -d --build
Then open localhost:3000 and sign in as admin / changeme. Change that first.
§ Stack
What it's built with.
One Next.js app, two Node services, and the packages they share.
Built with
languageTypeScript, strict, shared config across the monorepowebNext.js 15 and React 19, App Router and server actionsuiTailwind 4, Radix primitives, virtualised listsdataPrisma, with migrations and a seedjobsBullMQ, with server-sent events to the browserauthbetter-auth, roles checked on every server actionbotdiscord.js, running as its own processtoolingpnpm workspaces, Turborepo, zod for config
Runs on
nodeNode 20databasePostgreSQL 16queueRedis 7storageMinIO, or any S3-compatible bucketvisionAny OpenAI-compatible endpoint, local or hostedimagesDocker, multi-stage builds, non-rootcomposeOne file for local, one for deploymentciGitea Actions, type-check and lint before build
