Contributing
🚀 Quick Start
Prerequisites
- Node.js >= 22.1.0
- FoundryVTT running locally (for development)
- Git for version control
Development Setup
Clone the repository:
bashgit clone https://github.com/Nimble-Co/FoundryVTT-Nimble.git cd FoundryVTT-NimbleInstall dependencies:
bashpnpm installStart the development server:
bashpnpm devThis will start a Vite development server on
http://localhost:30001that proxies to your local FoundryVTT instance running on port 30000.Configure FoundryVTT:
- Ensure FoundryVTT is running on
http://localhost:30000 - The development server will automatically proxy requests to your FoundryVTT instance
- The system will be available at
/systems/nimble/in your FoundryVTT installation
- Ensure FoundryVTT is running on
Build Commands
pnpm build- Build the system and compendia for productionpnpm build:system- Build only the system filespnpm build:compendia- Build only the compendia datapnpm dev- Start development server with hot reloadpnpm format- Format code with Biomepnpm lint- Lint code with Biomepnpm lint-fix- Auto-fix linting issuespnpm type-check- Run TypeScript type checkingpnpm check- Run all checks (format, lint, circular dependencies, type-check, tests)
📁 Project Structure
FoundryVTT-Nimble/
├── src/ # Main source code
│ ├── nimble.ts # Main entry point
│ ├── config.ts # System configuration
│ ├── game.ts # Game instance setup
│ ├── hooks/ # FoundryVTT lifecycle hooks
│ │ ├── init.ts # System initialization
│ │ ├── setup.ts # System setup
│ │ ├── ready.ts # System ready state
│ │ └── ...
│ ├── documents/ # Document classes (Actors, Items, etc.)
│ ├── models/ # Data models
│ ├── dice/ # Custom dice implementations
│ ├── canvas/ # Canvas and rendering logic
│ ├── view/ # Svelte components and UI
│ ├── utils/ # Utility functions
│ ├── scss/ # Stylesheets
│ └── pixi/ # PIXI.js integrations
├── lib/ # Svelte component mixins
├── packs/ # Game content compendia
├── public/ # Static assets
├── types/ # TypeScript type definitions
├── vite.config.mts # Vite configuration
├── svelte.config.js # Svelte configuration
├── tsconfig.json # TypeScript configuration
├── package.json # Dependencies and scripts
└── compendia.mjs # Compendia build script🔧 Key Files
Core System Files
src/nimble.ts- Main entry point that registers all hooks and initializes the systemsrc/config.ts- System configuration including ability scores, damage types, classes, and game constantssrc/hooks/init.ts- System initialization hook that registers document classes, sheets, and data modelssrc/game.ts- Game instance setup and global utilities
Build Configuration
vite.config.mts- Vite configuration with FoundryVTT proxy setupsvelte.config.js- Svelte preprocessor configurationtsconfig.json- TypeScript configuration with FoundryVTT types
Development Tools
package.json- Project dependencies and pnpm scriptscompendia.mjs- Script for building game content compendia
🏗️ Architecture
Technology Stack
- Frontend Framework: Svelte 5 with TypeScript
- Build Tool: Vite
- Styling: SCSS with custom functions and variables
- Icons: Font Awesome
- Canvas: PIXI.js integration
- Linting/Formatting: Biome
- Type Checking: TypeScript with FoundryVTT type definitions
Key Features
- Custom Dice System: NimbleRoll and DamageRoll implementations
- Svelte Components: Modern UI components for character sheets and dialogs
- Compendia System: Game content packaged as compendia
- Modular Architecture: Clean separation of concerns with hooks, documents, and views
- Hot Reload: Development server with live reloading
FoundryVTT Integration
The system integrates deeply with FoundryVTT through:
- Document Classes: Custom Actor, Item, and Combat implementations
- Application Sheets: Svelte-based character and item sheets
- Canvas Integration: Custom template layer and token HUD
- Hooks System: Proper lifecycle management
- Data Models: Type-safe data structures for all game entities
🤝 Contributing
- Fork the repository
- Ensure you're on the
devbranch:git checkout dev - Create a feature branch from
dev:git checkout -b feature/your-feature - Make your changes and ensure tests pass
- Run checks before committing:
pnpm check - Commit your changes:
git commit -am 'Add some feature' - Push to the branch:
git push origin feature/your-feature - Submit a pull request against the
devbranch
Note: All development work should branch from
devand all pull requests should targetdev. Themainbranch is reserved for releases.
Development Guidelines
- Use TypeScript for all new code
- Follow the existing code style and patterns
- Run
pnpm checkbefore committing (formats, lints, checks for circular dependencies, type-checks, and runs tests) - Test your changes in FoundryVTT
- Update documentation as needed
Community & Communication
Join our Discord server before contributing: Nimble FoundryVTT System
We encourage all contributors to join the Discord and discuss changes before submitting large or architectural PRs. This helps ensure alignment with project direction and prevents wasted effort.
Pull Request Guidelines
PRs that will be rejected:
- Overly large PRs without prior discussion - If your PR touches many files or introduces significant new functionality, please discuss it on Discord first. Breaking changes into smaller, reviewable PRs is preferred.
- Complex infrastructure changes - PRs introducing Docker setups, Playwright automation, CI/CD changes, or other infrastructure without prior team consultation will be closed.
- AI-generated bulk changes - Large PRs that appear to be AI-generated without human review or curation are difficult to review and will be rejected. This includes bulk additions of configuration files, automated testing suites, or agent-style setups.
- Security risks - PRs containing potential security vulnerabilities, including prompt injection risks in configuration files, will not be merged.
Best practices:
- Keep PRs focused and reasonably sized
- Provide clear descriptions of what your PR does and why
- If using AI tools to assist with code, review and understand all changes before submitting
- For significant features or architectural changes, open an issue or discuss on Discord first
📦 Deployment
- Build the system:
pnpm build - Copy the
dist/folder to your FoundryVTTsystems/nimble/directory - Restart FoundryVTT or reload the system
📚 External Documentation
Everyday Knowledge
Used directly and frequently while working in the codebase.
- TypeScript Docs: https://www.typescriptlang.org/docs/ Language reference for typing, generics, and strict mode used across the project.
- Svelte Docs: https://svelte.dev/docs UI framework for character sheets and dialogs. Reactivity and component lifecycle.
- FoundryVTT API: https://foundryvtt.com/api/ Core Foundry classes, hooks, sheets, dialogs, combat, and system integration.
- FoundryVTT Community Wiki: https://foundryvtt.wiki/en/home Practical guides, patterns, common pitfalls, and system-level behavior not always obvious from the API docs.
- FoundryVTT TypeScript Types: https://github.com/League-of-Foundry-Developers/foundry-vtt-types Type definitions for Foundry APIs. Required for TypeScript safety and IDE autocomplete.
Occasional Reference
Only needed when working in specific areas or diagnosing issues.
- Vite Guide: https://vite.dev/guide/ Build tool and dev server for local development and bundling.
- Biome: https://biomejs.dev/ Formatter and linter enforcing code style and consistency.
- Vitest: https://vitest.dev/ Unit testing framework used for system tests.
Working on this documentation site
The site is built with VitePress from the docs/ folder. To preview locally:
- From the repo root, run
pnpm install, thenpnpm docs:generate. This builds the reference pages (rules, settings, conditions) from the system source. They are not checked in; without this step those pages 404. cd docs && pnpm install && pnpm dev.
The pages under docs/documentation/reference/ are regenerated on every deploy. Edit the generator (scripts/docs/generateReference.gen.ts), the source schemas, or the _partials/ examples instead of the output. Everything else is hand-written markdown.
House style for the user documentation: plain language a GM can follow, no developer jargon, and no em-dashes anywhere (the generator strips them from generated pages automatically).