Package Exports
- phaser-viewer
- phaser-viewer/test
- phaser-viewer/test-runner
Readme
Phaser Viewer
A Storybook-like development environment for Phaser 3 components with interactive testing capabilities.
A lightweight Storybook alternative for Phaser 3 game components
โจ Features
| ๐ฎ | Storybook-like UI Hierarchical sidebar with organized component demos |
| ๐งช | Interactive & Automated Testing Built-in expect API with visual feedback, play logs, and CLI test runner |
| ๐ฅ | Hot Reload Instant feedback during development with Vite |
| ๐ฆ | No Setup Required Just create .demo.ts files and run npm command |
| โก | Asset Loading PreloadScene support for centralized asset management |
| ๐ฌ | Scene Configuration Customizable canvas size and background color for different project needs |
| ๐ฏ | TypeScript First Full type safety with automatic component and args inference using advanced TypeScript patterns |
| ๐ | Component Reset Reset button to restore components to initial state after Play tests while preserving test history |
| ๐ | Development Grid System Smart square grid overlay that perfectly fits your scene size for precise component positioning and alignment |
๐ฆ Installation
npm install phaser-viewer
# or
yarn add phaser-viewer
# or
pnpm add phaser-viewer๐ Quick Start
1๏ธโฃ Install phaser-viewer
npm install phaser-viewer2๏ธโฃ Create your component demo
Create a .demo.ts file alongside your component:
// src/Button.demo.ts
import { expect, delay } from 'phaser-viewer';
import { Meta, Demo } from 'phaser-viewer';
import { Button } from './Button'; // Import your component
import * as Phaser from 'phaser';
const meta = {
component: Button,
title: 'UI/Button',
description: 'Interactive button component'
} as const satisfies Meta<typeof Button>;
export default meta;
interface ButtonArgs {
x: number;
y: number;
text: string;
config?: {
color?: number;
width?: number;
height?: number;
};
}
export const BasicButton: Demo<typeof meta, ButtonArgs> = {
name: 'Basic Button',
args: { x: 400, y: 300, text: 'Click Me!' },
create: (scene, args) => {
// Full type inference: args has x, y, text properties
return new Button(scene, args.x, args.y, args.text, args.config);
},
play: async (_scene, component) => {
// Full type inference: component is Button instance with all methods
await expect(component.getText(), 'Initial text').toBe('Click Me!');
// Test interaction
component.emit('pointerdown');
await delay(100);
await expect(component.getText(), 'After click').toBe('Clicked!');
}
};3๏ธโฃ Start the development server
npx phaser-viewer
# or add to package.json scripts:
# "phaser-viewer": "phaser-viewer"That's it! Your Phaser component viewer will start automatically. No React setup files needed!
๐ Project Structure
your-project/
โโโ src/ # Your Phaser components and demos
โ โโโ Button.ts # Button component implementation
โ โโโ Button.demo.ts # Button component demos
โ โโโ Sprite.ts # Sprite component implementation
โ โโโ Sprite.demo.ts # Sprite component demos
โโโ .phaser-viewer-temp/ # Hidden temp files (auto-generated)
โโโ package.json # Include phaser-viewer script๐งช Testing Your Components
Phaser Viewer includes a powerful testing API inspired by @storybook/test. Tests can be run interactively in the browser or automatically via CLI.
Interactive Testing
Test results appear in the Play Logs panel with visual feedback:
import { expect, delay } from 'phaser-viewer';
export const InteractiveButton: Demo<typeof meta, ButtonArgs> = {
name: 'Interactive Button',
args: { x: 400, y: 300, text: 'Test Button' },
create: (scene, args) => {
// Type inference: args is ButtonArgs, scene is Phaser.Scene
return new Button(scene, args.x, args.y, args.text);
},
play: async (_scene, component) => {
// Type inference: component is Button instance with all methods
await expect(component.getText(), 'Initial text').toBe('Test Button');
await expect(component.visible, 'Should be visible').toBe(true);
// Test button click
component.emit('pointerdown');
await delay(100);
await expect(component.getText(), 'After click').toBe('Clicked!');
// Test multiple clicks
component.emit('pointerdown');
await delay(100);
await expect(component.getText(), 'After second click').toBe('Clicked 2x');
}
};Automated Testing (CLI)
Run all Play functions as automated tests:
npx phaser-viewer testExample Output:
๐งช Starting Phaser Viewer Test Runner...
๐ง Loaded user config: { filePath: './src/**/*.demo.ts' }
๐ฏ Play Functions: 2 passed, 1 failed
โ Gold - TestableGold: Expected 999, but received 600How it works:
- Each Play function becomes a test unit
- Expect assertions determine pass/fail status
- Failed tests show detailed error messages
- Tests run in headless browser environment
- Automatic dependency installation (vitest, playwright)
โก Asset Loading with PreloadScene
For components that require assets (images, sounds, etc.), you can create a PreloadScene class to handle asset loading:
1๏ธโฃ Create a PreloadScene class
// src/GoldPreloadScene.ts
import * as Phaser from 'phaser';
export class GoldPreloadScene extends Phaser.Scene {
constructor() {
super({ key: 'GoldPreloadScene' });
}
preload() {
// Load all assets your component needs
this.load.image('gold', 'img/gold.png');
this.load.image('silver', 'img/silver.png');
this.load.audio('coinSound', 'audio/coin.mp3');
}
}2๏ธโฃ Reference the PreloadScene in your demo
// src/Gold.demo.ts
import { Meta, Demo } from 'phaser-viewer';
import { Gold } from './Gold';
import { GoldPreloadScene } from './GoldPreloadScene';
import * as Phaser from 'phaser';
const meta = {
component: Gold,
title: 'Sprites/Gold',
description: 'Gold coin sprite with preloaded assets',
preloadScene: GoldPreloadScene // โ Add this line
} as const satisfies Meta<typeof Gold>;
export default meta;
interface GoldArgs {
x: number;
y: number;
}
export const BasicGold: Demo<typeof meta, GoldArgs> = {
name: 'Basic Gold Coin',
args: { x: 400, y: 300 },
create: (scene, args) => {
// Assets are already loaded and available!
// Type inference: args has x, y properties
return new Gold(scene, args.x, args.y);
}
};3๏ธโฃ Use assets in your component
// src/Gold.ts
export class Gold extends Phaser.GameObjects.Sprite {
constructor(scene: Phaser.Scene, x: number, y: number) {
// The 'gold' texture is already loaded by GoldPreloadScene
super(scene, x, y, 'gold');
scene.add.existing(this);
// You can also use other preloaded assets
this.setInteractive();
this.on('pointerdown', () => {
scene.sound.play('coinSound'); // Audio is also preloaded
});
}
}How it works
- PreloadScene starts first - Phaser Viewer automatically detects and runs your PreloadScene
- Assets are loaded - All assets defined in
preload()method are loaded into memory - ViewerScene launches - After loading completes, the viewer scene starts
- Assets are available - Your components can immediately use the preloaded assets
This ensures smooth component rendering without loading delays or missing asset errors.
๐๏ธ Scene Configuration
Phaser Viewer allows you to customize the canvas size and background color to match your project needs:
Basic Scene Configuration
// phaser-viewer.config.ts
import { PhaserViewerConfig } from 'phaser-viewer';
const config: PhaserViewerConfig = {
filePath: './src/**/*.demo.ts',
scene: {
width: 1200, // Custom canvas width
height: 800, // Custom canvas height
backgroundColor: '#1a1a2e' // Custom background color
}
};
export default config;Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
width |
number |
800 |
Canvas width in pixels |
height |
number |
600 |
Canvas height in pixels |
backgroundColor |
string |
'#222222' |
Background color in hex format |
displayScale |
number |
auto |
Display scaling factor (0.1-2.0, or omit for responsive auto-scaling) |
TypeScript Path Alias Support
Phaser Viewer automatically detects and resolves TypeScript path aliases from your tsconfig.json:
// tsconfig.json
{
"compilerOptions": {
"paths": {
"@/*": ["./src/*"],
"@/utils/*": ["./src/utils/*"]
}
}
}
// Your demo files can use path aliases
import { Button } from '@/components/Button';
import { COLORS } from '@/utils/colors';Configuration Options:
// phaser-viewer.config.ts
export default {
filePath: './src/**/*.demo.ts',
// Auto-detection is enabled by default
typescript: {
autoDetectPaths: true, // Default: true
tsconfigPath: './tsconfig.json' // Optional
},
// Or manually configure Vite aliases
vite: {
resolve: {
alias: [
{ find: '@/', replacement: '/path/to/src/' }
]
}
}
}๐ ๏ธ Commands
Development
npx phaser-viewer- Start development server with auto-detected configurationnpx phaser-viewer --port 3000- Start on custom portnpx phaser-viewer --help- Show help
Testing
npx phaser-viewer test- Run automated tests for all Play functions
Test Runner Features:
- Headless Testing: Runs components in headless browser environment
- Play Function Tests: Each Play function becomes a test unit with pass/fail results
- Error Details: Detailed error messages for failed tests
- Clean Output: Filtered results without browser noise
- Automatic Setup: Installs test dependencies automatically (vitest, playwright, @vitest/browser)
Configuration Detection:
- Automatically loads
phaser-viewer.config.tsorphaser-viewer.config.js - Generates default configuration file if none exists
- Supports scene customization (size, background color)
- Auto-adds
.phaser-viewer-temp/to.gitignorewhen present
๐ Development Grid System
Phaser Viewer includes a smart grid overlay system to help with precise component positioning during development:
Features
- Square Grid Cells: Automatically calculates near-square grid cells for better visual alignment
- Perfect Scene Coverage: Grid lines perfectly span your configured scene dimensions with no cutoff
- Adaptive Sizing: Automatically adjusts to different screen sizes (100px, 120px, 80px target cells)
- Always Visible: Grid appears in all demos for consistent development experience
How it Works
For a 1920ร1080 scene:
- Calculates 19ร11 divisions (targeting ~100px square cells)
- Creates cells of 101.1ร98.2px (nearly perfect squares)
- 18 vertical + 10 horizontal lines provide complete coverage
- No manual configuration needed - works automatically
The grid system is enabled by default and helps developers align components precisely during development without any setup required.
๐ License
MIT License
๐ค Contributing
Contributions, issues and feature requests are welcome! Feel free to check issues page or contribute to the GitHub repository.
Phaser 3 โข React โข TypeScript