This guide explains how to create and register custom widgets for the Campaign Codex module. This allows other modules to add new functionality and interactive elements that can be embedded within Campaign Codex journal entries.
1. Create the module structure
Create a folder for your module using the same name as the module ID:
foldername/
├── module.json
└── scripts/
├── main.js
└── widgets/
└── WidgetName.js
Add a module.json file:
{
"id": "foldername",
"title": "Module Title",
"description": "Addon widgets for Campaign Codex",
"version": "1.0.0",
"scripts": [],
"esmodules": [
"scripts/main.js"
],
"compatibility": {
"minimum": "13",
"verified": "13"
},
"url": "",
"readme": "",
"authors": [
{
"name": "",
"url": "",
"flags": {}
}
],
"relationships": {
"systems": []
},
"manifest": "",
"download": ""
}
The id must match the module’s folder name.
2. Register the widgets
Create scripts/main.js.
Import each widget factory and register the resulting widget class when Foundry is ready:
import { createWidgetName } from "./widgets/WidgetName.js";
Hooks.once("ready", async () => {
const ccApi = game.modules.get("campaign-codex")?.api;
if (!ccApi) {
console.error(
"Widgets | Campaign Codex API was not found. Is Campaign Codex enabled?"
);
return;
}
const { CampaignCodexWidget, widgetManager } = ccApi;
const WidgetName = createWidgetName(CampaignCodexWidget);
widgetManager.registerWidget("Widget Name", WidgetName);
console.log("Widgets | Registered with Campaign Codex.");
});
For every additional widget, repeat the import, factory call, and registerWidget call:
import { createFirstWidget } from "./widgets/FirstWidget.js";
import { createSecondWidget } from "./widgets/SecondWidget.js";
Hooks.once("ready", async () => {
const ccApi = game.modules.get("campaign-codex")?.api;
if (!ccApi) {
console.error(
"Widgets | Campaign Codex API was not found. Is Campaign Codex enabled?"
);
return;
}
const { CampaignCodexWidget, widgetManager } = ccApi;
const FirstWidget = createFirstWidget(CampaignCodexWidget);
const SecondWidget = createSecondWidget(CampaignCodexWidget);
widgetManager.registerWidget("First Widget", FirstWidget);
widgetManager.registerWidget("Second Widget", SecondWidget);
console.log("Widgets | Registered with Campaign Codex.");
});
3. Create the widget class
Create scripts/widgets/WidgetName.js.
The widget must export a factory function that:
- Receives Campaign Codex’s
CampaignCodexWidgetbase class. - Creates a class that extends
CampaignCodexWidget. - Returns that class.
export function createWidgetName(CampaignCodexWidget) {
return class WidgetName extends CampaignCodexWidget {
// Add the widget implementation here.
};
}
The CampaignCodexWidget base class is supplied by the Campaign Codex API at runtime.