A minimal Foundry VTT v14 game system written in TypeScript with Svelte 5 sheets and vanilla CSS. The mechanics mirror the canonical asacolips boilerplate: two actor types (character, npc), three item types (item, feature, spell), six d20-style abilities, HP/power resources, and a d20 + @abil.mod + ceil(@lvl/2) roll formula on owned items.
$state, $derived, $props). Components are mounted into ApplicationV2 content via mount() / unmount().css/system.css, no preprocessor.DataModel for schemas, DocumentSheetV2 for sheets, no Handlebars templates.src/
system.ts # main entry — Hooks.once("init"), registers everything
config.ts # BOILERPLATE config object (ability labels, etc.)
helpers.ts # roll-data shaping
data/ # DataModel schemas
character.ts npc.ts item.ts feature.ts spell.ts
documents/ # Document subclasses (rolls, derived data)
actor.ts item.ts
sheets/ # ApplicationV2 + Svelte mount glue
actor-sheet.ts item-sheet.ts
components/ # Svelte 5 sheet UIs
ActorApp.svelte ItemApp.svelte
CharacterSheet.svelte NpcSheet.svelte
ItemSheet.svelte FeatureSheet.svelte SpellSheet.svelte
css/system.css # vanilla, scoped via .fvtt-svelte
lang/en.json
system.json template.json
npm install
npm run build # one-time: produce dist/ so Foundry can register the system
npm run dev # start Vite dev server with HMR (run Foundry on :30000)
Symlink dist/ into your Foundry user data so Foundry can read system.json from disk:
ln -s "$(pwd)/dist" "$FOUNDRY_DATA/Data/systems/fvtt-svelte"
vite build emits a self-contained Foundry system folder at dist/ — system.json, template.json, the bundled system.js, css/, lang/, and license/readme. Foundry serves it directly; nothing else needed.
npm run dev starts a Vite dev server on port 30001 that proxies to Foundry on port 30000. Open Foundry at http://localhost:30001/ instead of the usual port — Vite intercepts every request under /systems/fvtt-svelte/ and serves source files directly with HMR.
What you get:
.svelte edits hot-swap the component without a page reload (state preserved where possible) — that's vite-plugin-svelte doing its thing..ts edits trigger a fast module reload or page reload as Vite sees fit.css/system.css edits require a manual page reload — Foundry loads CSS via <link>, which is incompatible with Vite's JS-wrapped CSS HMR, so the dev server serves CSS raw instead.This pattern is adapted from the Lancer system's Vite setup. If your Foundry runs on a different port, edit FOUNDRY_PORT / VITE_PORT in vite.config.ts.
level, six abilities (str/agi/vig/int/tec/luc), HP, power, biography. mod = floor((value - 10) / 2) is derived per-ability.cr, HP, power, biography.quantity, weight, formula (default d20 + @str.mod + ceil(@lvl/2)); rolls via the chat card "Roll" button.spellLevel.