ritwiksharma.com
Work
AI Systems · Live Platform · Solo author · Ongoing

Soup

A persistent gaming community ecosystem spanning a Project Zomboid game server, a Discord community of several thousand active members, and a custom Next.js web platform. Same data, three different runtimes, real-time sync. Built and operated solo.

Role
Solo, architecture, full-stack, ops
Status
Live
Duration
Ongoing

What it is

Soup is the platform underneath a Project Zomboid multiplayer community. It runs across three completely different surfaces (a Lua-modded game server, a TypeScript Discord bot, and a Next.js web app) and presents a single, consistent world to its members. A shop you see on the website is the same shop you walk up to in-game. A reputation score generated by an LLM is visible in Discord, on the leaderboard page, and on your in-game character profile.

The community itself is several thousand active members. The platform handles their economy, their progression, their shop network, their seasonal events, their leaderboards, and their interactions with Zombita, the persistent AI agent that lives inside all three surfaces.

Zombita character page on the Soup website with smirk reaction
The Zombita interaction page on the Soup website. The same agent appears in Discord and in-game.

The hard part

The technical challenge isn't building a Discord bot, or a game server mod, or a web app. Each of those is a known problem. The hard part is keeping all three in sync as a single system: same source of truth, same state, same identity layer, same economy, same reputation, with users interacting from any surface at any time.

Architecture

The shape is a hub-and-spoke: a single canonical backend, with three runtime adapters that translate that backend's state into something each surface understands.

                  ┌──────────────────────────┐
                  │   Soup Backend (canonical) │
                  │   Database · Identity ·    │
                  │   Economy · Reputation     │
                  └─────────────┬──────────────┘
                                │
        ┌───────────────────────┼───────────────────────┐
        │                       │                       │
        ▼                       ▼                       ▼
┌───────────────┐       ┌───────────────┐       ┌───────────────┐
│  Lua adapter  │       │  Discord bot  │       │  Web (Next.js)│
│  in-game UI   │       │  TypeScript   │       │  React + SSR  │
│  shopkeeper   │       │  commands +   │       │  shop, leader │
│  dialogs,     │       │  Zombita      │       │  -board, mods │
│  triggers     │       │  conversation │       │  pages, admin │
└───────────────┘       └───────────────┘       └───────────────┘
        │                       │                       │
        └───── Real-time bridge ─────────────────────────┘
                  (single source of truth)

The key design choice: the runtimes never talk to each other. They talk to the backend. This keeps the system from collapsing into N-to-N integration hell, and lets me add a fourth surface (WhatsApp, Teams, a mobile app) without rewiring anything.

The shop network

The clearest demonstration of cross-runtime sync is the shop system. Eight named NPCs run shops with rotating stock. Stock can be edited from the admin panel, viewed publicly on the website, and bought from in-game.

Marketplace and Shop Management admin view showing five named NPCs
Marketplace & Shop Management. Five rotating shops, dynamic pricing, force-rotate controls, ban management. The same data feeds the public shop page and the in-game dialogs.
Public shop network page showing all eight shopkeepers
Public-facing shop network. Same backend, different surface. Players check restock timers from the web before logging into the game.
In-game NPC shopkeeper dialog showing Dex Malone's gas station shop
The same shop, in-game. The player right-clicks an NPC, this dialog opens, and the stock listed is whatever the backend says it is at this moment.

Why this matters: any one of these screenshots is a screenshot of a web app, a game UI, or an admin panel. Together they're a screenshot of the same thing, rendered three ways. That is the entire point of Soup as a platform.

Economy & treasury

The economy is fully closed-loop. There's a treasury cap, weekly recycle injections, a burn rate, and per-user wallets that can hold three currency tiers. Every transaction (buy, sell, marketplace listing, leaderboard payout) is logged with a full event log going back weeks.

Treasury overview
Treasury overview, circulating supply, cycle status, 24h flows.
Per-item inventory management
Per-item inventory. Stock, base prices, dynamic pricing, on/off toggle per item.

The economy isn't just numbers, it's the underlying mechanic that drives player engagement. A poorly-tuned economy kills a community in weeks. Soup's economy has been live and stable for months.

Reputation & Zombita's read

Every player has a daily Zombita-generated commentary on the leaderboard. It's not a stock template, it's an LLM-produced read on what that player has been doing in the community over the past day. Combined with point totals and an archetype label (competitor / lurker / known / neutral), it doubles as a public-facing social barometer.

Leaderboard showing Zombita's per-player AI-generated commentary
Per-player Zombita commentary, regenerated daily. "Dawn's chat activity today was a nice addition to the community, but I still think a sprinkle of humor would do wonders for their competitive edge."
Survivors directory showing all known community members
Survivors directory. Every member Zombita has interacted with.
Individual player profile page
Individual player profile, stats, archetype, Zombita's reputation read, game history.

Operations

Soup is a production service with a live user base. That means it needs the same kind of operational tooling any real platform needs: service health monitoring, restart controls, deployment, and emergency procedures.

System panel showing service health for Discord bot, Zombita API, and Game Server, plus server wipe controls
System Panel. Three services monitored, Discord bot, Zombita API, game server. Restartable from the web. Three tiers of server wipe, the most destructive available only via SSH.
Server admin status page showing game server uptime and online players
Server admin status. Uptime, online players, RCON access, in-game item granting: all from the same web interface.

Lua mod suite

Alongside the platform, I built a suite of Project Zomboid Lua mods that hook into the same backend, extending the in-game world with content that's driven by Soup's web layer and triggerable from Discord.

Each of these would be impressive in isolation. The point is that they're not in isolation. They're four manifestations of the same backend, written in three different runtimes, presented as one consistent experience.

Stack

Next.js 15 TypeScript React Tailwind CSS Cloudflare Pages Cloudflare Workers Node.js Discord.js Python Project Zomboid Lua API SQLite WebSocket bridges

What this project demonstrates

Related work