Hey Streamlit Community! ![]()
I wanted to share a project I built called DM Co-Pilot, an open-source AI assistant for Dungeons & Dragons. It generates VTT-ready JSON data (monsters, items, etc.) for Game Masters.
This weekend, the app unexpectedly went viral in a few TTRPG forums, hitting 450+ concurrent users. My streamlit-analytics2 dashboard just clocked 711 pageviews, 1,200+ widget interactions, and over 27 hours of active session time. Going from a quiet local build to a live stress test immediately broke my generation pipeline, so I had to re-architect it on the fly.
Here is how I kept it alive using Streamlit:
-
Global Session Memory: With 22 different generation modules, users were losing their generated JSON when switching tabs. I built a custom caching system using
st.session_stateto hold the JSON payloads globally, allowing them to switch between the Bestiary and the Loot Artificer without wiping their data. -
The Engine & Safeguards: I swapped to the Groq LPU API to bring inference latency down to sub-2-seconds. To prevent the massive traffic from generating bad JSON formats for VTT exports, I wrapped all outputs in strict Pydantic validators and used Tenacity for auto-retries.
-
Audio Scribe (New!): I just integrated the new
st.audio_inputwidget paired with Groq’swhisper-large-v3. Users can now literally speak their chaotic campaign ideas out loud, and the AI organizes them into structured text notes! -
Database: I hooked it up to Google Cloud Firestore (NoSQL) so users can publish their generated items to a live “Community Vault.”
The App: https://dm-copilot-app.streamlit.app/ The Repo: https://github.com/Cmccombs01/DM-Copilot-App
I would love any feedback from the veterans here on how you handle complex st.session_state management when dealing with large nested JSON dictionaries!