Lorebook is a local-first Python app for generating a world setting and companion character through a LangGraph workflow, with a FastAPI backend and a Svelte frontend.
src/lorebook/: Package source (state, nodes, graph, CLI).src/lorebook/api/: FastAPI app, routes, and persistence helpers.run.py: Compatibility launcher that exposes the packageapp.ui/: Svelte + Vite frontend.scripts/dev.ps1: Starts the backend and frontend together on Windows.scripts/dev.sh: Starts the backend and frontend together on Linux/macOS.outputs/: Saved run artifacts and generated assets (gitignored, app-written).user/: Permanent user-curated content (gitignored). Split into two sub-directories:user/artefacts/mirrorsoutputs/for curated run data, anduser/configs/holds personas and UI assets (backgrounds etc.). The app reads from both but never auto-writes touser/.requirements.txt: Runtime dependencies.requirements-dev.txt: Dev and test dependencies.AGENTS.md: Agent/role documentation for the pipeline.
& ./start.ps1- Python 3.12+
- A local text-generation endpoint at
http://localhost:5001 - Node.js 20.19+ and npm 10+ for the Svelte frontend
# Create virtual environment
py -3 -m venv .venv
# Activate virtual environment
.\.venv\Scripts\Activate.ps1
# Install Python dependencies
python -m pip install --upgrade pip
python -m pip install -r requirements-dev.txt
# Install package in editable mode (enables `python -m lorebook`)
python -m pip install -e .
# Install frontend dependencies
Set-Location .\ui
npm install
Set-Location ..
# Optional: override the LLM endpoint if your local server uses a different host
$env:LOREBOOK_LLM_ENDPOINT = "http://localhost:5001"# Compatibility launcher
python run.py
# Package entrypoint
python -m lorebook
# API server directly
uvicorn lorebook.api.app:app --reload --port 8000.\scripts\dev.ps1chmod +x ./scripts/dev.sh
./scripts/dev.sh# If this is a fresh checkout or ui/node_modules is missing
Set-Location .\ui
npm install
Set-Location ..
# Lint
ruff check .
# Test
pytest -q
# Frontend build
Set-Location .\ui
npm run build
Set-Location ..- Prompts load
src/lorebook/config/prompts/blank.pywhen present, otherwisesrc/lorebook/config/prompts/_template.py. - SD styles load from
user/configs/sd/styles.jsonfirst (seeuser/configs/sd/_example.jsonfor the format), then from built-insrc/lorebook/config/sd/styles.py. - General Settings includes a toggle to include baseline SD styles in the preset list; if
user/configs/sd/styles.jsonis missing, baseline styles are loaded regardless.
POST /api/run- blocking workflow run, saves JSON output tooutputs/world/POST /api/story- generate or refine structured Story artifacts with setup/instruction/action controls (generate,suggest_next_beat,rewrite_opening,add_character,add_location,add_object)POST /api/story/stream- SSE stream for initial Story generation; reports each orchestrator/specialist stage and progressively publishes completed Story sections (raw model JSON remains internal)POST /api/story-item- edit/delete individual story list items (characters_artifact,locations,objects,examples) and generate SD prompts/images for each itemPOST /api/character- generate one standalone character payloadPOST /api/save- save a run with optional story sub-artifact extractionGET /api/gallery- list saved run previews with search/tag filtering and optional artifact type filterPOST /api/character-role- persist character/persona role changes to a saved runGET /api/stream?raw_idea=...- SSE stream of per-node updatesGET /api/graph- Mermaid graph definition for the workflowGET /api/artifact/location/{artifact_id}- retrieve standalone location artifactDELETE /api/artifact/location/{artifact_id}- delete location artifact and folderGET /api/artifact/object/{artifact_id}- retrieve standalone object artifactDELETE /api/artifact/object/{artifact_id}- delete object artifact and folderPATCH /api/story/{id}/update-location- update story location and auto-create independent artifactPATCH /api/story/{id}/update-object- update story object and auto-create independent artifact
Initial Story generation uses a compact orchestrator brief followed by independent Title, Plot, History, Characters, Locations, Objects, and Openings specialists. Each specialist has a safe output-token floor, so an overly small configured maxLength cannot truncate the full artifact generation. The Story UI renders completed sections progressively while retaining JSON only as the API and persistence format; direct module edits are debounced into the Story draft cache. POST /api/story accepts optional story_setup (protagonist, opening_preference, output_format, tone, length_target), instruction, action, and current state.story_artifact for refinement passes. The response includes generation_quality (full, partial, or fallback) for UI diagnostics.
Story artifacts store Plot, Setting, Style, and History as independent text sections. openings is a list of optional chooser descriptions and role-based messages. Examples are not part of the Story schema.
Story draft internals are also split into per-section JSON files under outputs/story/_drafts/<draft>_story_sections/. List sections are persisted per-item (for example objects/silver_keycard.json) to keep section-focused updates resilient. Item image files are co-located with those item JSON files, and item JSON stores image_name (filename only).
Artifacts are organized by type with subdirectories and co-located resources:
- World:
outputs/world/<run_id>/artifact.json - Character:
outputs/character/<run_id>/artifact.json(images:<run_id>.png,<run_id>_2.png, etc.) - Story:
outputs/story/<run_id>/artifact.json(includes sub-artifacts: locations, objects, characters_artifact) - Location:
outputs/location/<run_id>/artifact.json(images:<run_id>_locations_1.png, etc.) - Object:
outputs/object/<run_id>/artifact.json(images:<run_id>_objects_1.png, etc.)
Image Co-location Strategy: Character images and story entity images (location/object/character sub-artifacts) are written to the same folder as their artifact.json file. Image paths are normalized from volatile fields (image_path, image_data) to persistent references (image_file for characters, image_name for story entities). This ensures images aren't lost on re-saves and follow standard naming conventions.
Story Sub-Artifact Extraction: When a story artifact is saved, locations, objects, and character details are automatically extracted and saved as separate artifacts if they contain meaningful content (name + description). Each becomes its own gallery entry, indexed by type and order.
Drafts are stored per type under each folder's _drafts/ subdirectory (e.g., outputs/world/_drafts/latest.json).
Lorebook intentionally separates storage into two roles:
outputs/: app-generated working storage. Good for iteration, drafts, and disposable runs; easy to clear/reset.user/: user-owned curated storage. Use this for artifacts/settings you want to keep long-term.
The app reads from both, but never auto-writes to user/. Today, promoting content from outputs/ into user/ is a manual copy step; this separation keeps ephemeral generation output independent from durable user curation.
It is split into two sub-directories:
user/
├── artefacts/ # Curated run data (mirrors outputs/ structure)
│ ├── world/ # Same artifact.json format as outputs/world/
│ ├── character/
│ ├── story/
│ ├── location/
│ └── object/
└── configs/ # UI configuration and custom assets
├── personas/ # Curated personas (meta.json + prompts.json per sub-directory)
└── backgrounds/# Custom background images for the UI shell
The Gallery, Personas, and Lore pages load from both outputs/ and user/artefacts/ automatically. If the same artifact ID exists in both, outputs/ takes priority.
Background management under user/configs/backgrounds/ is currently paused/not implemented in the active UI flow; treat this folder as reserved for the rework.
This repository keeps a tracked scaffold under user/ using per-folder README.md files. Real user content remains gitignored, while these scaffold docs describe what each folder is for and how loading/precedence works.
The gallery provides browsing and editing capabilities for all artifact types:
- Tab-based browsing: Switch between Character, Location, Object, and Story tabs
- Search & filtering: Search by name/content, filter by favorites
- Card preview: Quick preview with image, title, and summary
- Modal viewing: Click cards to open detailed modals for each artifact type
- Location editor (
/location/:id): Full CRUD for location artifacts with atmosphere, accessibility, inhabitants, and history fields - Object editor (
/object/:id): Full CRUD for object artifacts with material, purpose, origin, and properties - Features include image upload (base64 encoding), validation, and delete with confirmation
- Expandable sections in story modal for Locations, Objects, and Characters
- Toggle edit mode on any story sub-item without leaving the modal
- Auto-artifact creation: Editing a story's location or object automatically creates an independent gallery entry
- Form validation: Per-field error messages, required field checks
- Toast notifications: User feedback for save/error states
- StoryArtifactModal: Displays story with collapsible Locations, Objects, Characters sections
- LocationModal: Displays standalone location artifacts with description, atmosphere, inhabitants, history
- ObjectModal: Displays standalone object artifacts with description, material, purpose, origin, properties
- Open the Gallery tab in the top navigation
- Click an artifact card to open its modal
- For stories: Expand the "Locations" or "Objects" sections and click "Edit" to inline edit
- Editing a story sub-item automatically creates it as a separate gallery entry
- Switch tabs to view Character, Location, or Object artifacts independently
Capture a real local-LLM output once, then run tests without a live connection:
# Capture fixture data from your running local endpoint
python scripts/capture_test_fixtures.py
# Run tests offline (unit tests monkeypatch LLM calls)
pytest -q- Add robust response validation for
call_local_llm. - Implement real asset export in
save_assets_node. - Add automated tests for routing and node outputs.
