Observed since 20 Oct, 20:40 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Svelte 5 components and hooks for building Phaser 4 games
Svelte 5 components and hooks for building Phaser 4 games.
A modern rewrite of the original svelte-phaser (Svelte 3 / Phaser 3) using runes, snippets and callback props — targeting Svelte ^5 and Phaser ^4.
| Layer | What | Where it works |
|---|---|---|
Core (svelte-phaser/core, JSR: @easierbycode/svelte-phaser) | Pure TypeScript: context getters, event hooks, prop appliers, and compiler-free hooks (useSprite, useArcadePhysics, createGame, …). Reactivity flows out through svelte/store and in through per-step prop syncing — no runes, no .svelte files. | Anywhere — including installed from JSR, which only accepts JS/TS modules. |
Components (svelte-phaser) | .svelte components (<Game>, <Scene>, <Sprite>, …) built on the core, with fine-grained $effect prop bindings. | npm / workspace installs, where your bundler's Svelte plugin compiles library source. |
Why the split? JSR's module graph only accepts JavaScript/TypeScript —
.sveltefiles (and rune code, which needs the Svelte compiler) cannot be published there (jsr-io/jsr#861). The core layer is designed to be fully usable without the compiler, so the JSR package is a real, working game-binding API — not a stub.
From JSR (core API):
npx jsr add @easierbycode/svelte-phaser
From a workspace / local checkout (components + core) — note the unscoped
svelte-phaser name on the npm registry belongs to the original Svelte 3
project, so install this package by path:
npm install phaser svelte
npm i 5velte-ph4ser
(see examples/dino, which consumes it via file:../..)
<script lang="ts">
import Phaser from 'phaser'
import { Game, Scene, Sprite, Text } from 'svelte-phaser'
function preload(scene: Phaser.Scene) {
scene.load.image('player', 'assets/player.png')
}
</script>
<Game width={800} height={600} physics={{ default: 'arcade' }}>
<Scene key="main" {preload}>
{#snippet loading(progress)}
<Text x={400} y={300} text={`Loading ${Math.round(progress * 100)}%`} />
{/snippet}
<Sprite texture="player" x={400} y={300} />
</Scene>
</Game>
<Game> — creates the Phaser.Game. Accepts game config as props, a
booting snippet, and bind:instance.<Scene key> — creates and registers a Phaser.Scene. Accepts preload /
create / init callbacks, a loading snippet (receives progress 0–1),
and bind:instance.<Sprite>, <Text>, <TileSprite>, <Rectangle>, <Container> — game
objects. Props apply reactively; omitted props keep Phaser defaults.
Phaser events surface as callback props (onpointerdown,
onanimationcomplete, …).<ArcadePhysics> — enables an arcade body on the parent game object
(velocityX, bounce, collideWorldBounds, circle, …).<ArcadeCollider with={...} overlapOnly oncollide={...}> — collides the
parent game object with other objects, or with names (string targets are
matched against gameObject.name, including objects spawned later).<Spawner> — provides getSpawner() context so gameplay code can
imperatively spawn(Component, props) (bullets, pickups, …). Spawned
components receive an onDestroy prop to remove themselves.import {
getGame, getScene, getSpawner, getGameObject, getContainer,
onGameEvent, onSceneEvent, onInputEvent, onArcadePhysicsEvent,
} from 'svelte-phaser'
const scene = getScene()
onGameEvent('step', () => { /* runs every game step */ })
onInputEvent('pointerdown', () => { /* ... */ })
The hooks create the same objects without any library .svelte files. Pass a
props getter — it is re-read every game step and only changed values are
re-applied to Phaser:
<script lang="ts">
import { createGame, createScene, useSprite, useArcadePhysics }
from '@easierbycode/svelte-phaser'
// inside your own components:
const sprite = useSprite(() => ({ texture: 'player', x, y }))
useArcadePhysics(() => ({ velocityX, collideWorldBounds: true }), sprite)
</script>
createGame(config) → { game, booted } (booted is a store)createScene({ key, preload, create }) → { scene, loading, progress } (stores)createSpawner() → { spawn } — mounts components imperatively with the
current context (uses Svelte's public mount/unmount)useSprite / useText / useTileSprite / useRectangle / useContainer(getProps)useArcadePhysics(getProps, gameObject?), useArcadeCollider(props, gameObject?)applyGameObjectProps(...) etc. — the underlying idempotent prop appliersAll hooks must be called during component initialisation (they use Svelte context and lifecycle under the hood).
<Container>/<Rectangle>/<Text>, keyed
{#each} obstacle spawning, onGameEvent/onInputEvent, and reactive
theme/color customization. cd examples/dino && npm install && npm run dev.
The deployable full-stack version (Deno Deploy + PostgreSQL leaderboard)
lives at dino-sp.npx jsr publish from this directory publishes the core layer as
@easierbycode/svelte-phaser (see jsr.json). Run npm install here first
so the bare svelte/phaser specifiers type-check, then validate with
npx jsr publish --dry-run..svelte/TS source, which
@sveltejs/vite-plugin-svelte compiles in the consuming app (the svelte
export condition points at the source). The unscoped svelte-phaser npm
name is taken by the original project, so publishing to npm requires a
scoped rename (e.g. @easierbycode/svelte-phaser) in package.json.@sveltejs/vite-plugin-svelte)npm · 90 observations shown. Missing days are unknown.
| Date / source period | Value | Observed at |
|---|---|---|
| 2026-10-19 – 2026-10-19 | 0 | 2026-10-20T21:34:23.0536876Z |
| 2026-10-18 – 2026-10-18 | 11 | 2026-10-20T21:34:23.0536876Z |
| 2026-10-17 – 2026-10-17 | 9 | 2026-10-20T21:34:23.0536876Z |
| 2026-10-16 – 2026-10-16 | 6 | 2026-10-20T21:34:23.0536876Z |
| 2026-10-15 – 2026-10-15 | 0 | 2026-10-20T21:34:23.0536876Z |
| 2026-10-14 – 2026-10-14 | 0 | 2026-10-20T21:34:23.0536876Z |
| 2026-10-13 – 2026-10-13 | 0 | 2026-10-20T21:34:23.0536876Z |
| 2026-10-12 – 2026-10-12 | 4 | 2026-10-20T21:34:23.0536876Z |
| 2026-10-11 – 2026-10-11 | 6 | 2026-10-20T21:34:23.0536876Z |
| 2026-10-10 – 2026-10-10 | 7 | 2026-10-20T21:34:23.0536876Z |
| 2026-10-09 – 2026-10-09 | 5 | 2026-10-20T21:34:23.0536876Z |
| 2026-10-08 – 2026-10-08 | 7 | 2026-10-20T21:34:23.0536876Z |
| 2026-10-07 – 2026-10-07 | 4 | 2026-10-20T21:34:23.0536876Z |
| 2026-10-06 – 2026-10-06 | 0 | 2026-10-20T21:34:23.0536876Z |
| 2026-10-05 – 2026-10-05 | 0 | 2026-10-20T21:34:23.0536876Z |
| 2026-10-04 – 2026-10-04 | 5 | 2026-10-20T21:34:23.0536876Z |
| 2026-10-03 – 2026-10-03 | 7 | 2026-10-20T21:34:23.0536876Z |
| 2026-10-02 – 2026-10-02 | 5 | 2026-10-20T21:34:23.0536876Z |
| 2026-10-01 – 2026-10-01 | 5 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-30 – 2026-09-30 | 4 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-29 – 2026-09-29 | 5 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-28 – 2026-09-28 | 8 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-27 – 2026-09-27 | 8 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-26 – 2026-09-26 | 6 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-25 – 2026-09-25 | 9 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-24 – 2026-09-24 | 6 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-23 – 2026-09-23 | 7 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-22 – 2026-09-22 | 6 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-21 – 2026-09-21 | 6 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-20 – 2026-09-20 | 7 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-19 – 2026-09-19 | 9 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-18 – 2026-09-18 | 9 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-17 – 2026-09-17 | 45 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-16 – 2026-09-16 | 7 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-15 – 2026-09-15 | 0 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-14 – 2026-09-14 | 10 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-13 – 2026-09-13 | 8 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-12 – 2026-09-12 | 16 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-11 – 2026-09-11 | 7 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-10 – 2026-09-10 | 8 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-09 – 2026-09-09 | 12 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-08 – 2026-09-08 | 0 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-07 – 2026-09-07 | 0 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-06 – 2026-09-06 | 8 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-05 – 2026-09-05 | 9 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-04 – 2026-09-04 | 29 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-03 – 2026-09-03 | 0 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-02 – 2026-09-02 | 7 | 2026-10-20T21:34:23.0536876Z |
| 2026-09-01 – 2026-09-01 | 10 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-31 – 2026-08-31 | 7 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-30 – 2026-08-30 | 15 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-29 – 2026-08-29 | 11 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-28 – 2026-08-28 | 4 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-27 – 2026-08-27 | 6 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-26 – 2026-08-26 | 25 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-25 – 2026-08-25 | 31 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-24 – 2026-08-24 | 30 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-23 – 2026-08-23 | 39 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-22 – 2026-08-22 | 38 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-21 – 2026-08-21 | 45 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-20 – 2026-08-20 | 53 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-19 – 2026-08-19 | 155 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-18 – 2026-08-18 | 1 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-17 – 2026-08-17 | 3 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-16 – 2026-08-16 | 0 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-15 – 2026-08-15 | 4 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-14 – 2026-08-14 | 0 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-13 – 2026-08-13 | 0 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-12 – 2026-08-12 | 3 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-11 – 2026-08-11 | 1 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-10 – 2026-08-10 | 8 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-09 – 2026-08-09 | 1 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-08 – 2026-08-08 | 6 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-07 – 2026-08-07 | 3 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-06 – 2026-08-06 | 3 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-05 – 2026-08-05 | 2 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-04 – 2026-08-04 | 6 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-03 – 2026-08-03 | 0 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-02 – 2026-08-02 | 9 | 2026-10-20T21:34:23.0536876Z |
| 2026-08-01 – 2026-08-01 | 5 | 2026-10-20T21:34:23.0536876Z |
| 2026-07-31 – 2026-07-31 | 1 | 2026-10-20T21:34:23.0536876Z |
| 2026-07-30 – 2026-07-30 | 3 | 2026-10-20T21:34:23.0536876Z |
| 2026-07-29 – 2026-07-29 | 1 | 2026-10-20T21:34:23.0536876Z |
| 2026-07-28 – 2026-07-28 | 2 | 2026-10-20T21:34:23.0536876Z |
| 2026-07-27 – 2026-07-27 | 7 | 2026-10-20T21:34:23.0536876Z |
| 2026-07-26 – 2026-07-26 | 4 | 2026-10-20T21:34:23.0536876Z |
| 2026-07-25 – 2026-07-25 | 4 | 2026-10-20T21:34:23.0536876Z |
| 2026-07-24 – 2026-07-24 | 5 | 2026-10-20T21:34:23.0536876Z |
| 2026-07-23 – 2026-07-23 | 9 | 2026-10-20T21:34:23.0536876Z |
| 2026-07-22 – 2026-07-22 | 7 | 2026-10-20T21:34:23.0536876Z |
This describes our collected data; it is not a security assessment.
Shared repository data · GitHub
Observed since 20 Oct, 20:40 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:bbd520aa99b4f2fa16f84fc5591faf3c78c164843e105652bcd95c9be0f948c7