Backend API service for the SCEA Destinations platform in PlayStation Home — the GDO layer (Quest Manager, Activity Board, Central Dispatch, cross-game quest tracking) and Wardrobe Wars.
- Publisher Registry (
/publisher/*)- Publisher discovery, names, IDs, and token authentication (e.g. Publisher 12 = RC Rally).
- Space Quests & Catalogs (
/user/space/*)- Space-specific quest catalogs, metadata, loyalty, and start conditions.
- Completed quest status and task reconstruction (
<task id="1"><status>c</status></task>). - Scene entry metrics (visited count & cumulative time spent per space).
- Quest Groups & Tasks (
/user/group/*)- Group descriptions, space mappings (
destinations_indie, etc.), and exit logic blocks.
- Group descriptions, space mappings (
- Game Telemetry & Bit-Compression (
/user/game/*)- Per-game stats, track lap times, custom vehicle loadouts, and 64-bit BigInt compressed objective/parts bitmasks.
- Central Dispatch Manager (
/user/sync/*)- Central Dispatch (CDM) periodic player stats and quest synchronization handler.
- Leaderboards (
/leaderboard/*)- Global and space leaderboards with ascending/descending sorting for race and activity times.
- Wardrobe Wars (
/WardrobeWars/*) — VEEMEE's avatar fashion contest at the SCEA Marketplace kiosk: entry photos, 1-10 voting, and the daily/weekly/monthly prize ladder.
- ⚡ Bun & Hono: Ultra-fast HTTP engine written in TypeScript.
- 💾 SQLite Persistence: Powered by Drizzle ORM and
bun:sqlitewith auto-initializing publisher-agnostic tables. - 📜 Fast XML Builders: Robust XML generation via
fast-xml-parserwith structured responses matching original SCEA Destinations schema. - 🪵 Observability: LogLayer, Pino pretty logging, and OpenTelemetry OTLP tracing / log exporting.
Route the following domains through your DNS / reverse proxy to this container (default port 30088):
| Domain | Protocol | Purpose |
|---|---|---|
destinations.destinationhome.live |
HTTP | Destinations GDO endpoints (/publisher/*, /user/space/*, /user/game/*, /user/group/*, /user/sync/*, /leaderboard/*) |
ww-prod.destinations.scea.com |
HTTP | Wardrobe Wars, unauthenticated calls (podium.php, podium_score.php, screen.php, photo-p2.php, Images/*) |
ww-prod-sec.destinations.scea.com |
HTTPS | Wardrobe Wars, bracelet-authenticated calls (verify.php, podium_vote.php, reward.php, photo-p1.php) |
Both
ww-prod*hostnames are hard-coded in the minigame object and must reach this service. The HTTPS one needs a certificate chaining to a CA the Home client trusts.
| Variable | Default | Purpose |
|---|---|---|
WW_PHOTO_ROOT |
data/wardrobewars/photos |
Where submitted entry photos are stored, laid out as <YYYY-MM-DD>/<psnid>-<HH-MM-SS>.dds |
WW_PRIZE_TILE_DIR |
data/wardrobewars/prizes |
Prize thumbnails named <OBJECT-GUID>.dds; missing ones 404 |
WW_SEED_DIR |
(unset) | Point at the CDN's WardrobeWars/Images tree to import the surviving 2012 entries and prize art on first run |
WW_TIMEZONE |
America/Los_Angeles |
Timezone the contest day/week/month boundaries are measured in |
WW_THEMES |
(built-in list) | |-separated themes, one per contest week |
WW_MIN_VOTES_TO_WIN |
1 |
Votes an entry needs before it can win a period |
WW_SHOWCASE_WHEN_EMPTY |
true |
Show the most recent day's entries when today has none yet |
WW_PODIUM_REFRESH / WW_SCREEN_DISPLAY / WW_KIOSK_SCORE_REFRESH / WW_PODIUM_SCORE_REFRESH |
180 / 15 / 5 / 10 |
Client-side timers, handed back by verify.php |
-
Install dependencies:
bun install
-
Start the development server:
bun run dev
-
Run unit tests & linting:
bun test bun run lint
Run with Docker Compose:
docker compose up -dThe service will start listening on port 30088.
This project is licensed under the GNU Affero General Public License v3.0 - see the LICENSE file for details.