Skip to main content
logo_image

PlotIt

A full-stack world-building engine with an AI chronicler, interactive SVG cartography, and a relational entity graph. Built for writers and game designers who need their lore to stay consistent.

#React, #Node.js, #PostgreSQL, #Python, #Ollama, #LlamaIndex, #Drizzle ORM, #D3.js, #ChromaDB
PlotIt
Creative Tooling / AI
May 2024

Goal

Build a world-building engine that treats lore like a real database — queryable, validated, and backed by AI.

My Role

Solo Developer & Architect

Timeline & Tools

Jan 2024 – May 2024

React, D3.js, LlamaIndex, FastAPI, PostgreSQL

01. Overview

PlotIt is a world-building engine for writers, game designers, and tabletop DMs who work with large fictional universes full of interconnected details.

Instead of another note-taking app, PlotIt stores your lore as structured relational data. Characters link to races, regions sit on planets, factions track real relationships, and everything stays consistent. On top of that graph sits Demitrei, an AI chronicler that can query and reason over your actual world data.

What sets it apart

  • 12 entity types with proper relationships and foreign keys
  • A grounded AI assistant that uses both the database and vector search
  • Interactive SVG maps you can bind directly to your regions
  • A detailed hierarchical power system model

02. The Problem

Big world-building projects get hard to manage quickly. After dozens of chapters or several campaign sessions, you start losing track of who belongs where and which groups are allies or enemies.

Regular tools don’t help much. Google Docs and Notion are flat. Wikis don’t understand relationships. Generic AI chatbots make things worse by inventing details that contradict your canon. And your carefully drawn map is just a dead image with no connection to the actual lore.


03. The Architecture

PlotIt uses three separate services:

Frontend (React + Vite + Tailwind)
Entity management, Demitrei chat, interactive map viewer, and Excalidraw idea board.

Backend (Express + TypeScript + Drizzle ORM)
Handles the PostgreSQL database, business logic, and routes requests to the AI service.

Demitrei (Python + FastAPI + LlamaIndex)
Runs the ReAct agent with tool calling and vector search.


04. The Entity Graph

All data lives inside a Universe container. The PostgreSQL schema uses foreign keys and cascading deletes to keep relationships consistent.

There are 12 main entity types: Universe, Character, Race, Faction, Religion, Region, Celestial bodies, Power System, Map, Construct, Nature, and Idea Board.

The Entity Graph
The Entity GraphThe Entity Graph

05. Demitrei — The AI Chronicler

Demitrei is the feature I’m most proud of. It’s an AI assistant that actually knows your world instead of guessing.

It works in two ways:

  1. Tool calling — It can call API functions like search_characters(race_name="Arboreal") against the live database.
  2. Vector search — For backstory and narrative questions, it searches a ChromaDB store with embeddings of your entity descriptions.

Whenever you create or update an entity, an event automatically syncs the data to the vector store so the AI stays up to date.

Responses stream in real time, showing reasoning steps, tool calls, and the final answer.

Demitrei

Chain of Thought, Querying data and Tool use

Demitrei

Complex Analysis & Reasoning

Demitrei

06. Interactive Cartography

The mapping system works with SVG exports from Azgaar. You upload the map, then click any path or shape and link it to a Region in your database.

D3.js handles smooth zoom, pan, and highlighting on the frontend. Clicking a region on the map takes you directly to its detail page.


07. Technical Highlights

Layered Entity Pattern Every entity follows the same strict structure (scaffolded by my custom Rust CLI called Tether):

src/entities/character/
├── character.schema.ts
├── character.constants.ts
├── character.types.ts
├── character.validation.ts
├── character.repository.ts
├── character.service.ts
├── character.controller.ts
└── character.router.ts

Other notable parts:

Smart plural-aware full-text search (smartSearch) 6-level hierarchical power system:textRoot of Power → Power System → SubSystem → Category → Ability → Character Access Directed faction relationships (SPOUSE, PARENT_OF, REPORTS_TO, etc.) rendered as family trees and org charts with React Flow


08. Results & Reflection

The test universe “Astraeum” currently has over 500 entities. Demitrei can answer complex cross-referenced questions by calling the actual database.

Main lessons:

  • Relational data works much better than flat notes for complex worlds
  • Automatic syncing between the database and vector store is essential
  • Turning SVG elements into database links makes maps actually useful
  • Supporting both local Ollama and cloud models saved a lot of time

09. Tech Stack

Frontend: React 18, Vite, TailwindCSS, Radix UI, D3.js, React Flow, Excalidraw, TanStack Query
Backend: Express + TypeScript, Drizzle ORM, PostgreSQL
AI Service: Python, FastAPI, LlamaIndex, Ollama/Gemini, ChromaDB
Tooling: Tether CLI (Rust), Vitest