From 93204ce1b0460b9dfc6066f25d561ce92270c1f5 Mon Sep 17 00:00:00 2001 From: parththakkar106 Date: Mon, 10 Aug 2026 19:21:26 +0530 Subject: [PATCH] Add a project page so the resume link loads instantly The demo sleeps on Render's free tier, so a cold link looks broken to anyone who won't wait 30-60s. A static page on GitHub Pages is never asleep: it shows the screenshots immediately and sets the expectation before the visitor clicks through to the demo. Served from main:/docs, reusing the screenshots already committed there. Palette and type match the app so the two read as one product. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_015sygnUWH8WnaoKPDp7hXM1 --- README.md | 2 + docs/index.html | 249 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 251 insertions(+) create mode 100644 docs/index.html diff --git a/README.md b/README.md index aebe4dd..4e60178 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,8 @@ scripting**. > ### ▶️ Try it live: **[ai-dnd-1gmp.onrender.com](https://ai-dnd-1gmp.onrender.com)** > Play a demo scenario as a guest — no sign-up, no API key needed. (Hosted on Render's free > tier, so the first load after it's been idle takes ~30–60s to wake up.) +> +> Prefer a tour first? The **[project page](https://parththakkar106.github.io/AI-DnD/)** loads instantly. Built with FastAPI + SQLAlchemy on the backend and React (Vite) on the frontend, running on SQLite locally and Postgres in the cloud. Works with **any OpenAI-compatible endpoint**: Ollama diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..8d051e4 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,249 @@ + + + + + +AI D&D — an AI Dungeon-style storytelling engine + + + + + + + + + + + + + + +
+ +
+
⚔ Interactive fiction, refereed
+

AI D&D

+

Open-ended adventures narrated by an LLM — with an engine that keeps the numbers honest.

+

Create a world, play it in second person, and let the model improvise the story while a Python + referee enforces what's actually true: hit points, an ally's trust, a raised alarm, a quest milestone. + Bring your own model, or play the demo with none.

+ + +

No sign-up, no API key. Hosted on a free tier that sleeps — the first load takes ~30–60s to wake.

+ +
+ The play screen with the world-state rail open, showing HP, mana, an NPC's trust and a raised alarm flag +
The left rail is live world state. The model proposes what changed this turn; the engine decides + what sticks, and the chip under the narration reports the result.
+
+
+ +
+

What makes it more than a chat wrapper

+

Three things a plain "talk to a model" app doesn't do.

+ +
+
+

The AI proposes, Python referees

+

A scenario declares stats, flags, milestones and a named cast. Each turn the model appends the changes + it thinks happened — and the engine clamps them to range, enforces per-turn caps and cooldowns, keeps + counters monotonic and milestones sticky, then strips the machine-readable block out of the prose. + Word-labelled bands (40–60: minor damage) are what make the model reliable at it. + No dice, no scripting required.

+ The scenario editor showing NPC stats with ranges, per-turn caps, cooldowns and labelled bands +
+ +
+

You can see the entire prompt

+

Every turn stores exactly what was sent to the model. Open Insights on any action to see each context + component, what it cost in tokens, and why it was there — including which trigger word pulled in each + story card and the similarity score behind each retrieved memory.

+ The Insights panel showing the assembled prompt broken into components with token counts +
+ +
+

Real AI Dungeon scripts run

+

The three familiar hooks — onInput, onModelContext, onOutput — + with shared persistent state and a worldEntries API, executed in an embedded + quickjs sandbox. Scripts written for AI Dungeon import and work, and there's a CodeMirror editor in the app.

+ The in-app script editor showing an input hook written in JavaScript +
+ +
+

Memory that survives a long story

+

The modern AI Dungeon memory system: AI-generated memories every few actions, a running story summary, + and embedding-based retrieval that pulls an old-but-relevant fact back into context when it matters. + Undo and retry roll the world state back to a per-action snapshot rather than only rewriting the text. + Every story stays where you left it, and the home page opens on its most recent line.

+ The home page, showing stories in progress alongside scenarios to start from +
+
+
+ +
+

How a turn works

+

Player input goes through the script pipeline, into a token-budgeted context, out to whichever + model you configured, and back through the referee.

+
player input
+  → onInput script modifier
+  → assemble context:  [narrator prompt] + [world state + stat guide] + [AI instructions]
+                       + [plot essentials] + [story summary] + [retrieved memories]
+                       + [triggered story cards] + [story history, token-budgeted]
+                       + [author's note] + [player action]
+  → onModelContext script modifier
+  → snapshot context (Insights)
+  → provider adapter → AI (streamed)
+  → extract + referee the world-state delta block, strip it from the prose
+  → onOutput script modifier
+  → store & render
+ +
+ FastAPI + SQLAlchemy + React + Vite + Postgres / SQLite + quickjs sandbox + Server-sent events + Docker + Any OpenAI-compatible endpoint +
+
+ +
+

Engineering notes

+

The parts that were measured rather than guessed at.

+ +
+
189×
less database egress per adventure load
+
151
backend tests, run by CI on every push
+
37
schema migrations, applied in order on boot
+
$0
to run it locally against Ollama
+
+ +
    +
  • Database egress, cut ~189×. Every adventure load was pulling the entire assembled + prompt — about 74 KB per turn — just to read two small fields off it. Moving those into their own columns + and deferring the heavy ones took one load from 38.5 MB to 0.20 MB. A test hooks into SQLAlchemy's cursor + events and fails if a bulk load ever names those columns again.
  • +
  • Turn cost, made flat. Assembling a turn walked the whole story, so it grew with story + length — 839 KB of reads by turn 200. History is now served as tails and slices from SQL: the same turn + costs 129 KB and stops growing at around turn 50.
  • +
  • A shared demo key that can't be drained. The hosted demo funds a model for visitors, so + model selection is pinned server-side with a structural backstop that raises if any code path tries to + resolve a model outside the allowed set — plus a daily per-visitor turn cap.
  • +
+
+ + + +
+ +