fvtt-v13-migration
This skill should be used when the user asks to "migrate to V13", "upgrade to Foundry V13", "update module for V13", "fix V13 compatibility", "convert to ESM", "use DataModel", or mentions V13-specific patterns like hook signature changes, actor.system vs actor.data.data, or Application V2. Provides comprehensive Foundry VTT V13 development patterns and migration guidance.
What this skill does
# Foundry VTT V13 Development Guide
**Domain:** Foundry VTT Module/System Development
**Status:** Production-Ready
**Last Updated:** 2026-01-05
## Overview
This guide covers V13-specific patterns and migration from earlier versions. For modules targeting V13, follow these guidelines.
### When to Use This Skill
- Migrating a module/system from V12 or earlier to V13
- Converting CommonJS (`require`) to ESM (`import`/`export`)
- Implementing DataModel for structured data
- Updating deprecated patterns (`actor.data.data` to `actor.system`)
- Fixing hook signature changes after V13 upgrade
- Setting up V13-compatible manifest configuration
## Core Architecture Principles
### Use DataModel for Structured Data
**ALWAYS** use `foundry.abstract.DataModel` for defining data structures instead of plain JavaScript objects. DataModels provide:
- Built-in validation and type coercion
- Schema definition with `DataSchema`
- Automatic data preparation lifecycle
- Integration with Foundry's document system
Example:
```javascript
class MyModuleData extends foundry.abstract.DataModel {
static defineSchema() {
const fields = foundry.data.fields;
return {
name: new fields.StringField({ required: true, blank: false }),
value: new fields.NumberField({ initial: 0, min: 0 }),
enabled: new fields.BooleanField({ initial: true })
};
}
}
```
### ESM Modules Only
Foundry V13 uses **ECMAScript Modules (ESM)** exclusively. Your code must:
- Use `import` and `export` statements (NO `require()`)
- Declare `"esmodules"` in your manifest (NOT `"scripts"`)
- Use `.js` extensions in import paths when importing relative files
Example manifest entry:
```json
{
"esmodules": ["scripts/module.js"],
"scripts": []
}
```
### Internationalization (i18n)
**ALWAYS** use `game.i18n.localize()` or `game.i18n.format()` for user-facing text. Never hardcode English strings.
```javascript
// BAD
ui.notifications.info("Item created successfully");
// GOOD
ui.notifications.info(game.i18n.localize("MYMODULE.Notifications.ItemCreated"));
// For dynamic values
const message = game.i18n.format("MYMODULE.Notifications.ItemCreatedWithName", {
name: itemName
});
```
Localization files go in `lang/en.json`:
```json
{
"MYMODULE.Notifications.ItemCreated": "Item created successfully",
"MYMODULE.Notifications.ItemCreatedWithName": "Item {name} created successfully"
}
```
## Common V13 Pitfalls
### Hook Arguments Have Changed
Many hooks in V13 have different argument signatures than V12. Always check the current API documentation.
**Example: `createToken` Hook**
```javascript
// V12 (OLD - WRONG in V13)
Hooks.on("createToken", (scene, tokenData, options, userId) => { });
// V13 (CORRECT)
Hooks.on("createToken", (tokenDocument, options, userId) => { });
```
### Document vs Data
V13 distinguishes between Document classes (e.g., `Actor`, `Item`) and their data models:
- Access document properties directly: `actor.name`, `item.system`
- Use `actor.system` to access system-specific data defined in your DataModel
- Avoid accessing `actor.data.data` (deprecated pattern from V10)
```javascript
// BAD (V10 pattern)
const hp = actor.data.data.attributes.hp.value;
// GOOD (V13 pattern)
const hp = actor.system.attributes.hp.value;
```
### Active Effects Structure
Active Effects in V13 use a cleaner structure:
- Effects are stored in `document.effects` (EffectCollection)
- Use `await actor.createEmbeddedDocuments("ActiveEffect", [effectData])`
- Effect changes use `key` (path to property) and `mode` (add, multiply, override, etc.)
```javascript
const effectData = {
name: game.i18n.localize("MYMODULE.Effects.Blessed"),
icon: "icons/magic/light/beam-rays-yellow.webp",
changes: [{
key: "system.attributes.ac.bonus",
mode: CONST.ACTIVE_EFFECT_MODES.ADD,
value: "2"
}],
duration: { rounds: 10 }
};
await actor.createEmbeddedDocuments("ActiveEffect", [effectData]);
```
### Canvas Rendering Layers
V13 has reorganized canvas layers. Use the correct layer references:
- `canvas.tokens` - TokenLayer
- `canvas.tiles` - TilesLayer
- `canvas.lighting` - LightingLayer
- `canvas.grid` - GridLayer
### Dialog API Updates
Dialog construction now prefers Application V2 patterns in some contexts, but classic Dialogs still work:
```javascript
new Dialog({
title: game.i18n.localize("MYMODULE.Dialog.Title"),
content: `<p>${game.i18n.localize("MYMODULE.Dialog.Content")}</p>`,
buttons: {
yes: {
icon: '<i class="fas fa-check"></i>',
label: game.i18n.localize("MYMODULE.Dialog.Confirm"),
callback: () => { /* action */ }
},
no: {
icon: '<i class="fas fa-times"></i>',
label: game.i18n.localize("MYMODULE.Dialog.Cancel")
}
},
default: "yes"
}).render(true);
```
## Data Field Types Reference
When defining DataModel schemas, use these field types from `foundry.data.fields`:
- `StringField` - Text data
- `NumberField` - Numeric values (integers or floats)
- `BooleanField` - True/false values
- `ObjectField` - Nested objects
- `ArrayField` - Arrays of values
- `SchemaField` - Nested DataModel schema
- `HTMLField` - Sanitized HTML content
- `FilePathField` - File paths (images, sounds, etc.)
- `ColorField` - Color values (hex strings)
- `AngleField` - Angles in degrees
- `AlphaField` - Alpha transparency (0-1)
## Best Practices
1. **Always await async operations** - Most Foundry operations are async
2. **Check for user permissions** - Use `game.user.isGM` or document permission checks
3. **Use `fromUuidSync()` or `fromUuid()`** - For reliable document references
4. **Leverage Hooks** - Don't override core behavior, extend it via hooks
5. **Handle errors gracefully** - Wrap operations in try/catch and show user-friendly messages
6. **Test with multiple users** - Permission and rendering issues often appear in multi-user scenarios
7. **Follow Foundry's module conventions** - Use proper manifest structure, versioning, and compatibility flags
## Manifest Requirements
Your `module.json` or `system.json` must declare V13 compatibility:
```json
{
"id": "my-module",
"title": "My Module",
"version": "1.0.0",
"compatibility": {
"minimum": "13",
"verified": "13",
"maximum": "13"
},
"esmodules": ["scripts/init.js"],
"languages": [
{
"lang": "en",
"name": "English",
"path": "lang/en.json"
}
]
}
```
## Development Workflow
1. Enable "Developer Mode" in Foundry settings for better error messages
2. Use browser DevTools Console for debugging
3. Use `console.log()` liberally, or set up proper logging with `CONFIG.debug`
4. Test in a fresh world to avoid conflicts with other modules
5. Use `CONFIG.debug.hooks = true` to see all hook executions
Remember: When in doubt, check the official Foundry VTT V13 API documentation at https://foundryvtt.com/api/
## Implementation Checklist
### Module Structure
- [ ] Manifest declares `"esmodules"` (not `"scripts"`)
- [ ] All imports use ESM syntax with `.js` extensions
- [ ] Compatibility set to minimum V13
### Data Patterns
- [ ] DataModel classes define schemas with `defineSchema()`
- [ ] Access system data via `document.system` (not `data.data`)
- [ ] Active Effects use correct change structure
### Code Quality
- [ ] All user-facing strings use `game.i18n.localize()`
- [ ] Hook callbacks use V13 argument signatures
- [ ] Async operations are properly awaited
- [ ] Permissions checked before privileged operations
### Testing
- [ ] Module loads without console errors
- [ ] DataModel validation works correctly
- [ ] Hooks fire with expected arguments
- [ ] Multi-user scenarios tested
## References
- [Foundry VTT V13 API](https://foundryvtt.com/api/)
- [DataModel API](https://foundryvtt.com/api/classes/foundry.abstract.DataModel.html)
- [Migration Guide](https://foundryvtt.wiki/en/development/guides/v13-migration)
- [ESM in Foundry](https://foundryvtt.wiki/en/development/guides/esm)
---
**Last Updated:** 2026-01-05
**Status:** PRelated in Code Review
gstack
IncludedFast headless browser for QA testing and site dogfooding. Navigate pages, interact with elements, verify state, diff before/after, take annotated screenshots, test responsive layouts, forms, uploads, dialogs, and capture bug evidence. Use when asked to open or test a site, verify a deployment, dogfood a user flow, or file a bug with screenshots. (gstack)
startup-due-diligence
IncludedLegal due diligence review for seed-stage and Series A startups (US, Delaware C-Corp focus). Supports both investor and founder perspectives. Capabilities include: (1) Interactive document review and issue spotting; (2) Document request list generation; (3) Cap table and SAFE/convertible note analysis; (4) Red flag identification with severity ratings; (5) Diligence report generation. TRIGGERS: due diligence, DD, startup investment, cap table review, Series A, seed round, investor diligence, legal review startup, SAFE analysis, convertible note, 409A, founder vesting.
interview-master
IncludedThis skill should be used when the user asks to "generate interview questions", "prepare for interview", "optimize resume", "conduct mock interview", "analyze git commits for resume", "generate resume from code", "review my resume", or mentions interview preparation, career assistance, or extracting project experience from git history. Provides comprehensive interview and career development guidance for both job seekers and interviewers.
fix-issue
IncludedFixes GitHub issues using parallel analysis agents for root cause investigation, code exploration, and regression detection. Reads issue context from gh CLI, searches codebase and memory for related patterns, generates a fix with tests, and links the resolution back to the issue via PR. Includes prevention analysis to avoid recurrence. Use when debugging errors, resolving regressions, fixing bugs, or triaging issues.
sf-apex
IncludedGenerates and reviews Salesforce Apex code with 150-point scoring. TRIGGER when: user writes, reviews, or fixes Apex classes, triggers, test classes, batch/queueable/schedulable jobs, or touches .cls/.trigger files. DO NOT TRIGGER when: LWC JavaScript (use sf-lwc), Flow XML (use sf-flow), SOQL-only queries (use sf-soql), or non-Salesforce code.
swift-development
IncludedComprehensive Swift development for building, testing, and deploying iOS/macOS applications. Use when Claude needs to: (1) Build Swift packages or Xcode projects from command line, (2) Run tests with XCTest or Swift Testing framework, (3) Manage iOS simulators with simctl, (4) Handle code signing, provisioning profiles, and app distribution, (5) Format or lint Swift code with SwiftFormat/SwiftLint, (6) Work with Swift Package Manager (SPM), (7) Implement Swift 6 concurrency patterns (async/await, actors, Sendable), (8) Create SwiftUI views with MVVM architecture, (9) Set up Core Data or SwiftData persistence, or any other Swift/iOS/macOS development tasks.