### Install Dependencies
Source: https://foundryvtt.wiki/en/development/guides/gitlab-pipeline
Prepares the environment by installing zip and git utilities.
```yaml
before_script: |
apk add --no-cache zip git
```
--------------------------------
### Initialize World Settings and Setup Hook
Source: https://foundryvtt.wiki/en/development/api/hooks
Registers a world setting and uses the ready hook to trigger a one-time setup function for the game world.
```javascript
Hooks.once("init", () => {
game.settings.register('mySystem', 'setupWorld', {
name: 'Setup World',
scope: 'world',
config: false,
type: Boolean,
default: false
})
});
Hooks.once("ready", () => {
const isWorldSetup = game.settings.get("mySystem", "setupWorld");
if (!isWorldSetup && game.users.activeGM?.isSelf) setupWorld()
})
async setupWorld() {
const warning = ui.notifications.warn("Setting up world, please do not exit the program")
// do stuff
await game.settings.set("mySystem", "setupWorld", true)
ui.notifications.remove(warning)
}
```
--------------------------------
### Start Tour on First Login
Source: https://foundryvtt.wiki/en/development/guides/tours
Uses the 'ready' hook to check if a tour has been started. If the tour status is 'unstarted', it initiates the tour. This is useful for onboarding new users. Consider checking if the user is the GM for specific tours.
```javascript
Hooks.once("ready", async function () {
if(game.tours.get("myModuleName.tourName").status == "unstarted")
{
game.tours.get("myModuleName.tourName").start();
}
});
```
--------------------------------
### Install Boilerplate Dependencies
Source: https://foundryvtt.wiki/en/development/guides/SD-tutorial/SD01-Getting-started
After cloning the Boilerplate repository, navigate into the directory and run this command to install the necessary Node.js dependencies for the generator. Ensure Node.js version 20 or higher is installed.
```bash
npm install
```
--------------------------------
### Start Vite Development Server
Source: https://foundryvtt.wiki/en/development/guides/vite
Command to initiate the Vite development server.
```bash
$ npx vite serve
vite v2.5.0 dev server running at:
> Local: http://localhost:30001/systems/lancer/
> Network: use `--host` to expose
ready in 205ms.
```
--------------------------------
### Example Asset Placement
Source: https://foundryvtt.wiki/en/development/api
Illustrates the recommended directory structure for placing page assets, such as images, relative to the documentation page.
```bash
/development/api
└── document
└── document-console.png
```
--------------------------------
### ApplicationV2 Manual Drag/Drop Setup
Source: https://foundryvtt.wiki/en/development/guides/applicationV2-conversion-guide
Manual implementation of drag and drop handlers for base ApplicationV2 classes.
```javascript
const { DragDrop } = foundry.applications.ux
class MyAppV2 extends HandlebarsApplicationMixin(ApplicationV2) {
#dragDrop
static DEFAULT_OPTIONS = {
dragDrop: [{
dragSelector: '[data-drag="true"]',
dropSelector: '.drop-zone'
}]
}
constructor(options = {}) {
super(options)
this.#dragDrop = this.#createDragDropHandlers()
}
#createDragDropHandlers() {
return this.options.dragDrop.map((d) => {
d.permissions = {
dragstart: this._canDragStart.bind(this),
drop: this._canDragDrop.bind(this)
}
d.callbacks = {
dragstart: this._onDragStart.bind(this),
dragover: this._onDragOver.bind(this),
drop: this._onDrop.bind(this)
}
return new DragDrop(d)
})
}
_onRender(context, options) {
this.#dragDrop.forEach((d) => d.bind(this.element))
}
_canDragStart(selector) {
return this.document.isOwner && this.isEditable
}
_canDragDrop(selector) {
return this.document.isOwner && this.isEditable
}
_onDragOver(event) {
// Optional: handle dragover events if needed
}
}
```
--------------------------------
### Configure Foundry Install Path
Source: https://foundryvtt.wiki/en/development/guides/improving-intellisense
Specify the installation directory of Foundry VTT in a configuration file. This path is device-specific and should not be committed.
```yaml
installPath: "C:\\Program Files\\Foundry Virtual Tabletop\\Version 13"
```
--------------------------------
### Full template.json Boilerplate Example
Source: https://foundryvtt.wiki/en/development/guides/SD-tutorial/SD04-templatejson
A comprehensive example of a template.json file defining actor and item types, shared base templates, and specific attributes.
```json
{
"Actor": {
"types": ["character", "npc"],
"templates": {
"base": {
"health": {
"value": 10,
"min": 0,
"max": 10
},
"power": {
"value": 5,
"min": 0,
"max": 5
},
"biography": ""
}
},
"character": {
"templates": ["base"],
"attributes": {
"level": {
"value": 1
}
},
"abilities": {
"str": {
"value": 10
},
"dex": {
"value": 10
},
"con": {
"value": 10
},
"int": {
"value": 10
},
"wis": {
"value": 10
},
"cha": {
"value": 10
}
}
},
"npc": {
"templates": ["base"],
"cr": 0
}
},
"Item": {
"types": ["item", "feature", "spell"],
"templates": {
"base": {
"description": ""
}
},
"item": {
"templates": ["base"],
"quantity": 1,
"weight": 0,
"formula": "d20 + @str.mod + ceil(@lvl / 2)"
},
"feature": {
"templates": ["base"]
},
"spell": {
"templates": ["base"],
"spellLevel": 1
}
}
}
```
--------------------------------
### Legacy FormApplication Example
Source: https://foundryvtt.wiki/en/development/guides/converting-to-appv2
A standard implementation of a FormApplication before migration to ApplicationV2.
```javascript
class TemplateApplication extends FormApplication {
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
id: "foo-form",
title: `My Module: ${game.i18n.localize("FOO.form.title")}`,
template: "./modules/foo/templates/form.hbs",
classes: ["form"],
width: 640,
height: "auto",
closeOnSubmit: true,
});
}
getData() {
const setting = game.settings.get("foo", "config");
return {
setting
}
}
async activateListeners(html) {
super.activateListeners(html);
html.find("input[name=something]").on("click", /* ... */);
html.find("button[name=reset]").on("click", async (event) => {
await game.settings.set("foo", "config", {});
});
}
async _updateObject(event, formData) {
await Promise.all(
Object.entries(formData)
.map(([key, value]) => game.settings.set("foo", key, value));
);
}
}
```
--------------------------------
### Configure system.json manifest and download URLs
Source: https://foundryvtt.wiki/en/development/guides/SD-tutorial/SD03-systemjson
Example configuration for manifest and download properties using Gitlab URLs for a specific release version.
```json
"manifest": "https://gitlab.com/asacolips-projects/foundry-mods/boilerplate/-/raw/main/system.json",
"download": "https://gitlab.com/asacolips-projects/foundry-mods/boilerplate/-/archive/1.0.0/boilerplate-1.0.0.zip",
```
--------------------------------
### Register and Configure Custom Tours
Source: https://foundryvtt.wiki/en/development/guides/tours
Hooks into the setup process to register tours from JSON files and defines a custom Tour class for pre-step logic.
```javascript
Hooks.once("setup", async function () {
registerMyTours();
}
// necessary to toggle tab from settings to chat before you are able to target #chat
Hooks.on("closeToursManagement", function (event) {
ui.sidebar.activateTab("chat");
});
class MyTour extends Tour {
async _preStep() {
await super._preStep();
const currentStep = this.currentStep;
if(currentStep.id == "chat") {
ChatMessage.create({
content: "
Demo MyTour
",
speaker: ChatMessage.getSpeaker({alias: "MyTour", color: "#ff0000"})
});
} else {
console.log("MyTours | Tours _preStep: ",currentStep.id);
}
}
}
async function registerMyTours() {
try {
game.tours.register(moduleName, 'format', await MyTour.fromJSON('/modules/'+moduleName+'/tours/chat.json'));
if(game.user.isGM) {
game.tours.register(moduleName, 'settings', await MyTour.fromJSON('/modules/'+moduleName+'/tours/settings.json'));
}
} catch (error) {
console.error("MyTour | Error registering tours: ",error);
}
}
```
--------------------------------
### Hooks.callAll() Examples
Source: https://foundryvtt.wiki/en/development/guides/Hooks_Listening_Calling
Examples of using Hooks.callAll() to trigger various events within the Foundry VTT system. These hooks are used to notify different parts of the system about changes or events.
```APIDOC
## Hooks.callAll()
### Description
Triggers all registered callbacks for a given hook event.
### Method
`Hooks.callAll(hookName, ...args)`
### Endpoint
N/A (Client-side JavaScript API)
### Parameters
- **hookName** (string) - The name of the hook event to call.
- **...args** (any) - Arguments passed to the registered callbacks.
### Request Example
```javascript
Hooks.callAll("updateWorldTime", worldTime, dt)
Hooks.callAll("init")
Hooks.callAll('setup')
Hooks.callAll("ready")
Hooks.callAll("pauseGame", this.data.paused)
Hooks.callAll(`create${type}`, doc, options, userId)
Hooks.callAll(`update${doc.documentName}`, doc, change, options, userId)
Hooks.callAll(`delete${doc.documentName}`, doc, options, userId)
Hooks.callAll("updateCompendium", this, documents, options, userId)
Hooks.callAll(`preCreate${embeddedName}`, doc, d, options, user.id)
Hooks.callAll(`preUpdate${embeddedName}`, doc, d, options, user.id)
Hooks.callAll(`preDelete${embeddedName}`, doc, options, user.id)
Hooks.callAll("preUpdateActor", this.actor, data, options, user.id)
Hooks.callAll(`create${embeddedName}`, doc, options, userId)
Hooks.callAll(`update${embeddedName}`, doc, d, options, userId)
Hooks.callAll(`delete${embeddedName}`, doc, options, userId)
Hooks.callAll("updateActor", this.actor, data, options, userId)
Hooks.callAll('canvasInit', this)
Hooks.callAll("canvasPan", this, constrained)
Hooks.callAll("canvasPan", this, {x: stage.pivot.x, y: stage.pivot.y, scale: stage.scale.x})
Hooks.callAll("control"+this.constructor.embeddedName, this, this._controlled)
Hooks.callAll("hover"+this.constructor.embeddedName, this, this._hover)
Hooks.callAll("collapseSidebar", this, this._collapsed)
Hooks.callAll("changeSidebarTab", app)
Hooks.callAll(`getSceneControlButtons`, controls)
Hooks.callAll("collapseSceneNavigation", this, this._collapsed)
Hooks.callAll("initializePointSourceShaders", this, this.animation.type)
Hooks.callAll("targetToken", this.user, token, targeted)
Hooks.callAll("lightingRefresh", this)
Hooks.callAll("sightRefresh", this)
Hooks.callAll("rtcSettingsChanged", this, changed)
Hooks.callAll(`${key}Changed`, volume)
```
### Response
N/A (This is an API call, not an endpoint response)
### Response Example
N/A
```
--------------------------------
### GitHub Actions Build Step
Source: https://foundryvtt.wiki/en/development/api/CompendiumCollection
Example workflow step to ensure compendiums are built during CI/CD processes.
```yaml
- name: Install Dependencies
run: npm ci
- name: Build Packs
run: |
npm run pullYMLtoLDB --if-present
```
--------------------------------
### Override prepareBaseData()
Source: https://foundryvtt.wiki/en/development/guides/SD-tutorial/SD06-Extending-the-Actor-class
Example of an empty override for the base data preparation step.
```javascript
/** @override */
prepareBaseData() {
// Data modifications in this step occur before processing embedded
// documents or derived data.
}
```
--------------------------------
### Start Tour with Timeout
Source: https://foundryvtt.wiki/en/development/guides/tours
When opening a window like client-settings, it is recommended to call tour.start() within a timeout function to ensure proper rendering and execution.
```javascript
setTimeout(function(){
game.tours.get("myModuleName.tourName").start();
}, 1000);
```
--------------------------------
### Legend for Foundry VTT Settings
Source: https://foundryvtt.wiki/en/development/api/settings
Notation guide for understanding static methods, instance methods, and the game object structure.
```text
Setting.defineSchema // `.` indicates static method or property
ClientSettings#register // `#` indicates instance method or property
game.settings.register // The ClientSettings class is instantiated as part of the `game` object
```
--------------------------------
### Example Module File Structure
Source: https://foundryvtt.wiki/en/development/guides/gitlab-pipeline
This is a recommended file structure for your Foundry VTT module repository to facilitate pipeline packaging. Ensure module.json and .gitlab-ci.yml are in the root directory.
```text
my-module --| module.json
| /.git
| /src---|
| /packs
| /scripts
| /styles
| /templates
```
--------------------------------
### Handle i18n Initialization Hook
Source: https://foundryvtt.wiki/en/development/api/localization
Example of using the `i18nInit` hook to localize configuration data after settings are loaded and localizations are available.
```javascript
Hooks.once("i18nInit", () => {
// Localize CONFIG additions here
});
```
--------------------------------
### Basic _prepareContext Implementation
Source: https://foundryvtt.wiki/en/development/guides/from-load-to-render
A minimal example of overriding `_prepareContext` to include system data and schema fields in the rendering context. Ensure `super` is called to preserve default behavior.
```javascript
async _prepareContext(options) {
const context = await super._prepareContext(options)
return Object.assign(context, {
system: this.document.system,
systemFields: this.document.system.schema.fields,
})
}
```
--------------------------------
### Registering Hook Callbacks
Source: https://foundryvtt.wiki/en/development/guides/Hooks_Listening_Calling
Examples of using Hooks.on to register callbacks for specific events.
```javascript
Hooks.on("init", async function () {
//obviously triggered by a Hooks.callAll() that's gonna call every module/system that registered 'init', no matter what
});
```
```javascript
Hooks.on("renderCompendium", (compendiumApp, html, appData) => {
//TODO: add real world, working example
});
```
--------------------------------
### Register a Custom Client Setting
Source: https://foundryvtt.wiki/en/development/guides/handling-data
Shows how to register a new setting for a module using `game.settings.register`. This example registers a number setting with a range, configuration option, and an onChange callback.
```javascript
/*
* Create a custom config setting
*/
await game.settings.register('myModuleId', 'mySettingName', {
name: 'My Setting', // can also be an i18n key
hint: 'A description of the registered setting and its behavior.', // can also be an i18n key
scope: 'world', // "world" = sync to db, "client" = local storage
config: true, // false if you dont want it to show in module config
type: Number, // Number, Boolean, String, or even a custom class or DataModel
default: 0,
range: {. // range turns the UI input into a slider input
min: 0,
max: 100,
step: 10
},
onChange: value => { // value is the new value of the setting
console.log(value)
},
filePicker: false, // set true with a String `type` to use a file picker input,
requiresReload: false, // when changing the setting, prompt the user to reload
});
```
--------------------------------
### Define Package-Specific Translations
Source: https://foundryvtt.wiki/en/development/api/localization
Example of a language.json file structure for a package, demonstrating nested namespaces and overriding system translations.
```json
{
"MYMODULE": {
"Foo": "Bar"
},
"DND5E.Item.Property.Magical": "Supernatural"
}
```
--------------------------------
### Example module.json Manifest URL
Source: https://foundryvtt.wiki/en/development/guides/releases-and-history
This field in module.json should point to the latest release's manifest JSON, ensuring Foundry clients always fetch the most recent manifest.
```json
"manifest": "https://github.com/ElfFriend-DnD/AmazingModule/releases/latest/download/module.json"
```
--------------------------------
### Legend for API Documentation
Source: https://foundryvtt.wiki/en/development/api/time
Notation guide for distinguishing between static and instance members in the API documentation.
```text
CalendarData.formatTimestamp // `.` indicates static method or property
CalendarData#timeToComponents // `#` indicates instance method or property
```
--------------------------------
### Triggering Hooks
Source: https://foundryvtt.wiki/en/development/guides/Hooks_Listening_Calling
Examples of using Hooks.call and Hooks.callAll to trigger events within the Foundry VTT system.
```javascript
Hooks.callAll("ready");
// called when the game is done initializing its data structure and is 'ready'
```
```javascript
Hooks.call("dropCanvasData", this, data);
// when anything is dragDropped onto the canvas
// ('this' being the canvas instance)
```
```javascript
Hooks.callAll(`update${doc.documentName}`, doc, change, options, userId);
// that will trigger for any document type,
// giving us a wide range of hookNames to deal with like
// 'updateActor', 'updateMacro', 'updateChatMessage'...
```
--------------------------------
### Localization JSON for Data Model Fields
Source: https://foundryvtt.wiki/en/development/api/localization
Provides an example of a JSON localization file that pairs with a DataModel using LOCALIZATION_PREFIXES. It shows how to define 'hint' and 'label' for fields like 'someMessage'.
```json
{
"NESTED": {
"Path": {
"FIELDS": {
"someMessage": {
"hint": "Behavior hint",
"label": "Behavior label"
}
}
}
}
}
```
--------------------------------
### Basic String Translation Example
Source: https://foundryvtt.wiki/en/development/guides/localization/localization-best-practices
Demonstrates a simple string translation where a phrase is split into multiple keys. This approach can cause issues in languages with different grammatical structures.
```json
"modulename.phrase": "This is an",
"modulename.noun": "apple"
```
--------------------------------
### Example 'includes' field in Manifest+
Source: https://foundryvtt.wiki/en/development/manifest-plus
The 'includes' field is an array of strings specifying relative file paths to be included in the package zip archive. This is useful for deployment tools.
```json
"includes": [
"relative/path/to/files/script.js",
"relative/to/templates/template.html",
"path/to/image/assets/folder"
]
```
--------------------------------
### Parameterized String Translation Example
Source: https://foundryvtt.wiki/en/development/guides/localization/localization-best-practices
Shows how to use placeholders for dynamic content in translations. This method allows translators to reorder words and adapt to different grammatical structures.
```json
"modulename.phrase": "This is an {noun}",
"modulename.noun": "apple"
```
--------------------------------
### Initialize System with 'init' Hook
Source: https://foundryvtt.wiki/en/development/guides/SD-tutorial/SD05-Creating-your-main-JS-file
Use the 'init' hook to perform essential system setup, including adding utility classes to the global game object, defining custom configuration constants, setting initiative formulas, defining custom document classes, and registering custom sheet applications.
```javascript
/* -------------------------------------------- */
/* Init Hook */
/* -------------------------------------------- */
Hooks.once('init', function () {
// Add utility classes to the global game object so that they're more easily
// accessible in global contexts.
game.boilerplate = {
BoilerplateActor,
BoilerplateItem,
rollItemMacro,
};
// Add custom constants for configuration.
CONFIG.BOILERPLATE = BOILERPLATE;
/**
* Set an initiative formula for the system
* @type {String}
*/
CONFIG.Combat.initiative = {
formula: '1d20 + @abilities.dex.mod',
decimals: 2,
};
// Define custom Document classes
CONFIG.Actor.documentClass = BoilerplateActor;
CONFIG.Item.documentClass = BoilerplateItem;
// Active Effects are never copied to the Actor,
// but will still apply to the Actor from within the Item
// if the transfer property on the Active Effect is true.
CONFIG.ActiveEffect.legacyTransferral = false;
// Register sheet application classes
Actors.unregisterSheet('core', ActorSheet);
Actors.registerSheet('boilerplate', BoilerplateItemSheet, {
makeDefault: true,
label: 'BOILERPLATE.SheetLabels.Actor',
});
Items.unregisterSheet('core', ItemSheet);
Items.registerSheet('boilerplate', BoilerplateItemSheet, {
makeDefault: true,
label: 'BOILERPLATE.SheetLabels.Item',
});
// Preload Handlebars templates.
return preloadHandlebarsTemplates();
});
```
--------------------------------
### Example TinyMCE translation file content
Source: https://foundryvtt.wiki/en/development/guides/localization/localizing-tinymce
An example of how to append custom keys to the TinyMCE translation object.
```javascript
tinymce.addI18n('fi',{
...omitted data...
"Caption": "Seloste",
"Insert template": "Lis\u00e4\u00e4 pohja",
"Custom": "Mukautettu",
"Secret": "Salainen"
});
```
--------------------------------
### Display Forge Installs Badge
Source: https://foundryvtt.wiki/en/development/guides/repository-bling
Shows the percentage of users who have installed a module via The Forge. Replace [YOUR_PACKAGE_NAME] with the name field from your manifest.
```markdown
[](https://forge-vtt.com/bazaar#package=[YOUR_PACKAGE_NAME])
```
--------------------------------
### Bundle and Package Module
Source: https://foundryvtt.wiki/en/development/guides/gitlab-pipeline
Copies the configuration file to the source directory and creates a zip archive for the release.
```bash
# copy module.json to src
echo "[Info] Bundling module... this may take some time"
cp -v "${CI_PROJECT_DIR}/module.json" "${MODULE_DIRECTORY}/module.json"
# Package module
cd "${MODULE_DIRECTORY}"
zip -qr "${RELEASE_FILE}" .
cd ${CI_PROJECT_DIR}
```
--------------------------------
### Handlebars Helper Example
Source: https://foundryvtt.wiki/en/development/guides/SD-tutorial/SD02-Stuff-to-be-aware-of
An example of a Handlebars helper function in Javascript that concatenates strings. This can be used within your Handlebars templates to combine text dynamically.
```javascript
Handlebars.registerHelper('concat', function() {
return Array.prototype.slice.call(arguments, 0, -1).join(' ');
});
```
--------------------------------
### Hooks.call() with Interruption Examples
Source: https://foundryvtt.wiki/en/development/guides/Hooks_Listening_Calling
Specific examples demonstrating Hooks.call() usage where callbacks might interrupt the flow or modify data before it's passed further. This is common for pre-event hooks.
```APIDOC
## Hooks.call() with Interruption
### Description
Examples of using `Hooks.call()` for pre-event hooks that can modify data or interrupt the default behavior.
### Method
`Hooks.call(hookName, ...args)`
### Endpoint
N/A (Client-side JavaScript API)
### Parameters
- **hookName** (string) - The name of the hook event to call.
- **...args** (any) - Arguments passed to the registered callbacks.
### Request Example
```javascript
Hooks.call(`preCreate${type}`, doc, createData, options, user.id)
Hooks.call(`preUpdate${doc.documentName}`, doc, update, options, user.id)
Hooks.call(`preDelete${doc.documentName}`, doc, options, user.id)
Hooks.call("modifyTokenAttribute", {attribute, value, isDelta, isBar}, updates)
Hooks.call("dropCanvasData", this, data)
Hooks.call("dropActorSheetData", actor, this, data)
Hooks.call("dropRollTableSheetData", this.document, this, data)
Hooks.call("chatBubble", token, html, message, {emote})
Hooks.call("hotbarDrop", this, data, slot)
Hooks.call("chatMessage", this, message, chatData)
Hooks.call(`get${cls.name}EntryContext`, html, entryOptions)
Hooks.call(`get${cls.name}EntryContext`, html, entryOptions)
Hooks.call(`get${cls.name}SoundContext`, html, entryOptions)
```
### Response
- **result** (any) - The return value of the last executed callback, or `false` if the hook was interrupted.
### Response Example
N/A
```
--------------------------------
### Hooks.call() Examples
Source: https://foundryvtt.wiki/en/development/guides/Hooks_Listening_Calling
Examples of using Hooks.call() to trigger events that may be interrupted or have specific return values. This is often used for actions that can be modified or cancelled by registered callbacks.
```APIDOC
## Hooks.call()
### Description
Calls a hook event and returns the result of the last callback. If any callback returns `false`, the hook call is interrupted.
### Method
`Hooks.call(hookName, ...args)`
### Endpoint
N/A (Client-side JavaScript API)
### Parameters
- **hookName** (string) - The name of the hook event to call.
- **...args** (any) - Arguments passed to the registered callbacks.
### Request Example
```javascript
Hooks.call(`render${cls.name}`, this, html, data)
Hooks.call(`get${cls.name}HeaderButtons`, this, buttons)
Hooks.call(`close${cls.name}`, this, el)
Hooks.call("applyActiveEffect", actor, change)
Hooks.call("renderChatMessage", this, html, messageData)
Hooks.call("canvasReady", this)
Hooks.call(`paste${cls.name}`, this._copy, toCreate)
Hooks.call(`get${cls.name}FolderContext`, html, folderOptions)
Hooks.call(`get${cls.name}EntryContext`, html, entryOptions)
Hooks.call("getSceneNavigationContext", html, contextOptions)
Hooks.call(`getUserContextOptions`, html, contextOptions)
Hooks.call(`get${cls.name}EntryContext`, html, entryOptions)
Hooks.call(`paste${cls.name}`, this._copy, toCreate)
```
### Response
- **result** (any) - The return value of the last executed callback, or `false` if the hook was interrupted.
### Response Example
N/A
```
--------------------------------
### Custom Enrichment Function Example
Source: https://foundryvtt.wiki/en/development/guides/enrichers
This example demonstrates how to create a temporary custom enrichment function. It adds a custom enricher, calls TextEditor.enrichHTML, and then removes the custom enricher to avoid global side effects.
```typescript
export const myEnrichHTML = async(text: string): Promise => {
const enricherConfig = {
pattern: myRegex,
enricher: myEnricherFn,
replaceParent: false, // or true, as you need
};
// add your enricher
CONFIG.TextEditor.enrichers.push(enricherConfig);
// call enrichHTML
const enrichedText = await TextEditor.enrichHTML(text || '', {
// any options you want to pass in for your enricher or to disable defaults
});
// remove your enricher
CONFIG.TextEditor.enrichers = CONFIG.TextEditor.enrichers
.filter((f): boolean => (f!=enricherConfig));
return enrichedText;
}
```
--------------------------------
### ApplicationV2 Lifecycle and Rendering
Source: https://foundryvtt.wiki/en/development/api/applicationv2
Demonstrates how to instantiate, render, and close an ApplicationV2 instance. It also shows how to refresh an existing application.
```APIDOC
## ApplicationV2 Lifecycle
### Description
This section covers the basic lifecycle of an ApplicationV2 instance, including instantiation, rendering, and closing.
### Methods
- **new MyApp().render(true)**: Instantiates a new application and renders it to the screen.
- **myApp.render()** or **this.render()**: Refreshes an already rendered application.
- **myApp.close()**: Removes the application from the UI. The instance persists until garbage collected.
### Example
```javascript
// Instantiate and render a new application
const myApp = new MyApp();
myApp.render(true);
// Refresh the application
myApp.render();
// Close the application
myApp.close();
```
```
--------------------------------
### Complex Localization Example for Legendary Actions
Source: https://foundryvtt.wiki/en/development/api/localization
An example of a complex localization string for 'legendary actions' that uses placeholders for dynamic content like '{name}'. This demonstrates the importance of nested localization keys for clarity and reusability.
```json
{
"MOBLOKS5E.LegendaryText": "The {name} can take 3 legendary actions, choosing from the options below. Only one legendary action option can be used at a time and only at the end of another creature's turn. The {name} regains spent legendary actions at the start of its turn."
}
```
--------------------------------
### Open a FormApplication instance
Source: https://foundryvtt.wiki/en/development/guides/understanding-form-applications
Instantiate and render the custom application to the screen.
```javascript
/**
* To open your application
*/
new MyFormApplication('example').render(true);
```
--------------------------------
### Example Map Note Icon Translation JSON
Source: https://foundryvtt.wiki/en/development/guides/localization/localizing-map-note-icons
This is an example of the translated JSON file for map note icons. Replace the English keys with your localized strings. Ensure the file is named according to your language tag (e.g., fi-FI_icons.json).
```json
{
"Anchor": "Ankkuri",
"Barrel": "Tynnyri",
}
```
--------------------------------
### Get a Setting Value
Source: https://foundryvtt.wiki/en/development/guides/handling-data
Retrieves the current value of a registered setting.
```javascript
const someVariable = game.settings.get('myModuleId','myModuleSetting');
console.log(someVariable); // expected to be 'foo'
```
--------------------------------
### Initialize FormApplication with Partials
Source: https://foundryvtt.wiki/en/development/guides/Tabs-and-Templates/Tabs-FormApplication
Extended initialization logic that includes loading required Handlebars partials.
```javascript
class myFormApplication extends FormApplication {
constructor(object, options) {
super(object, options);
}
static get defaultOptions() {
return super.defaultOptions;
}
getData(options = {}) {
return super.getData().object; // the object from the constructor is where we are storing the data
}
activateListeners(html) {
super.activateListeners(html);
}
async _updateObject(event, formData) {
return;
}
}
const template_file = "macro_data/TEMPLATE_FILE";
loadTemplates(["macro_data/tab_partial.html"]);
const template_data = { header: "Handlebars header text.",
tabs: [{ label: "tab1",
title: "My First Tab",
content: "Fancy tab1 content."},
{ label: "tab2",
title: "My Second Tab",
content: "Fancy tab2 content."}],
footer: "Handlebars footer text."};
const my_form = new myFormApplication(template_data, { template: template_file,
tabs: [{navSelector: ".tabs", contentSelector: ".content", initial: "tab1"}] }); // data, options
const res = await my_form.render(true);
```
--------------------------------
### Complete module.json with Manifest and Download URLs
Source: https://foundryvtt.wiki/en/development/guides/local-to-repo
This shows the module.json file after adding the manifest and download URLs. Remember to include commas at the end of each added line.
```json
{
"id": "my-module",
"title": "My Module",
"version": "1.0.0",
"manifest": "https://github.com/my-user/my-module/releases/latest/download/module.json",
"download": "https://github.com/my-user/my-module/releases/download/1.0.0/module.zip",
"compatibility": {
"minimum": "12",
"verified": "12"
}
}
```
--------------------------------
### DialogV2 Static Methods (prompt)
Source: https://foundryvtt.wiki/en/development/api/dialogv2
Demonstrates the usage of the `DialogV2.prompt` static method for displaying a dialog with custom content and options.
```APIDOC
## DialogV2.prompt()
This static method displays a prompt dialog. It is asynchronous and returns a Promise.
### Parameters:
- `options` (object): Configuration options for the dialog.
- `window` (object): Window title.
- `title` (string): The title to display in the dialog's window.
- `content` (string): The HTML content to display within the dialog.
- `modal` (boolean): Whether the dialog should be modal.
- `actions` (object, optional): Callbacks for actions defined in the content.
- `render` (function, optional): Callback function triggered when the dialog finishes rendering.
### Request Example:
```javascript
const response = await foundry.applications.api.DialogV2.prompt({
window: { title: "User Input" },
content: "
Please enter your name:
",
modal: true,
actions: {
submit: (event, target) => {
// Handle submission
}
},
render: (app) => {
console.log("Dialog rendered:", app);
}
});
```
### Response:
Returns a Promise that resolves with the dialog's response. The structure of the response depends on the dialog's implementation and user interaction.
```
--------------------------------
### Socket Interface Legend
Source: https://foundryvtt.wiki/en/development/api/sockets
Notation guide for interpreting Foundry VTT API documentation.
```text
SocketInterface.dispatch // `.` indicates static method or property
Socket#on // `#` indicates instance method or property
```
--------------------------------
### Game Class Initialization Flow
Source: https://foundryvtt.wiki/en/development/api/game
Illustrates the sequence of calls for creating and initializing the Game instance. This process includes establishing server connections, fetching data, and constructing the singleton `game` object.
```javascript
1. `Game.create` is called after all code is imported
a. `Game.connect` establishes the underlying socket connection with the server
b. `Game.getData` fetches the live data from the database.
c. `new Game` constructs the singleton instance which is publicly stashed as `game`
2. `Game.initialize` is called, which progressively builds out the `game` instance and calls a series of hooks.
```
--------------------------------
### Override prepareData()
Source: https://foundryvtt.wiki/en/development/guides/SD-tutorial/SD06-Extending-the-Actor-class
Example of calling the super method to maintain the default data preparation lifecycle.
```javascript
/** @override */
prepareData() {
// Prepare data for the actor. Calling the super version of this executes
// the following, in order: data reset (to clear active effects),
// prepareBaseData(), prepareEmbeddedDocuments() (including active effects),
// prepareDerivedData().
super.prepareData();
}
```
--------------------------------
### Define System Configuration Constants
Source: https://foundryvtt.wiki/en/development/guides/SD-tutorial/SD13-Localization
Create a configuration file to map ability keys to their corresponding localization string identifiers.
```javascript
export const MYSYSTEM = {}
MYSYSTEM.abilities = {
"str": "MYSYSTEM.AbilityStr",
"dex": "MYSYSTEM.AbilityDex",
"con": "MYSYSTEM.AbilityCon",
"int": "MYSYSTEM.AbilityInt",
"wis": "MYSYSTEM.AbilityWis",
"cha": "MYSYSTEM.AbilityCha"
}
```
--------------------------------
### GET CompendiumCollection#getDocuments
Source: https://foundryvtt.wiki/en/development/api/CompendiumCollection
Retrieves an array of documents from a compendium, optionally filtered by query parameters.
```APIDOC
## GET CompendiumCollection#getDocuments
### Description
Retrieves documents from the compendium. If no query is provided, returns all documents.
### Parameters
#### Query Parameters
- **query** (object) - Optional - Filter criteria. Examples include { type: "weapon" }, { _id__in: arrayOfIds }, or { type__in: ["weapon", "armor"] }.
### Response
#### Success Response (200)
- **documents** (Array) - An array of documents matching the query.
```
--------------------------------
### Define Compendium Legend
Source: https://foundryvtt.wiki/en/development/api/CompendiumCollection
Notation guide for static and instance methods within the CompendiumCollection class.
```javascript
CompendiumCollection.createCompendium // `.` indicates static method or property
CompendiumCollection#getDocument // `#` indicates instance method or property
```
--------------------------------
### Development Entrypoint Files
Source: https://foundryvtt.wiki/en/development/guides/vite
Placeholder files required for FoundryVTT to load the development environment.
```javascript
// only required for dev
// in prod, foundry loads lancer.mjs, which is compiled by vite/rollup
// in dev, foundry loads lancer.mjs, this file, which loads lancer.ts
import './src/lancer.ts';
```
```css
/**
* only required in dev
* in prod, foundry loads style.css, as compiled by vite/rollup,
* mostly from the `import lancer.scss` line at the top of lancer.ts
*
* in dev, foundry loads style.css, this file, which is a no-op
* in dev, lancer.ts imports lancer.scss directly
*/
```
--------------------------------
### Interrupting Hook Events
Source: https://foundryvtt.wiki/en/development/guides/Hooks_Listening_Calling
Example of returning false in a hook callback to prevent the default behavior of an event.
```javascript
//if there's a canvas init, register a permanent protection against some 'types'
Hooks.once('canvasInit', (canvas) => {
Hooks.on("dropCanvasData", (canvas, dropData) => {
if ( dropData.type === 'Actor') {
const actor = game.actors.get(dropData.id);
if ( actor.name === 'Xx_DarkSasuke69420_xX' ) { return false; }
}
});
});
```
--------------------------------
### Importing ApplicationV2 and HandlebarsApplicationMixin
Source: https://foundryvtt.wiki/en/development/api/applicationv2
Demonstrates how to import ApplicationV2 and HandlebarsApplicationMixin using object destructuring for cleaner syntax. This is a common pattern when working with ESModules in Foundry VTT.
```javascript
const { ApplicationV2, HandlebarsApplicationMixin } = foundry.applications.api
class MyHandlebarsApp extends HandlebarsApplicationMixin(ApplicationV2) {}
```
--------------------------------
### Add Foundry Paths to .gitignore
Source: https://foundryvtt.wiki/en/development/guides/improving-intellisense
Prevent Foundry VTT installation paths from being committed to your version control system.
```gitignore
foundry-config.yaml
foundry
```
--------------------------------
### Getting a Flag's Value
Source: https://foundryvtt.wiki/en/development/api/flags
Demonstrates how to retrieve a flag's value from a document using the `getFlag` method.
```APIDOC
## GET /documents/{documentId}/flags/{scope}/{flagName}
### Description
Retrieves the value of a specific flag from a document.
### Method
`GET`
### Endpoint
`/documents/{documentId}/flags/{scope}/{flagName}`
### Parameters
#### Path Parameters
- **documentId** (string) - Required - The ID of the document to retrieve the flag from.
- **scope** (string) - Required - The namespace of the flag.
- **flagName** (string) - Required - The name of the flag.
#### Query Parameters
None
#### Request Body
None
### Request Example
None
### Response
#### Success Response (200)
- **value** (any) - The value of the requested flag.
#### Response Example
```json
"foo"
```
```
--------------------------------
### Configure FormApplication dialog dimensions
Source: https://foundryvtt.wiki/en/development/guides/Tabs-and-Templates/Template-Basics
Demonstrates how to pass dynamic options during instantiation to control dialog size and resizability.
```javascript
const my_form = new myFormApplication(template_data, { template: template_file,
width: "400",
height: "auto",
resizable: true });
```
--------------------------------
### Define DataModel Schema Legend
Source: https://foundryvtt.wiki/en/development/api/DataModel
Notation guide for identifying static versus instance members in DataModel documentation.
```text
DataModel.defineSchema // `.` indicates static method or property
DataModel#invalid // `#` indicates instance method or property
```
--------------------------------
### Execute Production Build
Source: https://foundryvtt.wiki/en/development/guides/vite
Runs the Vite build process to generate production-ready files in the dist directory.
```bash
$ npx vite build
vite v2.5.0 building for production...
✓ 963 modules transformed.
rendering chunks (9)...
dist/lancer.es.js 0.04 KiB / brotli: 0.05 KiB
dist/lancer.es.js.map 0.09 KiB
dist/aws-exports.js 0.92 KiB / brotli: 0.42 KiB
dist/aws-exports.js.map 2.32 KiB
dist/index.js 1.69 KiB / brotli: 0.70 KiB
dist/index.js.map 5.04 KiB
dist/marked.js 46.42 KiB / brotli: 12.97 KiB
dist/marked.js.map 137.94 KiB
dist/index4.js 52.08 KiB / brotli: 14.08 KiB
dist/index4.js.map 238.45 KiB
dist/Credentials.js 138.40 KiB / brotli: 29.90 KiB
dist/Credentials.js.map 968.75 KiB
dist/style.css 36.59 KiB / brotli: 7.38 KiB
dist/index2.js 144.89 KiB / brotli: 34.89 KiB
dist/index2.js.map 602.29 KiB
dist/index3.js 179.36 KiB / brotli: 33.85 KiB
dist/index3.js.map 1536.81 KiB
dist/lancer.js 1030.44 KiB / brotli: skipped (large chunk)
dist/lancer.js.map 1777.34 KiB
```
--------------------------------
### Initialize TabbedDialog with default settings
Source: https://foundryvtt.wiki/en/development/guides/Tabs-and-Templates/Extending-Dialog-with-Tabs
Demonstrates creating a dialog with three tabs using default configuration values.
```javascript
let d = new TabbedDialog(
{
title: "Test Tabbed Dialog",
header: "Test header",
footer: "Test footer",
tabs: [ { },
{ },
{ }
],
buttons: {
one: {
icon: '',
label: "Option One",
callback: () => console.log("Chose One")
},
two: {
icon: '',
label: "Option Two",
callback: () => console.log("Chose Two")
}
},
default: "two",
render: html => console.log("Register interactivity in the rendered dialog"),
close: html => console.log("This always is logged no matter which option is chosen")
},
{ resizable: true }
);
d.render(true);
```
--------------------------------
### Example Handlebars tab part
Source: https://foundryvtt.wiki/en/development/guides/Tabs-and-Templates/Tabs-in-AppV2
A sample template for a tabbed section, requiring data-group and data-tab attributes and the tab.cssClass class.
```handlebars
Aptitudes
{{#each this.aptitudes}} {{#if this.show}}
{{this.label}}
{{this.trait}}
{{this.totalRanks}}d{{this.die}}
{{/if}} {{/each}}
```
--------------------------------
### Choosing the Right Base Class for V13 Applications
Source: https://foundryvtt.wiki/en/development/guides/applicationV2-conversion-guide
Illustrates how to extend different v2 application classes based on the intended use case: ActorSheetV2 for actor sheets, DocumentSheetV2 for other document types, ApplicationV2 for custom applications, and DialogV2 for prompts.
```javascript
class MyActorSheet extends HandlebarsApplicationMixin(ActorSheetV2) {
// Gets automatic drag/drop, actor-specific features
}
// For item sheets - use DocumentSheetV2
class MyItemSheet extends HandlebarsApplicationMixin(DocumentSheetV2) {
// Gets document handling, no automatic drag/drop
}
// For configuration dialogs - use ApplicationV2
class MyConfigDialog extends HandlebarsApplicationMixin(ApplicationV2) {
// Gets basic application features only
}
// For user prompts - use DialogV2
class MyPrompt extends DialogV2 {
// Gets modal behavior, button handling
}
```
--------------------------------
### Configure jsconfig.json for IntelliSense
Source: https://foundryvtt.wiki/en/development/guides/improving-intellisense
Set up your `jsconfig.json` file in the project root to include your ESM files. This enables IntelliSense for Foundry VTT modules and client/common paths.
```json
{
"compilerOptions": {
"module": "ES2022",
"target": "ES2022",
"paths": {
"@client/*": ["./foundry/client/*"],
"@common/*": ["./foundry/common/*"]
},
},
"exclude": ["node_modules", "**/node_modules/*"],
"include": ["your-package-root.mjs", "foundry/client/client.mjs", "foundry/client/global.d.mts", "foundry/common/global.d.mts"],
"typeAcquisition": {
"include": ["jquery"]
}
}
```
--------------------------------
### Get Module Setting Value
Source: https://foundryvtt.wiki/en/development/api/settings
Retrieve the value of a module setting. The returned value is constructed using the `type` specified during registration.
```javascript
const someVariable = game.settings.get('myModuleName','myModuleSetting');
console.log(someVariable); // expected to be 'foo'
```
--------------------------------
### Configuration Settings for Tours
Source: https://foundryvtt.wiki/en/development/guides/tours
Defines configuration settings for tours, including selectors for specific UI elements. Use this to mark elements for tour steps.
```json
{
"title": "Configuration Settings",
"description": "Howto mark the Button Configuration Settings for Tours",
"canBeResumed": false,
"display": true,
"steps": [
{
"id": "configSettings",
"selector": "button[data-action=\"configure\"]",
"title": "Config Tour",
"content": "MYTRANSLATION.tours.configSettings",
"sidebarTab" "settings"
},
{
"id": "stepTwo",
// ...
}
]
}
```
```json
{
"title": "..",
"description": "...",
"display": true,
"steps": [
{
"id": "configSettings",
"selector": ".tabs>a[data-tab='actors']",
//...
}
]
}
```
--------------------------------
### Get Square Grid Space Coordinates
Source: https://foundryvtt.wiki/en/development/api/canvas
Retrieves the grid space coordinates for the currently hovered square grid. Requires the mouse position.
```javascript
const p = canvas.mousePosition; // { x, y }
const { x, y } = canvas.grid.getTopLeftPoint({x: p.x, y: p.y });
```
--------------------------------
### Using LOCALIZATION_PREFIXES for Data Models
Source: https://foundryvtt.wiki/en/development/api/localization
Demonstrates how to use the static LOCALIZATION_PREFIXES property in a custom DataModel to automatically generate localization keys for 'hint' and 'label' fields. This simplifies configuration form generation.
```javascript
export default class MyModel extends foundry.abstract.DataModel {
static LOCALIZATION_PREFIXES = ["NESTED.Path"];
static defineSchema() {
return {
someMessage: new fields.StringField()
};
}
}
```