Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ClassicUO/classicuo-web/llms.txt

Use this file to discover all available pages before exploring further.

This guide walks you through creating a working ClassicUO Web mod from scratch. You will initialise a TypeScript + React project, install @classicuo/modding, write your first component, bundle it with Parcel, and register the mod URL in your shard’s configuration. The modding-example package in the ClassicUO Web monorepo is a complete reference you can clone and adapt.
1
Create and initialise your project
2
Create a new directory for your mod and initialise a package.json. The example uses Yarn, but npm or pnpm work equally well.
3
mkdir my-classicuo-mod
cd my-classicuo-mod
yarn init -y
4
Install dependencies
5
Install @classicuo/modding along with React, React DOM, styled-components, and Parcel as your bundler. TypeScript type packages are added as dev dependencies.
6
yarn add @classicuo/modding react@^17 react-dom@^17 styled-components@^5
yarn add --dev parcel typescript @types/react@^17 @types/react-dom@^17 @types/styled-components@^5
7
The @classicuo/modding package ships both ESM and CJS builds and includes TypeScript declarations. No extra @types package is required for it.
8
Configure package.json
9
Set the source field so Parcel knows your entry point, and add build scripts. This mirrors the modding-example setup exactly.
10
{
  "name": "my-classicuo-mod",
  "private": true,
  "source": "src/index.html",
  "scripts": {
    "dev": "parcel src/index.html --open",
    "build": "NODE_ENV=production parcel build src/index.html"
  },
  "dependencies": {
    "@classicuo/modding": "^0.0.34",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "styled-components": "^5.3.5"
  },
  "devDependencies": {
    "parcel": "latest",
    "@types/react": "^17.0.17",
    "@types/react-dom": "^17.0.17",
    "@types/styled-components": "^5.1.26",
    "typescript": "^4.7.4"
  }
}
11
Create the HTML entry point
12
Parcel uses an HTML file as its entry. Create src/index.html and point it at your mod script.
13
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
  </head>
  <body>
    <script type="module" src="./mod.tsx"></script>
  </body>
</html>
14
Write your mod entry point
15
Create src/mod.tsx. Every mod must call mountInterfaceRoot exactly once with a React function component. The SDK mounts your component tree over the game canvas.
16
import React from 'react';
import { mountInterfaceRoot, addEventListener, removeEventListener } from '@classicuo/modding';

const App = () => {
  const [lastMessage, setLastMessage] = React.useState<string>('');

  React.useEffect(() => {
    const id = addEventListener('journalEntry', (ev) => {
      setLastMessage(`[${ev.name}]: ${ev.text}`);
    });
    return () => removeEventListener(id);
  }, []);

  if (!lastMessage) return null;

  return (
    <div
      style={{
        position: 'fixed',
        bottom: 80,
        left: 16,
        background: 'rgba(0,0,0,0.7)',
        color: '#fff',
        padding: '6px 12px',
        borderRadius: 4,
        fontFamily: 'monospace',
        fontSize: 13,
        pointerEvents: 'none'
      }}
    >
      {lastMessage}
    </div>
  );
};

mountInterfaceRoot(App);
17
This is functionally equivalent to the entry point in the modding-example package (packages/modding-example/src/mod.tsx), which calls mountInterfaceRoot after importing custom components.
18
Add a tsconfig.json
19
{
  "compilerOptions": {
    "target": "ES2017",
    "module": "ESNext",
    "moduleResolution": "node",
    "jsx": "react",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true
  },
  "include": ["src"]
}
20
Build and host your mod
21
Build the production bundle. Parcel outputs hashed assets into dist/.
22
yarn build
23
Host the output directory on any static file server that serves content over HTTPS. The ClassicUO Web client will not load mods served over plain HTTP.
24
# Example: serve locally with a tunnel for testing
npx localtunnel --port 1234
25
Register the mod URL in your shard
26
Log into the ClassicUO Shard Management dashboard, open your shard’s settings, and add the HTTPS URL of your bundled index.js to the Mods list. The URL must point directly to the JavaScript bundle (e.g. https://your-cdn.com/mod.js), not to an HTML page.
27
Once saved, players who connect to your shard will automatically receive and execute the mod bundle at login.
28
You can register multiple mods per shard. Each URL in the mods array is loaded in order. Make sure each bundle calls mountInterfaceRoot independently — multiple mods mount separate React roots without interfering with each other.

What’s Next

API Reference

Explore the full set of events, client actions, and player properties available to your mod.

WebGumps

Learn how to build server-driven UIs with the useWebGump hook.

Build docs developers (and LLMs) love