Skip to content
fvtt-v13-migration logo

Foundry VTT V13 Development Guide

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. Provi...

SKILL.md

Full skill instructions

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:

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:

{
  "esmodules": ["scripts/​module.js"],
  "scripts": []
}

Internationalization (i18n)

ALWAYS use game.i18n.localize() or game.i18n.format() for user-facing text. Never hardcode English strings.

// 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:

{
  "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

// 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)
// 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.)
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:

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:

{
  "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


Last Updated: 2026-01-05 Status: Production-Ready Maintainer: ImproperSubset

More skills from majiayu000

xiaohongshu logo
majiayu000/claude-arsenal

xiaohongshu

xiaohongshu

286 148
View
agent-task-conductor logo
majiayu000/claude-skill-registry

agent-task-conductor

Conduct multi-agent task orchestration and workflow coordination.

663 1
View
conductor-setup logo
majiayu000/claude-skill-registry

conductor-setup

Initialize project with Conductor artifacts (product definition,

663 1
View
animation-designer logo
majiayu000/claude-skill-registry

animation-designer

Expert in web animations, transitions, and motion design using Framer Motion and CSS

663 1
View
diagramming logo
majiayu000/claude-skill-registry

diagramming

Creates Mermaid and ASCII diagrams for flowcharts, architecture, ERDs, state machines, mindmaps, and more. Use when user mentions diagram, flowchart, mermaid, ASCII diagram, text diagram, terminal diagram, visualize, C4, mindmap, architecture diagram, sequence diagram, ERD, or needs visual docume...

663 1
View
h3-pg logo
majiayu000/claude-skill-registry-data

h3-pg

PostgreSQL bindings for H3 hexagonal grid system. Use when working with H3 cells in Postgres, including spatial indexing, geometry/geography integration, and raster analysis.

23 1
View
conductor-development logo
majiayu000/claude-skill-registry

conductor-development

Context-Driven Development skill for projects using Conductor. Use this skill when you detect a `conductor/` directory in the project, when working on tasks defined in a `plan.md` file, or when the user asks about tracks, specs, or plans. Automatically applies TDD workflow, tracks task completion...

663 1
View
conductor-status logo
majiayu000/claude-skill-registry

conductor-status

Display project status, active tracks, and next actions

663 1
View
dockerization logo
majiayu000/claude-skill-registry

dockerization

Official Stakpak application containerization standard operating procedure, a step-by-step guidline to properly dockerize applications. This is a rule book curated by the Stakpak Team.

663 1
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View