Skip to main content

MMORPG entries

When RPG_TYPE=mmorpg, RPGJS now treats your project as a multi-entry application:
  • a browser client
  • a framework-agnostic server module
  • optional hosting adapters such as Express
Use this layout when you want to keep your game server portable across:
  • Vite development
  • Express in production
  • another Node host such as Fastify or Hono
  • a custom deployment target later
RPG_TYPE defaults to rpg when it is not set. If this is your first online deployment, start with Put an MMORPG online, which covers local verification, map publication, Node/Docker, and Cloudflare. Keep your game logic in src/server.ts, and put host-specific bootstraps in src/entries.
Role of each file:
  • src/client.ts: browser entry for mmorpg
  • src/server.ts: RPGJS server module, without express(), listen(), or platform code
  • src/entries/express.ts: Node entry that mounts src/server.ts in Express
  • src/standalone.ts: browser entry for RPG_TYPE=rpg

Configure rpgjs()

Declare the MMORPG entries explicitly in your Vite config.

Keep src/server.ts agnostic

src/server.ts should export your RPGJS server module and nothing else. It should not:
  • create an HTTP server
  • call listen()
  • import Express directly
  • depend on a specific host runtime
Example:
This file is the canonical server entry for your game. Vite development can use it directly, and production adapters can import it without duplicating game setup.

Express adapter example

Put your Express bootstrap in src/entries/express.ts.
This adapter is responsible for:
  • serving the built client from dist/client
  • forwarding HTTP requests under /parties
  • forwarding WebSocket upgrades to the RPGJS transport

Build output

Run the MMORPG build with:
RPGJS produces two output folders:
Meaning of each output:
  • dist/client: browser assets containing client and explicitly shared modules
  • dist/server/server.js: built version of your agnostic src/server.ts
  • dist/server/express.js: built version of your Express adapter
The MMORPG client build does not include modules imported only by src/server.ts. Conversely, client-only modules and components are not part of the server entry. Files imported by both entry graphs are shared code and may be present in both outputs.
Do not import a server module, a server adapter, or a combined module index from the client entry graph. Any file reachable from browser code can be included in dist/client. Keep secrets in the deployment environment, never in source code that a browser build can reach.

Keep source maps server-side

Map assets follow the same entry boundary as modules. In MMORPG mode, install the server side of a map provider in src/server.ts; its compiler reads the complete map and streams only nearby render and prediction chunks. The client side applies those chunks but does not fetch the source document. For Tiled, expose image files through tiledMapFolderPlugin() and omit .tmx and .tsx from allowedExtensions. Event definitions, object properties, collision rules and the raw tile layer stay in the map room. The same provider module works with a Node.js transport or a Cloudflare Durable Object. Start the built Express server with:

Development flow

During development, Vite still uses the server module you pass to rpgjs({ server }). That means:
  • src/server.ts stays the single source of truth for your game server
  • your adapter files are only needed when you want a specific production host
  • you do not need a separate server-dev.ts

Add another host later

To support another runtime, keep src/server.ts unchanged and add another adapter file:
  • src/entries/fastify.ts
  • src/entries/hono.ts
  • src/entries/custom.ts
Then declare it in entryPoints.mmorpg.adapters.
The build will emit one file per adapter in dist/server.