Repository navigation
Client Web Development
TL;DR: The web client (
mudjs) is a React and Vite app that speaks the JSON WebSocket protocol to the game. Work happens on thedreamlandbranch,npm run devgives a hot-reloading copy on port 3000 that connects to the live game, and a push todreamlandrebuilds and publishes the client. Themasterbranch is a frozen generic client for other MUDs. Use when: you change the web client, run it locally, point it at another server, or ship a client change. Source of truth:mudjs/package.json,mudjs/vite.config.js,mudjs/src/websock.js,mudjs/.drone.yml,mudjs/scripts/hooks/pre-pushVerified: 2026-11-02 against mudjs 990bf6d (default branchdreamland), dreamland_code 88da8302
mudjs is the browser client served at https://dreamland.rocks/play. It is public: github.com/dreamland-mud/mudjs, GPL-3.0. Players get a terminal with clickable output, side panels (location, group, affects, quest, who, weather), a graph map with search, chat frames, a help sheet, settings with aliases, macros, triggers and sounds, and a login roster. The wire format is described in Client-Web-Protocol.
Stack, from package.json: React 18, Redux, Vite 6, MUI 5, Bootstrap 4 and jQuery (the terminal and tag code is still jQuery), Monaco for the script editor, d3 and three for the map. The project needs Node 20.19 or newer (sass and its dependencies require it), the deploy uses 22.
Two branches exist:
| Branch | State | Use |
|---|---|---|
dreamland |
Default. All work lands here. Tight integration with the DreamLand protocol. | The game's client. |
master |
Frozen since 2018. Small generic client, no game-specific protocol. | A base for another MUD, see Use it for another MUD. |
git clone https://github.com/dreamland-mud/mudjs.git
cd mudjs
npm install
npm run devVite serves on port 3000 under the base path /play/, so open http://localhost:3000/play/. Edits hot-reload. By default the client connects to the public game server, so you play on the real game with a real character. Create a throwaway character if you only test the UI.
package-lock.json is ignored by git. The deploy build runs npm install --legacy-peer-deps, so use the same flag if npm install complains about peer dependencies.
The dev server proxies four paths (vite.config.js):
| Path | Goes to |
|---|---|
/api |
http://localhost:4000 (a local API, if you run one) |
/maps, /help, /data
|
https://dreamland.rocks (map JSON, help dumps, site data) |
Map graph files can be staged locally: put them under dev-maps/graph/ (git-ignored) and the dev server serves them at /maps/graph/ before the proxy. A missing file falls through to the proxy, and the map shows its ASCII fallback if there is no data at all.
If the page loads and the socket never connects, check whether an ad blocker is active on the page. They are known to block the WebSocket.
The server address is the wsUrl constant at the top of src/websock.js:
- Default: the public game server.
- Open the page with
#buildin the address to connect to the build server (the sandbox where builders and scripters work). Ask the team for a builder character first, see Building. - Local play is not supported through this client. The web client expects the full nanny dialogue of the live server, which a stock local server does not provide, and the client source says the local WebSocket on 1234 stalls at login. Use telnet on port 9000 (or the backdoor on 9001) for a server on your machine, see Local-Setup.
npm run build # writes build/
npm run preview # serve build/ locallyThe output goes to build/, not Vite's default dist/. Every build stamps an id into the bundle and into build/version.json. A running client polls that file every three minutes and reloads itself into the new build once the player has been idle for 15 seconds and is not in a fight (src/autoupdate.js). Until then a dismissable banner offers an immediate update.
-
Branch from
dreamland, change, open a pull request againstdreamland. Commit messages and PR text are English. -
Install the pre-push hook once. It runs
npm run buildbefore every push and skips itself whennode_modulesis missing:ln -sf ../../scripts/hooks/pre-push .git/hooks/pre-push
Bypass one push with
git push --no-verify. -
A push to
dreamlandtriggers the project's CI (.drone.yml). It resets the deploy checkout to the branch head, runsnpm install --legacy-peer-depsandnpm run build, and reports success or failure to the team chat. The built files are the live client. There is no staging step, so a broken merge breaks/playuntil the next good push. -
.travis.yml(Node 14, plain build) is legacy and no longer matches the Vite version..gitpod.yml(build andpython3 -m http.server) is also old and was not re-tested (unverified).
src/ at the top level holds single-purpose modules, src/components/ the React views.
| Path | What |
|---|---|
websock.js, telnet.js
|
Socket, reconnect, resume, keepalive, KOI8 decoding and telnet bytes. |
store.js, prompt.js, react-hooks.js
|
Redux store and the merged prompt object (window.mudprompt). |
manip.js, ansi2html.js
|
Turn output tags and ANSI colours into elements. |
input.js, aliases.js, macros.js, triggers.js, settings.js, sound.js
|
The command line and the player's scripting layer. |
i18n.js, langsync.js
|
Interface language (en, ru, ua) taken from the prompt. |
components/terminal.jsx |
Output area. Live region for screen readers. |
components/mapper/ |
The graph mapper (rooms, z-layers, search, path finding). |
components/windowletsPanel/ |
Side panels. |
components/settings/ |
Settings dialog and its pages. |
components/sysCommands/ |
The client-side # commands (#help lists them). |
components/chat/, components/helpSheet/
|
Chat frames and the help sheet. |
Interface strings live in i18n.js in three languages. Game text arrives from the server already in the player's language, so do not translate it in the client.
Accessibility rules apply to every change: the terminal output is a polite live region, panels repeat information that is also in the text, and nothing may exist only as an icon or colour. See Accessibility.
The simple route is the frozen master branch. Your server needs WebSocket support. If it speaks plain telnet, put websockify in front of it:
websockify :4321 :9000Then set wsUrl in the page that loads the client, for example ws://yourmud.com:4321. The host must match the host that serves the page. The first thing the master client sends after connecting is a codepage digit. DreamLand's codepage menu uses 7 for UTF-8. Change the digit to whatever your MUD expects. This route is not tested on any other MUD (unverified).
The dreamland branch is not generic: it expects the DreamLand RPC events, the nanny dialogue and the prompt object, and it refuses to connect unless the server sends the matching version string.
Start here
Get running
Contribute
- Contribute
- Contributing Workflow
- Code Style
- Accessibility
- Writing Player Text
- Game Design Principles
Build areas
- Building
- OLC
- OLC Rooms
- OLC Mobiles
- OLC Objects
- OLC Resets
- OLC Line Editor
- OLC Other Editors
- Area Format
- Area Quests
- Mob Forms and Parts
Fenia
- Fenia
- Fenia Language
- Fenia Triggers
- Fenia Gotchas
- Fenia API
- Fenia Scripts
- Fenia Behaviors
- Fenia Skills and Spells
- Fenia Cookbook
- Fenia Grammar
Engine
- Engine Architecture
- Engine Time and Pulses
- Output Format
- Mechanics Combat
- Mechanics World
- Data Configs
- Item Power
Localization
Clients
More