How newideas99/open-dungeon works
1. Overall shape
Open Dungeon is a local-first Next.js application with three major runtime pieces: the browser UI, the Next.js server/API layer, and optional local model workers. The app is designed so the browser never talks directly to model backends or the database; those interactions go through server routes.
2. Primary user interface
The UI lives under src/app and uses the App Router. src/app/page.tsx is the main experience, with layout.tsx and globals.css providing app shell and styling. The sidebar, composer, story view, character management, settings, and image controls are all client-side features backed by API calls.
3. Next.js server as orchestration layer
The src/app/api/* routes are the central coordination boundary. They expose chat CRUD, message edits, character CRUD, story generation, settings defaults, uploads, local-data cleanup, health checks, and image-worker proxying. This server layer owns validation, persistence, prompt assembly, and forwarding requests to external local services.
4. Local persistence boundary
Chats, messages, characters, settings, and story state are stored locally in SQLite via src/lib/db.ts. The default database path is data/local-roleplay.sqlite. The README also shows filesystem-backed storage for uploaded and generated media under public/uploads/, public/generated/, and public/generated/refs/. Deleting a chat or clearing local data is handled through the API and cascades through this local storage boundary.
5. Story generation flow
The main loop is: user action in the composer → server assembles the story prompt → chosen text backend generates the next passage → response is written back to SQLite and rendered in the chat. src/lib/story-prompt.ts, src/lib/defaults.ts, src/lib/runtime-defaults.ts, src/lib/text-models.ts, and src/lib/types.ts support this orchestration. The app also keeps a rolling “story so far” summary when older context is compacted out.
6. Text model backends
Text generation is abstracted behind two provider modes: bundled local Ollama and “Connect a server” OpenAI-compatible backends. The defaults and environment wiring in src/lib/server-env.ts and related lib files determine base URLs, model selection, context size, and timeouts. This makes the model backend a replaceable external dependency rather than part of the app itself.
7. Image generation architecture
Image generation is optional and isolated behind a separate Python HTTP worker. The Next.js app sends image requests to this worker through src/app/api/image-worker/route.ts and related image routes. The worker lives in image_server/ and workers/flux_worker.py, wrapping ultra-fast-image-gen backends for FLUX-based scene rendering. The app treats image generation as a service boundary, not an in-process feature.
8. Narrator tool-to-image bridge
The story model can call a generate_image tool, and the app converts that tool invocation into a local image request. If the worker is unavailable or the backend does not support tools, the app degrades gracefully and keeps the story flowing. This is an important cross-subsystem integration point between text generation and image generation.
9. Characters and visual continuity
Character portraits are first-class local data. The app stores them in the database and passes them both to the narrator as vision context and to the image worker as reference images. This makes characters a shared asset across the text and image subsystems rather than just UI metadata.
10. Local file and upload handling
User uploads and generated assets are written to disk and served from the Next.js public/ tree. The src/app/api/upload/route.ts and src/app/api/images/route.ts endpoints likely mediate this filesystem flow, keeping browser access simple while preserving local-only storage.
11. Operational scripts and platform launchers
The repository includes platform-specific launchers and diagnostics for macOS and Windows, plus smoke tests and image-server checks in scripts/. These scripts are not core product logic, but they materially define deployment and runtime topology: one Node app process, optionally one Python image-worker process, and optionally Ollama or another model server.
12. External dependencies that matter architecturally
The app depends on Node.js 22+, SQLite, Ollama or any OpenAI-compatible text backend, and the ultra-fast-image-gen repository for image generation. On Apple Silicon the image worker uses a resident MFLUX/MLX path; on Windows/Linux it uses the PyTorch SDNQ path. These backend choices affect the service boundaries and runtime matrix more than the UI code does.
13. How to diagram it
A good architecture diagram should show: browser UI at the top; Next.js server/API in the middle; SQLite and filesystem storage as local persistence; an optional Ollama/OpenAI-compatible text backend on one side; and a separate optional Python FLUX image worker on the other side. The key data flows are chat/state CRUD, story prompt generation, tool-driven image requests, and local media persistence.
Main entry points: route.ts Story API · db.ts SQLite layer · page.tsx Main app · optimized_image_server.py Image server
Components 27
Browser UI
App Router UI and client-facing experience
- Main app · Primary chat and story experience
src/app/page.tsx - Layout · Shared app shell and metadata
src/app/layout.tsx - Global styles · App-wide styling layer
src/app/globals.css
Next.js Server
API routes and orchestration
- Chats API · Chat creation, updates, and listing
src/app/api/chats/route.ts - Chat detail · Single-chat operations and lifecycle
src/app/api/chats/[chatId]/route.ts - Messages API · Message edits and chat message operations
src/app/api/chats/[chatId]/messages/[messageId]/route.ts - Characters API · Character management within chats
src/app/api/chats/[chatId]/characters/route.ts - Character detail · Single-character operations
src/app/api/chats/[chatId]/characters/[characterId]/route.ts - Story API · Assembles prompts and advances the story
src/app/api/story/route.ts - Defaults API · Exposes default settings and runtime defaults
src/app/api/settings/defaults/route.ts - Upload API · Receives local uploads and media assets
src/app/api/upload/route.ts - Images API · Serves generated and uploaded images
src/app/api/images/route.ts - Worker proxy · Forwards image requests to the separate worker
src/app/api/image-worker/route.ts - Local data · Clears local app data and stored state
src/app/api/local-data/route.ts - Health check · Runtime and service health endpoint
src/app/api/health/route.ts - Prompt builder · Builds story context and narrative prompts
src/lib/story-prompt.ts - Text models · Text backend selection and model wiring
src/lib/text-models.ts - Defaults · Baseline app and story configuration
src/lib/defaults.ts - Runtime defaults · Environment-sensitive defaults and overrides
src/lib/runtime-defaults.ts - Server env · Server-side endpoint and timeout configuration
src/lib/server-env.ts - Shared types · Core application data contracts
src/lib/types.ts
Local Storage
SQLite and filesystem-backed persistence
- SQLite layer · Local database access and persistence
src/lib/db.ts - SQLite DB · Default local persistence store
- Local files · Uploaded and generated media on disk
public
External Backends
Optional text and image services
- Text backend · Ollama or OpenAI-compatible server
- Image server · HTTP host for the Python image worker
image_server/optimized_image_server.py
Image Worker
Separate Python image-generation service
- FLUX worker · Python image-generation worker implementation
workers/flux_worker.py
Connections 31
- Layout → Main app: wraps · Provides shared app shell for the main experience
- Global styles → Main app: styles · Provides global styling for the UI
- Main app → Chats API: uses · Loads and manages chat state through the server API
- Main app → Story API: advances · Submits user actions to generate the next story turn
- Main app → Characters API: edits · Manages characters from the client UI
- Main app → Images API: shows · Fetches local and generated media
- Chats API → SQLite layer: persists · Reads and writes chat records locally
- Chat detail → SQLite layer: persists · Updates or deletes a single chat and its cascade
- Messages API → SQLite layer: persists · Stores message edits and conversation history
- Characters API → SQLite layer: persists · Stores character records for a chat
- Character detail → SQLite layer: persists · Updates or deletes a single character
- Story API → Prompt builder: builds · Assembles the prompt and story context
- Story API → Text models: selects · Chooses the active text backend and model
- Story API → Defaults: reads · Uses baseline story and app defaults
- Story API → Runtime defaults: reads · Applies runtime-sensitive overrides
- Story API → Server env: configures · Uses server endpoint and timeout settings
- Story API → Text backend: calls · Sends generation requests to the selected text service
- Defaults API → Defaults: exposes · Returns default settings to the client
- Defaults API → Runtime defaults: exposes · Returns runtime-adjusted defaults
- Upload API → Local files: writes · Saves uploaded assets to local disk
- Images API → Local files: serves · Returns stored generated and reference images
- Local data → SQLite layer: cleans · Deletes local persisted app state
- Local data → Local files: cleans · Removes local media and uploads
- Worker proxy → Image server: proxies · Forwards image jobs to the external worker host
- Image server → FLUX worker: runs · Hosts the Python worker implementation
- FLUX worker → Text backend: optional refs · Uses reference imagery and model outputs as inputs to generation
- Health check → Image server: checks · Confirms worker availability when present
- Health check → Text backend: checks · Confirms text backend connectivity when present
- Text models → Shared types: types · Shares model and runtime contracts
- Prompt builder → Shared types: types · Uses shared story data structures
- SQLite layer → SQLite DB: stores · Maps app state to the local SQLite database