Catalog npm
Back to packageRELEASE DETAILS

1.0.0

npm

5velte-ph4ser

Svelte 5 components and hooks for building Phaser 4 games

gamephasersveltewebgl
Published8 Jul 2026
Direct dependencies2
Transitive dependenciesNot calculated

README

Current package documentation

svelte-phaser

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.

The two layers

LayerWhatWhere 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 — .svelte files (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.

Install

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:../..)

Components example

<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>

Components

  • <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.

Context + events (both layers)

import {
  getGame, getScene, getSpawner, getGameObject, getContainer,
  onGameEvent, onSceneEvent, onInputEvent, onArcadePhysicsEvent,
} from 'svelte-phaser'

const scene = getScene()
onGameEvent('step', () => { /* runs every game step */ })
onInputEvent('pointerdown', () => { /* ... */ })

Hooks example (core / JSR API)

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 appliers

All hooks must be called during component initialisation (they use Svelte context and lifecycle under the hood).

Examples

  • examples/dino — a complete dino-runner game (a port of dino): runes-driven game state rendered declaratively with <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.
  • mario-sp

Publishing

  • JSR: 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.
  • npm: the package ships uncompiled .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.

Requirements

  • svelte ^5.0
  • phaser ^4.0
  • For the component layer: a bundler with the Svelte plugin (e.g. Vite + @sveltejs/vite-plugin-svelte)

Downloads & popularity

1downloads
7-day window · source-reported counts20 Oct 2026
10.50
2026-10-20: 1 · observed 2026-10-20T21:34:24.4849505Z
20 Oct20 Oct

npm · 1 observations shown. Missing days are unknown.

View observed values
Date / source periodValueObserved at
2026-10-2012026-10-20T21:34:24.4849505Z

Declared dependencies 4

Native requirements
2 direct targetsNot calculated transitive count
Package / targetRequirementRelationship
phaser
Environment
{
  "local_name": "phaser",
  "alias": false,
  "peer_metadata": null
}
^4.0.0development
svelte
Environment
{
  "local_name": "svelte",
  "alias": false,
  "peer_metadata": null
}
^5.0.0development
phaser
Environment
{
  "local_name": "phaser",
  "alias": false,
  "peer_metadata": null
}
^4.0.0peer
svelte
Environment
{
  "local_name": "svelte",
  "alias": false,
  "peer_metadata": null
}
^5.0.0peer

Distribution files

1 collected
Distribution 1

Source distribution

Source file
Checksums from source
{
  "shasum": "9c4094c26dee1638d47a9db9e8edc195a4854d68",
  "tarball": "https://registry.npmjs.org/5velte-ph4ser/-/5velte-ph4ser-1.0.0.tgz",
  "fileCount": 25,
  "integrity": "sha512-EktfL/F3HcNci+x/QH3JF9Lnvx8LMfA4rLTuerMJT4ZzF63uzPrZ1UGMJDToEsk5SYpFMVb30R2axcVgzR3STA==",
  "signatures": [
    {
      "sig": "MEQCIFny5FjbpqkOkTCXSz8nMqnaZ86sV7zqXBjXsd4vxDD6AiB1KTL4Br2RJJpoRuCICwtu8CTMm9IQnQerynd/8ZJS0A==",
      "keyid": "SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"
    }
  ],
  "unpackedSize": 62615
}

Repository

PENDING
easierbycode/svelte-phaser

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 20:40 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package_version:670fd0e4d53520fa75c3f0a06a302cda06feef2c8d0e08b0b00515e4f05ed741

Other collected versions

1.0.219 Aug1.0.119 JulView all collected versions →