This skill should be used when choosing between flags, settings, or files for data storage, implementing document flags, registering module settings, handling file uploads, or migrating data between storage types. Covers namespacing, scope types, and performance optimization.
View on GitHubImproperSubset/hh-agentics
fvtt-dev
fvtt-dev/skills/fvtt-data-storage/SKILL.md
January 21, 2026
Select agents to install to:
npx add-skill https://github.com/ImproperSubset/hh-agentics/blob/main/fvtt-dev/skills/fvtt-data-storage/SKILL.md -a claude-code --skill fvtt-data-storageInstallation paths:
.claude/skills/fvtt-data-storage/# Foundry VTT Data Storage
**Domain:** Foundry VTT Module/System Development
**Status:** Production-Ready
**Last Updated:** 2026-01-04
## Overview
Foundry VTT provides three primary storage mechanisms: Flags (document-attached), Settings (global config), and Files (external storage). Choosing the wrong method is a common source of bugs and performance issues.
### When to Use This Skill
- Deciding where to store module/system data
- Implementing document-specific custom properties
- Creating module configuration options
- Handling large datasets that impact performance
- Migrating data between storage types
### Quick Decision Matrix
| Need | Use | Why |
|------|-----|-----|
| Data on specific document | **Flags** | Travels with document, respects permissions |
| Global module config | **Settings** (world) | Synced to all clients, GM-controlled |
| Per-device preference | **Settings** (client) | localStorage, user-specific |
| Large datasets | **Files** | No performance impact on documents |
| Export/import data | **Files** | Portable, shareable |
## Flags
Flags attach key-value data to Documents (Actors, Items, Scenes, etc.).
### Basic Usage
```javascript
// Set a flag
await actor.setFlag('my-module', 'customProperty', { value: 42 });
// Get a flag
const data = actor.getFlag('my-module', 'customProperty');
// data === { value: 42 }
// Delete a flag
await actor.unsetFlag('my-module', 'customProperty');
// Direct access (read-only)
const value = actor.flags['my-module']?.customProperty;
```
### Namespacing
Always use your module ID as the scope:
```javascript
// CORRECT - Uses module ID
await doc.setFlag('my-module-id', 'flagName', value);
// WRONG - Generic scope causes collisions
await doc.setFlag('world', 'flagName', value);
```
### Batch Updates
```javascript
// BAD - Three database writes
await actor.setFlag('myModule', 'flag1', value1);
await actor.setFlag('myModule', 'flag2', value2);
await actor.setFlag('myModule', 'flag3', value3);
// GOOD