DungeonCore

The first easy-to-use, fully local AI roleplay app. The story and the inline scene images are both generated on your own machine — no accounts, no API keys, no cloud, no GPU rig. Your stories never leave your computer.

Inspiration

Most AI roleplay apps lock you into their cloud, their moderation, and their pricing. We wanted a private space where you could run an entire story — text and images — on a laptop, with no sign-up, no telemetry, and no one looking over your shoulder. DungeonCore is that space.

What it does

  • Local text generation via Ollama (Gemma 4 QAT), or Connect a server to any OpenAI-compatible backend — llama.cpp, LM Studio, vLLM, a remote Ollama, OpenRouter. Narration streams in real time as the model writes.
  • Local image generation — the narrator calls a generate_image tool and scenes render inline: FLUX.2-klein on Apple Silicon / NVIDIA / supported AMD Radeons, or point the app at your own ComfyUI instance.
  • Full play controls — Do / Say / Story input, Continue, Retry, Erase, and inline Edit on any passage. Quick-start presets write a custom opening.
  • Long-story memory — history fills the model's context window (128K–256K), and older passages compact into a rolling "story so far" summary instead of being forgotten.
  • Characters with visual continuity — saved portraits feed both the narrator (vision context) and the image generator (reference images).
  • Private by design — everything lives in a local SQLite database and folders on your disk. Play from your phone over Tailscale.
Serif story prose New story dialog with setting presets

How i built it

  • Next.js 16 app with React 19 and Tailwind v4 for the UI.
  • better-sqlite3 for local story storage — no server, no migrations, just a file on disk.
  • Ollama as the default text backend, with a streaming SSE proxy so the UI gets tokens as the model writes.
  • Python worker for image generation (FLUX via diffusers / ComfyUI), launched as a background process and called via HTTP.
  • Tool calling — the narrator can invoke generate_image mid-passage and the UI renders the result inline.
  • Rolling summary — when context gets long, a background summarization step compacts old turns into a "story so far" block the model can reference.
  • Next.js API routes for health checks, settings defaults, and chat history; everything else is client-side.

Challenges i ran into

  • Native module ABI driftbetter-sqlite3 breaks every time Node is upgraded because it ships a compiled .node binary. We had to add rebuild steps and detect the mismatch early.
  • Streaming + tool calls — getting the UI to render narration tokens while also waiting for an inline image tool call was tricky. We ended up splitting the stream into a text phase and a tool phase.
  • Long-context summarization — compressing 128K+ tokens without losing character voices and plot details required a few iterations on the prompt and chunk size.
  • Cross-platform image backends — FLUX runs differently on Apple Silicon (MPS), NVIDIA (CUDA), and AMD (ROCm / DirectML). The Python worker needed device detection and fallback paths for each.
  • Windows launcher — bundling Node, Python, Ollama, and the image worker into a double-clickable experience on Windows meant writing a PowerShell setup script that handles PATH, venvs, and GPU detection.

Accomplishments that i'm proud of

  • Zero-config first run on Mac — download the DMG, drag to Applications, open, pick a model, start writing.
  • Real inline images — the narrator decides when a scene needs an image, and it appears in the flow without breaking the read.
  • True privacy — no analytics, no cloud sync, no accounts. The entire app runs from a SQLite file and a couple of folders.
  • Cross-platform — Mac, Windows, and Linux all supported from the same codebase.
  • Phone play over Tailscale — you can run the server on your desktop and read/continue stories from your phone on the same network.

What i learned

  • Local-first changes everything — when the data never leaves the box, users trust the app more, but you also lose the safety net of cloud infrastructure. Error handling and offline states matter more.
  • Tool calling is the future of UI — letting the model trigger actions (like image generation) mid-response feels way more natural than separate buttons and panels.
  • Summarization beats retrieval for stories — for long fiction, a rolling summary the model can actually read is more useful than RAG over raw past turns.
  • Native modules are a tax — every Node upgrade costs you time with better-sqlite3 and friends. Pin Node versions tightly in production builds.

What's next for DungeonCore

  • Multi-model scenes — switch narrators or art styles mid-story.
  • Character voice tuning — save and swap speaking styles per character.
  • Export — EPUB, PDF, and plain-text exports of completed stories.
  • Plugin system — let users add custom tools the narrator can call (dice rolls, stat tracking, world-state lookups).
  • Mobile app — a proper iOS/Android build so Tailscale isn't required.
  • Community prompts — share and discover opening scenarios and narrator presets.

Built With

  • gemini
  • image-generation
  • local-llm
  • nextjs
  • ollama
  • on-device-ai
Share this project:

Updates