Repository navigation
api toolbar
Audience: Developers integrating with Blacksmith and leveraging the exposed API.
The Blacksmith Toolbar API allows external modules to register custom tools with the Blacksmith toolbar system. This provides a unified interface for adding functionality to both the Blacksmith Utilities toolbar and FoundryVTT's token control toolbar.
// Get the Blacksmith module API
const blacksmith = game.modules.get('coffee-pub-blacksmith')?.api;
// Check if API is available
if (blacksmith?.registerToolbarTool) {
// API is ready to use
} else {
// Wait for API to load
Hooks.once('ready', () => {
// API should be available now
});
}// Register a custom tool (minimal example - many properties have defaults)
const success = blacksmith.registerToolbarTool('my-custom-tool', {
icon: "fa-solid fa-dice-d20", // Optional: defaults to "fa-solid fa-square-question"
name: "my-custom-tool", // Optional: defaults to toolId if not provided
title: "My Custom Tool", // Optional: defaults to name or toolId
button: true, // Optional: defaults to true (v13 requirement)
visible: true, // Optional: defaults to true
zone: "rolls", // Optional: defaults to "general"
order: 5, // Optional: defaults to 999
moduleId: "my-module", // Optional: defaults to "blacksmith-core"
gmOnly: false, // Optional: defaults to false
leaderOnly: false, // Optional: defaults to false
onCoffeePub: true, // Optional: defaults to true (can be boolean or function)
onFoundry: false, // Optional: defaults to false (can be boolean or function)
onClick: () => {
// Your tool logic here
console.log("My custom tool clicked!");
}
});
if (success) {
console.log("Tool registered successfully!");
} else {
console.log("Failed to register tool");
}Note for FoundryVTT v13: The button property defaults to true and is required for toolbar display. The name property defaults to toolId if not provided, which is especially important for external modules to ensure proper tool identification.
Registers a new tool with the Blacksmith toolbar system.
Parameters:
-
toolId(string): Unique identifier for the tool -
toolData(Object): Tool configuration object
Returns: boolean - Success status
Tool Data Properties:
-
icon(string, optional): FontAwesome icon class (e.g., "fa-solid fa-dice-d20"). Defaults to"fa-solid fa-square-question"if not provided. -
name(string, optional): Tool name (used for data-tool attribute). Defaults totoolIdif not provided - this is especially important for external modules to ensure proper tool identification in FoundryVTT v13. -
title(string, optional): Tooltip text displayed on hover. Defaults totoolData.nameortoolIdif not provided. -
onClick(Function, required): Function to execute when tool is clicked -
button(boolean, optional): Whether to show as button. Defaults totrue- FoundryVTT v13 requiresbutton: truefor toolbar display. Must betruefor tools to appear in toolbars. -
toggle(boolean, optional): Automatically set tofalsefor all tools. Not user-configurable. -
visible(boolean|Function, optional): Whether the tool is visible in the Blacksmith (CoffeePub) toolbar. Defaults totrue; can be a function returning a boolean. Note:visibleis honored only on the Blacksmith toolbar — the Foundry native toolbar path (getFoundryToolbarTools) gates ononFoundry,gmOnly, andleaderOnlyonly and does not readvisible. To hide a tool on the Foundry toolbar, drive it withonFoundry(which accepts a function). -
zone(string, optional): Zone for organization (default: "general") -
order(number, optional): Order within zone (default: 999) -
moduleId(string, optional): Module identifier (default: "blacksmith-core") -
gmOnly(boolean, optional): Whether tool is GM-only (default: false) -
leaderOnly(boolean, optional): Whether tool is leader-only (default: false) -
onCoffeePub(boolean|Function, optional): Whether to show in Blacksmith toolbar. Can be a boolean or a function that returns a boolean for dynamic visibility. Defaults totruefor backward compatibility. -
onFoundry(boolean|Function, optional): Whether to show in FoundryVTT native toolbar. Can be a boolean or a function that returns a boolean for dynamic visibility. Defaults tofalse.
Removes a tool from the Blacksmith toolbar system.
Parameters:
-
toolId(string): Unique identifier for the tool
Returns: boolean - Success status
Gets all registered tools.
Returns: Map - Map of all registered tools (toolId -> toolData)
Gets all tools registered by a specific module.
Parameters:
-
moduleId(string): Module identifier
Returns: Array - Array of tools registered by the module
Checks if a tool is registered.
Parameters:
-
toolId(string): Unique identifier for the tool
Returns: boolean - Whether the tool is registered
Gets current toolbar settings.
Returns: Object - Current toolbar settings
{
displayStyle: string // "none", "dividers", or "labels"
}Updates toolbar settings.
Parameters:
-
settings(Object): Settings object-
displayStyle(string, optional):"none","dividers", or"labels". Validated against that set before writing — an unrecognized value is logged and ignored rather than stored.
-
The Blacksmith toolbar system supports two different toolbar locations:
-
onCoffeePub: true: Shows in the Blacksmith Utilities toolbar (custom toolbar) -
onFoundry: true: Shows in FoundryVTT's native token control toolbar
// Tool only in Blacksmith toolbar (default behavior)
blacksmith.registerToolbarTool('blacksmith-only', {
// ... other properties
onCoffeePub: true,
onFoundry: false
});
// Tool only in FoundryVTT toolbar
blacksmith.registerToolbarTool('foundry-only', {
// ... other properties
onCoffeePub: false,
onFoundry: true
});
// Tool in both toolbars
blacksmith.registerToolbarTool('both-toolbars', {
// ... other properties
onCoffeePub: true,
onFoundry: true
});-
onCoffeePub:true(backward compatibility) - Can be a boolean or function -
onFoundry:false(current behavior) - Can be a boolean or function
Both onCoffeePub and onFoundry support function values for dynamic visibility:
// Tool that only appears in CoffeePub toolbar when a setting is enabled
blacksmith.registerToolbarTool('conditional-tool', {
// ... other properties
onCoffeePub: () => {
return game.settings.get('my-module', 'enableToolbarTool');
},
onFoundry: false
});The toolbar system organizes tools into predefined zones:
-
general- Default zone for tools that don't fit other categories -
rolls- Roll-related tools, dice rollers, random generators -
communication- Chat, messaging, and communication tools -
utilities- General utility tools, helpers, calculators -
leadertools- Leadership and management tools -
gmtools- GM-specific tools, admin functions, management tools
-
general: Default zone for tools that don't fit other categories -
rolls: Dice rollers, random generators, roll-related tools -
communication: Chat tools, messaging, communication features -
utilities: General helpers, calculators, utility functions -
leadertools: Party leadership tools, vote management -
gmtools: GM-only tools, admin functions, management tools
The toolbar uses a three-tier visibility system:
- GM: Sees all tools (including GM tools and leader tools)
- LEADER: Sees all tools except GM tools, plus leader tools
- PLAYER: Sees all tools except GM tools and leader tools
-
gmOnly: true: Only visible to Game Masters -
leaderOnly: true: Visible to party leaders and GMs - Default: Visible to all users
Tools within each zone are ordered by their order property:
- Lower numbers appear first within each zone
-
Recommended ranges:
-
1-10: Core/primary tools -
11-50: Secondary tools -
51-100: Utility tools -
101+: Optional/advanced tools
-
// Minimal example - many properties have defaults
// Only onClick is truly required
blacksmith.registerToolbarTool('my-utility', {
icon: "fa-solid fa-calculator", // Optional: has default
onClick: () => {
// Your utility logic
ui.notifications.info("Utility tool activated!");
}
// name defaults to 'my-utility' (toolId)
// title defaults to name or toolId
// button defaults to true (v13 requirement)
// visible defaults to true
// zone defaults to "general"
// order defaults to 999
// onCoffeePub defaults to true
// onFoundry defaults to false
});// Register a simple utility tool (Blacksmith toolbar only)
blacksmith.registerToolbarTool('my-utility', {
icon: "fa-solid fa-calculator",
name: "my-utility", // Optional: defaults to toolId
title: "My Utility Tool", // Optional: defaults to name or toolId
button: true, // Optional: defaults to true (v13 requirement)
visible: true, // Optional: defaults to true
zone: "utilities",
order: 10,
moduleId: "my-module",
onCoffeePub: true, // Optional: defaults to true
onFoundry: false, // Optional: defaults to false
onClick: () => {
// Your utility logic
ui.notifications.info("Utility tool activated!");
}
});// Register a GM-only admin tool
blacksmith.registerToolbarTool('my-admin-tool', {
icon: "fa-solid fa-cog",
name: "my-admin-tool",
title: "Admin Tool",
button: true, // REQUIRED for toolbar display
visible: true, // REQUIRED for visibility
zone: "gmtools",
order: 5,
moduleId: "my-module",
gmOnly: true,
onClick: () => {
// Admin functionality
console.log("Admin tool used by GM");
}
});// Register a leader-only tool
blacksmith.registerToolbarTool('my-leader-tool', {
icon: "fa-solid fa-crown",
name: "my-leader-tool",
title: "Leader Tool",
button: true, // REQUIRED for toolbar display
visible: true, // REQUIRED for visibility
zone: "leadertools",
order: 1,
moduleId: "my-module",
leaderOnly: true,
onClick: () => {
// Leader functionality
ui.notifications.info("Leader tool activated!");
}
});// Register a tool for FoundryVTT's token toolbar
blacksmith.registerToolbarTool('my-token-tool', {
icon: "fa-solid fa-dice-d20",
name: "my-token-tool",
title: "Token Tool",
button: true,
visible: true,
zone: "rolls",
order: 5,
moduleId: "my-module",
onCoffeePub: false, // Don't show in Blacksmith toolbar
onFoundry: true, // Show in FoundryVTT toolbar
gmOnly: true, // Only GMs can use this tool
onClick: () => {
// Tool logic for token operations
ui.notifications.info("Token tool activated!");
}
});// Register a tool that appears in both toolbars
blacksmith.registerToolbarTool('my-universal-tool', {
icon: "fa-solid fa-star",
name: "my-universal-tool",
title: "Universal Tool",
button: true,
visible: true,
zone: "utilities",
order: 10,
moduleId: "my-module",
onCoffeePub: true, // Show in Blacksmith toolbar
onFoundry: true, // Show in FoundryVTT toolbar
onClick: () => {
// Tool logic
ui.notifications.info("Universal tool activated!");
}
});// Register a tool with dynamic visibility
blacksmith.registerToolbarTool('my-conditional-tool', {
icon: "fa-solid fa-eye",
name: "my-conditional-tool",
title: "Conditional Tool",
button: true,
visible: true,
zone: "utilities",
order: 20,
moduleId: "my-module",
onCoffeePub: true,
onFoundry: false,
visible: () => {
// Only show if certain conditions are met
return game.user.isGM || game.settings.get('my-module', 'enableFeature');
},
onClick: () => {
// Tool logic
}
});// Unregister every tool this module registered.
// Unregister by tool.toolId — NOT tool.name. The registry is keyed by toolId; `name` is only a
// CSS class/label that happens to default to toolId. If you passed a `name` different from your
// toolId, unregistering by name silently returns false and the tool becomes unremovable.
function cleanUpMyTools() {
const tools = blacksmith.getToolsByModule('my-module');
tools.forEach(tool => blacksmith.unregisterToolbarTool(tool.toolId));
}Call this from your own lifecycle, not from an unload hook. Foundry has no module-unload event — disableModule and unloadModule are both dead names that never fire (see api-hookmanager.md). Disabling a module reloads the world and tears the toolbar down anyway, so this is only worth calling if you turn a feature off at runtime.
The API includes robust error handling:
-
Invalid tool data: Returns
falseand logs error —toolIdmust be a non-empty string,toolDatamust be an object. -
Missing
onClick: Returnsfalseand logs error. A tool without a callableonClickwould render a button that does nothing, so it is rejected rather than stored. -
Duplicate tool IDs: Returns
falseonly when a different module already owns the id — the owner keeps its tool and the newcomer is rejected with a log naming both. Re-registering your own tool is allowed and overwrites your previous entry, returningtrue; modules do this deliberately to refresh button state. So afalsehere means "someone else owns this id", not "this id is taken". - API not available: Check for API availability before use
- Unique Tool IDs: Use descriptive, unique tool identifiers
- Proper Zone Selection: Choose the most appropriate zone for your tool
- Consistent Ordering: Use consistent order values within your module
- Module Cleanup: Unregister tools only if you disable a feature at runtime — there is no module-unload event, and a world reload clears them otherwise
- Error Handling: Always check return values and handle errors gracefully
- API Availability: Check if the API is available before using it
- Check if tool is registered:
blacksmith.isToolRegistered('tool-id') - Verify visibility settings (gmOnly, leaderOnly, visible function)
-
For FoundryVTT v13: Ensure
nameproperty is set (defaults totoolIdif not provided) -
For FoundryVTT v13:
buttonproperty defaults totruebut must betruefor toolbar display - Verify
onCoffeePuboronFoundryfunctions returntrueif using function values - Check console for error messages
- Ensure API is loaded:
blacksmith?.registerToolbarTool - If players don't see newly registered tools, make sure a controls refresh runs on their client (e.g., after registration or when settings change)
-
Use correct API path:
blacksmith.registerToolbarTool()notblacksmith.api.registerToolbarTool() - Wait for
readyhook, notblacksmithUpdatedhook - Check if module is active:
game.modules.get('coffee-pub-blacksmith')?.active
- Verify
zoneproperty is set correctly - Check zone spelling (must match predefined zones exactly)
- Default zone is "general" if not specified
- Verify
onClickfunction is provided and valid - Check for JavaScript errors in onClick function
- Ensure tool is not disabled by visibility logic
- Ai assistance
- Applicationv2 traps
- CSS traps
- dnd5e conditions
- Documentation standard
- Token actor identity
- Campaign
- Canvas
- Chatcards
- Compendiums
- Contextmenu
- Core
- Create journal entry
- Dialog
- Active Effects
- Entity list
- Equiplocations
- Geography
- GM request
- Gmnotes
- Health
- Hookmanager
- Importer
- Inventory
- Menubar
- Notes
- Party
- Pins
- Quantity split
- Requestroll
- Rolls
- Scene config
- Sockets
- Stats
- Tags
- Toast
- Tokens
- Toolbar
- Window
- Worldclock