Home Arrow Blog Arrow AI SDK
...
Arrow
I built a 3D world from a book on Ethora in a weekend

AI SDK

Published on Oct 19, 2026

I built a 3D world from a book on Ethora in a weekend

The Hatter, an AI character, greeting team members by name in a 3D tea party room during the live test
The Hatter greeting the team by name during the Monday call. Every room is an Ethora chat; every character is an Ethora AI agent.

On Friday evening I wrote a one-page brief while waiting for my son from his martial arts class. By Monday morning five people from my team were standing round a tea table in Wonderland, the Hatter was telling each of them that their hair wanted cutting, and someone had already asked for weapons.

I want to write down how that happened, what it cost, and the part I actually care about: what building on nothing but Ethora’s public surface told me about Ethora.

The idea

A chat room is a place. People are in it or not. They arrive and they leave. In Ethora an AI agent can live in one too. So what if a visitor could only be in one room at a time, had to walk to the next one through a door, and saw the other people in the room around them instead of a list of messages? And what if the rooms and the characters came from a book?

That is the whole concept. Pick a public domain book. A generator reads it and lays out its important locations as rooms on a grid. Each room becomes an Ethora chat room. Each character becomes an Ethora AI agent with the text of the book as its knowledge. Visitors enter from a link, walk around in first person, meet whoever else is there, and talk to the characters, who answer in character.

Working name: bookworld. It will get a real name before it gets a public repo.

The rules I set myself

One rule mattered more than the rest: Ethora does not change. The project uses the public React chat component, the backend SDK, the REST API and the hosted MCP server exactly as an outside developer would. Anything Ethora lacked went into a file called ETHORA-GAPS.md with the workaround used, and nothing got patched on the Ethora side to make the weekend easier. If I had allowed myself to fix the platform as I went, I would have learned nothing about what it is like to build on it.

The second rule was 3D first. I was not sure 3D was the right call against a flat version with navigation buttons, so the world file is renderer-neutral and a 2D client can follow. The third was no claiming or building by visitors yet. Seeded worlds only, until there is a population to balance for.

What got built, in order

Friday. The brief, then the scaffold: a Colyseus world service that knows where every visitor stands and which door leads where, a React Three Fiber client with a first person controller, and the Alice world written by hand with four rooms in a line and the Hatter at the tea party. The Ethora app, the four rooms and the Hatter agent were provisioned over the hosted MCP server in a few minutes; chapter seven went in as the Hatter’s knowledge, and the first test reply quoted the Queen’s concert. By the evening the chat was live inside the 3D client: guests get an Ethora identity through the backend SDK and a client token, the chat panel is pinned to the current room, and walking through a doorway re-pins it. The first in-world question to the Hatter was answered in about five seconds.

Friday night / early Saturday hours. (I’ve done these iterations mainly vibe coding via Claude Code mobile app while helping my wife looking after our child at night). Props and people. CC0 only: Kenney’s furniture and food, the KayKit low-poly characters with walk and run clips baked in, so no Adobe login for Mixamo. Speech bubbles over avatars, fed from the chat component’s own message list. Then rooms that look like places: a panorama garden from a Poly Haven HDRI, real textures on the walls, one music track per room with the credit in the corner, and character life. The Hatter strolls near his seat, turns to face whoever names him, walks to the garden every twenty minutes, and greets newcomers with “No room! No room!”.

Saturday. The generator and the provisioner. Give the generator a Project Gutenberg number and it fetches the book, splits the chapters, and asks a model for rooms on a grid with doors between them, props from the catalogue, personas, greetings and schedules. A converter fixes what models get wrong, which is a surprisingly stable list: diagonal doors, unreachable rooms, props standing in doorways. The provisioner then drives the hosted Ethora MCP server: create the app, one chat per room, one agent per character, crawl the book into each agent’s knowledge, invite each agent home. Every step is recorded, so a rerun continues where it stopped. Alice in Wonderland, six rooms, three characters: one attempt, four minutes, $2.93 in tokens (less on a subscription).

Then sound (footsteps that follow the floor material, a door creak on every room change, drips in the well, a clock at the tea party) (I really enjoyed adding this part as it was a minor and quick thing to add but a huge difference to the immersion!), a daily budget, and presence that survives a reload. Then The Tempest, generated as an enacted play: seven rooms on an island, Prospero, Ariel, Caliban and Miranda on hourly schedules that bring the right pair to the right room before each of seven scripted scenes, with lines taken from the text. $3.55. Then a world picker with live presence, a public stats API, and a “your own book” form on the join screen. The first world made through the form, while I was writing the journal entry about the form, was A Christmas Carol. $3.33, four minutes, and the card appeared before the log had finished scrolling.

Saturday night. Two boys (my sons, first QA testers for the project) ran around the island for half an hour on the home Wi-Fi and came back with a list. Your old avatar stays after a reload. You can walk through people. There is no way out. The chat background is not see-through. All four fixed before bed, and the reload one turned out to be the cause of “chat stopped working in the Tempest”, because the expired ghost seat was revoking the live seat’s room membership a minute later.

Sunday. Deployed as a fifth small service on a shared Digital Ocean server, behind Caddy web server, on a subdomain through Cloudflare, with a 350 MB memory cap and noindex while we test. The deploy itself took three attempts, all on my Mac’s side: the system bash is 3.2 and does not do what the install script assumed. Then the link went into the Monday team call.

That is one weekend from the brief to the team test, 23 commits, about 6,500 lines of TypeScript, and three worlds with sixteen rooms and eight characters between them.

What the team did with it

Within a couple of minutes five people were in the Tea Party at once. The Hatter greeted each one by name as they came through the door. Speech bubbles appeared over avatars as people typed, and the chat panel on the right carried the same conversation as any Ethora room. We moved to the island, switched on spoken lines (press ‘V’ for voiceover), and listened to Caliban complain about Prospero in the browser’s own synthetic voice, which is flat but free.

The questions were the useful part. Borys asked whether movement goes over XMPP. It does not: the chat does, positions and doors go over the project’s own WebSocket service. Which led to his better idea: carry movement over Ethora too, so that a student could host a world on a free static tier with nothing but an Ethora account. Roman wants to try a small multimodal model so characters can see what they are shown. Nikhil wants to hold the next team meeting inside the world, which means voice that fades with distance, and we already have WebRTC calls to plug in. My kids want weapons. I have watched enough product demos to know that the feature people ask for first is the one they will actually use, so I am not dismissing that one.

What it cost, and how it stops costing

Two things cost money. Every message that names a character makes its Ethora agent answer, and every generated world calls a model. The project caps both per day: character replies per world and per visitor, generator runs and dollars. At the limit the characters “rest”, the rooms get a narration line saying so, and the agents are switched to answer with probability zero over MCP until the reset.

I learned the need for the second half of that the hard way. On Saturday Ethora counted 3.7 million tokens from my local testing alone. The Tempest had been performing seven scenes an hour to an empty island, and a scripted line that names another character can draw a paid reply with nobody reading it. Scheduled lines now post only to rooms with a visitor in them. Nobody is going to bankrupt us with this, but it was a good reminder that an agent that answers when named is a cost centre that other agents can trigger.

The nineteen things Ethora should do better

This is the part I built the project for. Nineteen notes, each with a workaround, now sitting on the Ethora roadmap. The ones that matter most:

  • The App Secret stays in the dashboard. The provisioner can create an app, its rooms, agents and knowledge over MCP, but the secret that signs server tokens is only shown to the app owner in the web dashboard. So a world made by a visitor through the form has rooms and characters but no chat until I paste one line into the config. Returning it once to the creating owner would make the whole flow unattended. That one is the difference between a demo and a public “turn your book into a world” button.
  • Rooms created over MCP are public app chats. Every app user is a member of all of them, so “one room at a time” cannot be enforced by membership. The client enforces it for now. Group chats with per-user access are the fix.
  • Rooms carry no custom metadata. A world cannot live entirely inside Ethora; the world file holds the map, the wallpapers and the exits. (we do actually have some historical room metadata, wallpapers and background music capability but being honest this all needs a refactor and an upgrade)
  • No outbound webhooks per app. A server that wants to react to chat events still needs a client in the loop. The world service drives its scripts on its own timer instead.
  • Agent schedules are stored but not run. Character life is simulated by the world service rather than by Ethora. The worker is on the list.
  • Guests need a last name. A visitor who types one name shows as “Alice (guest)”.

And the other half of the finding, which I want to state plainly because it is easy to miss under a list of gaps: none of these blocked anything. A chat server, a hosted MCP server, an agent model with mention gating and retrieval, and a backend SDK for guest identities were enough to stand up a multiplayer world with living characters in a weekend. I did not expect the MCP server to be the fastest way to provision an app, but it was, by a wide margin.

Where this goes

Beyond the demo I want the project as a test bed for a question I keep coming back to: what happens when several AI agents with different roles share an environment with several people over a long time. Stanford’s Generative Agents paper showed agents with memory and reflection forming plans and relationships in a small simulated town. Here the town is a book, the agents are Ethora agents, and the other inhabitants are real people. Ethora agents already have a long-term memory they can write to themselves. The next step is social memory: a character that remembers who asked it for a song, who was kind and who was rude, and behaves differently with each of them, inside a world and in an ordinary team chat alike. If anyone on the team or outside it wants to write that up properly, I would like to.

Also on the list: the source on GitHub under MIT, a name that is not a working name, worlds described in a prompt rather than taken from a book, a 2D client on the same world file, voice between visitors that fades with distance, and a self-hosted guide for running the whole thing against Ethora Core.

One last thing. I did not spend much time on this. Not long ago, getting several people on a network to see each other walk around a 3D room, with physics, would have been weeks before the first door worked. The difference now is not that the problems went away. It is that if you know what you want and how the pieces connect, an AI coding assistant will do the weeks. The knowing is still the job.

The full write-up with the architecture diagram and the screenshots is on the case study page. If you build something odd on Ethora, I collect these stories.

Share with your community

Try Out Ethora in Action

Experience Ethora's messaging with a dedicated demo from our CEO or start building your App right now!

Free Sign Up