/add-feature — Add a New Game System
Use this skill when adding a new game system, equipment type, mechanic, or feature to Fabric Tycoon. It enforces the 9-step integration checklist from CLAUDE.md so nothing gets missed.
Instructions
When the user invokes /add-feature, ask them to describe the feature if they haven't already. Then follow every step below in order, confirming each is complete before moving on.
Step 1: Define Types & Constants
File: src/stores/gameStore.ts
- •Add any new TypeScript types or interfaces (PascalCase)
- •Add simulation constants to the
SIMobject or a new config object (UPPER_SNAKE_CASE) - •If it's a catalog-style feature (like incidents or achievements), create a
*_CATALOGarray - •Remember: no
enumornamespace(erasableSyntaxOnly is enabled)
Step 2: Add State & Actions
File: src/stores/gameStore.ts
- •Add new state fields to the
GameStateinterface - •Add initial values in the
create<GameState>()call - •Write action functions following the immutable update pattern (spread operators)
- •Call
calcStats()at the end of any action that changes power/heat-relevant state
Step 3: Update tick()
File: src/stores/gameStore.ts
- •Add processing logic in the
tick()function - •Place it in the correct section among the existing systems:
- •Time-of-day
- •Weather
- •Supply chain
- •Incidents & Ops Tier
- •Tech tree
- •Power market
- •Generators
- •Fire system
- •Heat
- •Revenue
- •Expenses
- •Noise
- •Spot compute
- •Staff
- •Maintenance
- •Infrastructure
- •Contracts
- •Reputation
- •Depreciation
- •Achievements
- •Traffic
- •Capacity history
- •Lifetime stats
- •Event logging
- •Tutorial
- •Carbon/Environment
- •Security/Compliance
- •Competitor AI
Step 4: Update calcStats() (if applicable)
File: src/stores/gameStore.ts
- •If the feature affects power draw, heat generation, or other computed stats, update
calcStats()and/orcalcTraffic() - •Ensure the pure function signature stays clean
Step 5: Add Phaser Rendering
File: src/game/PhaserGame.ts
- •Add a public API method on
DataCenterScene(e.g.,addXToScene(),updateX()) - •Use
Phaser.GameObjects.Graphicsonly — no sprites or images - •Follow the isometric drawing conventions (
drawIsoCube()for 3D elements) - •Choose colors consistent with the neon palette (green=servers, cyan=leaf, orange=spine)
Step 6: Bridge in GameCanvas
File: src/components/GameCanvas.tsx
- •Add a
useEffecthook to sync the new state to Phaser - •Use
useRefto track previous counts if adding incremental objects - •Follow the existing pattern of the 10 sync effects
Step 7: Add UI Controls
File: src/components/sidebar/*.tsx
- •Add controls in the appropriate sidebar panel (see
src/components/sidebar/for all panels) - •If no existing panel fits, create a new panel component and register it in
Sidebar.tsx - •Follow existing patterns: shadcn/ui buttons, Tailwind classes, neon color theme
- •Wrap interactive elements with
<Tooltip>using the established pattern - •Use
lucide-reacticons
Step 8: Add Tests
File: src/stores/__tests__/gameStore.test.ts
- •Add tests for new store actions and tick behavior
- •Use the
setupBasicDataCenter()helper for standard test fixtures - •Follow existing
describe()block organization by game system - •Test both happy paths and edge cases
Step 9: Update resetGame()
File: src/stores/gameStore.ts
- •Add all new state fields to the
resetGame()action with their default values - •Ensure a full reset returns the game to a clean initial state
Final Checklist
Before marking complete, verify:
- •
npm run lintpasses with no errors - •
npm run testpasses with no failures - •
npm run buildsucceeds (TypeScript + Vite) - • New types use
import typewhere appropriate (verbatimModuleSyntax) - • No unused variables or parameters (strict mode)
- • Constants use UPPER_SNAKE_CASE, types use PascalCase
- • State updates are immutable (spread operators, new arrays/objects)
- •
calcStats()called after relevant mutations - •
resetGame()resets all new state fields