Back to Skills

fvtt-data-storage

verified

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 GitHub

Marketplace

hh-agentics

ImproperSubset/hh-agentics

Plugin

fvtt-dev

development

Repository

ImproperSubset/hh-agentics

fvtt-dev/skills/fvtt-data-storage/SKILL.md

Last Verified

January 21, 2026

Install Skill

Select agents to install to:

Scope:
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-storage

Installation paths:

Claude
.claude/skills/fvtt-data-storage/
Powered by add-skill CLI

Instructions

# 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

Validation Details

Front Matter
Required Fields
Valid Name Format
Valid Description
Has Sections
Allowed Tools
Instruction Length:
10240 chars