Product Requirements & Architecture · v1 · 2026-06-16

The Way

An immersive browser experience of the life of Jesus Christ. This document is the single source of truth: every parameter of what exists today, and the proposed evolution from a scripted scroll into an open-exploration game.

● LIVE · the-way.pages.dev PlayCanvas 2.18 · React 19 · Vite 8 ◆ Pivot under review: scroll → open world 7 chapters · ~2.2 MB bundle

00Executive summary

What The Way is, in one screen.

The Way is a single-page WebGL experience that tells Christ's life across seven chapters — In the Beginning, the Manger, the Baptism, the Ministry, the Last Supper, the Cross, the Resurrection. Each chapter is a hand-built 3D scene (PlayCanvas) with its own camera framing, fog mood, ambient colour, particle systems, and a three-bus soundtrack. The player scrolls; scroll position drives chapter progression on rails.

Chapters
7
JS bundle
2.2 MB
App code (split)
13.5 KB
Audio assets present
0 / 21
The tension driving this PRD: the current model is a scripted scroll on rails — beautiful but linear and passive. The proposed direction (§7) is an open-exploration game where the player walks the world freely and discovers each station, informed by the "Advanced Game Development with AI" course.

01Status & open decisions

ItemStateDetail
Renders clean (0 errors)DONEPlayCanvas 2.x migration fixes applied across all 7 chapters
Live deployDONEthe-way.pages.dev (Cloudflare Pages)
Backed up to GitHubDONECosmicAndrew/the-way @ main
Code-split bundleDONEplaycanvas / react / vendor chunks
3-bus audio + save/restoreDONEnarration·score·ambience; localStorage
Audio asset filesPENDING — you21 mp3s (3 buses × 7 chapters) not yet produced
CrazyGames submissionPENDING — youneeds dev account + cover art + QA pass
Open-exploration pivotDECISIONscope & engine choice — see §7 / §9

— Current state · the full architecture —

02Stack & build

DependencyVersionRole
playcanvas^2.18.1WebGL 3D engine — all rendering
react / react-dom^19.2.6UI shell (overlays, HUD)
vite^8.0.0build + dev server (target esnext)
gsap^3.15.0overlay fade transitions
howler^2.2.4Web Audio — 3-bus soundtrack
tailwindcss^4.3.0utility CSS (HUD styling)

Boot: index.html loads the CrazyGames SDK v3 + fonts → src/main.jsx mounts React → src/App.jsx creates the PlayCanvas Application (FILLMODE_FILL_WINDOW, RESOLUTION_AUTO), instantiates AudioManager + SceneManager, and wires the SDK lifecycle (loadingStart→loadingStop→gameplayStart/Stop).

03Chapter data core game data

Each chapter = a scripture, a camera framing, a fog mood, an ambient colour, and a soundtrack. Source: src/data/chapters.js.

#SceneScriptureRefCamera pos → lookAtFog
0In the Beginning"In the beginning was the Word…"John 1:1(0,0,30)→(0,0,-20)none
1The Manger"For unto you is born this day…"Luke 2:11(0,3,15)→(0,.5,-5)linear 10–60
2The Baptism"This is my beloved Son…"Matt 3:17(0,2,12)→(0,-.5,-5)linear 15–80
3The Ministry"Blessed are the poor in spirit…"Matt 5:3(0,8,25)→(0,0,-10)linear 20–100
4The Last Supper"A new commandment I give…"John 13:34(0,2.5,10)→(0,1,-3)linear 5–30
5The Cross"For God so loved the world…"John 3:16(0,3,20)→(0,1,-5)exp 0.003
6The Resurrection"I am he that liveth, and was dead…"Rev 1:18(0,2,12)→(0,2,-5)none

Full ambient colours, fog colours and density values are in the Parameters appendix.

04Engine & particle systems

SceneManager lazy-loads 7 chapter builders, keeps one Entity root each (enabled on activation), and drives a LERP camera (CameraController, speed 0.025, FOV 55°, far 200).

Per-chapter scene construction
ChapterBuilds
1 · BeginningStarfield (800 pts, 60px radius) + nebula dust (30 planes)
2 · MangerGround, stable (box+roof), manger, star light (omni 2.5), ambient glow
3 · BaptismWater plane (ripple shader), dove particles, dir+fill lights, 12 rocks
4 · MinistryHeightfield terrain (sinusoid+radial), crowd (300), sun (dir 2.0)
5 · Last SupperTable+legs, 7 candles + candle lights (omni 0.6), walls
6 · CrossDark ground, 3 crosses, dim red dir light, red rain particles
7 · ResurrectionTomb panels + rolled stone, resurrection light (omni 8.0) + white glow (4.0)
Particle emitters
EmitterTypeConfig
starfieldcustom GL_POINTS mesh800 stars · additive · point-size by brightness · rotates
doveParticleSystem40 · sphere emitter r0.3 · life 3s · additive
crowdParticleSystem300 · box 25×2×25 · life 5s · normal blend
redRainParticleSystem500 · box 30×1×20 · life 4s · additive fade

05Audio — three independent buses

AudioManager (Howler). Each bus lazily creates a Howl per chapter; a missing file fails silently via onloaderror. 800 ms crossfade on chapter change, 400 ms mute fade.

BusVolumeLoopSource pattern
narration0.9one-shot/audio/narration/chapter-N.mp3
score0.4looped/audio/score/chapter-N.mp3
ambience0.3looped/audio/ambience/chapter-N.mp3
Gap: all 21 source files (3 buses × 7 chapters) are not yet produced — the engine runs silent until they're dropped into public/audio/.

06The scroll → chapter mechanic

  • A 700vh scroll-spacer = 7 chapters × 100 vh. Scroll position → progress (0–1).
  • useChapter maps progress → chapter index with a ~7% dead-zone between stops and a 1200 ms transition lock (prevents flashing).
  • useScrollProgress smooth-lerps 8%/frame and persists the fraction to localStorage["the-way:progress"] — restored on return.
  • useReducedMotion: when the OS requests reduced motion, the spacer collapses and chapter is pinned to 0 (static, accessible).
This is the on-rails constraint. The player cannot move — they can only advance or rewind a fixed timeline. Every scene is framed by a single scripted camera. That is exactly what §7 proposes to change.

07Build & deploy

ChunkSizeCached separately
playcanvas-*.js1.88 MByes — engine rarely changes
react-*.js190 KByes
vendor-*.js (gsap+howler)106 KByes
index-*.js (app)13.5 KBchanges per deploy
Chapter1–7.js~2 KB eachlazy, async

Deployed to Cloudflare Pagesthe-way.pages.dev. Source on GitHub CosmicAndrew/the-way @ main. GB course-archive videos are git-ignored (never pushed).


— Direction · where it's going —

08Open exploration proposed

From a timeline you scroll to a world you walk. Design principles drawn from your "Advanced Game Development with AI" course (Godot module + publishing lessons), re-mapped to the web stack.

Today — scroll on rails

  • Linear: chapter 0 → 6, one axis
  • Fixed scripted camera per scene
  • Player is a passenger
  • Discovery = scrolling further

Proposed — open world

  • Free movement through a continuous space
  • Player-controlled camera follows an avatar
  • Player is a pilgrim
  • Discovery = walking to a station & finding it

Design pattern (translated from the course's Godot lessons → PlayCanvas/web)

Course lesson (Godot)Web/PlayCanvas equivalent for The Way
Tilemaps & terrains (L15–17)A walkable 3D ground / path-network connecting the 7 stations as regions of one world
Camera system (L14)Third-person follow camera with boundaries (replaces the scripted LERP rail)
Input & movement (L18)WASD / on-screen joystick avatar control (keyboard + touch for mobile)
Collisions / physics layers (L16)Walkable vs. blocked zones so the pilgrim follows the path, not the void
Signals & Area2D triggers (L22)Proximity triggers at each station → reveal the scripture overlay + play that chapter's audio on arrival
AI enemy spawner (L25)Ambient life — other pilgrims, doves, crowds — populated dynamically, not hand-placed
Animated tilemaps (L21)Environmental motion: water at the Baptism, wind, candlelight — already partly built per chapter
Re-use, don't rebuild. The 7 chapters' scenes, lighting, particles and audio buses already exist and are good. The pivot mostly replaces the scroll-rail + scripted camera with an avatar + follow-camera + proximity triggers, and stitches the 7 scenes into one connected space (or a hub you travel out from). The scripture/overlay/audio systems stay.

The key engine question

The course teaches Godot; The Way is built in PlayCanvas (web). Two honest paths:

  • Stay PlayCanvas — keep all 7 finished scenes + the live web deploy + CrazyGames-web path. Add an avatar controller, follow camera, collision, and trigger volumes. Lowest waste, fastest to a playable open build.
  • Rebuild in Godot — follow the course 1:1, gain its tooling/export targets (web + Play Store + iOS), but discard the existing PlayCanvas scenes. Higher cost, broader platform reach.

09CrazyGames publishing from course L04

The text-rich publishing lesson, distilled to a concrete checklist.

SDK integration
  • SDK v3 already loaded in index.html; lifecycle wired in useCrazyGames.
  • Required events: loadingStart/Stop, gameplayStart/Stop ✅ wired.
  • Ads to add for monetization: interstitial (between chapters/stations) + rewarded (opt-in unlock, e.g. fast-travel to a station).
  • Save progress: use the CrazyGames Data module (our useCrazyGames.getData/setData already bridges to it + localStorage).
Required submission assets
AssetSpec
Landscape cover1920 × 1080 (16:9)
Portrait cover800 × 1200 (2:3)
Square cover800 × 800 (1:1)
Preview videoslandscape + portrait gameplay capture
Textcategory, tags, description, controls
Orientationportrait / landscape / both
QA gates (where most games fail)
  • No ads on startup or during exploration — bad UX is rejected.
  • Save system must actually persist (test in their iframe sandbox).
  • Must work well in fullscreen + at the declared orientation.
  • Test every integrated feature fires before submitting.
Strategy note from course L08: web publishing (CrazyGames) is capital-efficient — don't chase VC; prove DAU/retention first, then a publisher or Meta-ads scale follows.

10Gaps & decisions for you

DecisionOptions
Pivot scope(a) ship current scroll build to CrazyGames now, pivot later · (b) build the open-exploration version first, then ship
Engine(a) stay PlayCanvas — reuse all 7 scenes, fastest · (b) rebuild in Godot per the course — broader platforms, higher cost
World shape(a) one continuous walkable land linking all 7 · (b) a hub you travel out from to each station
Audioproduce 21 mp3s · or ship score-only · or AI-generate (course L27: ElevenLabs/Suno)
CrazyGames accountyou create the dev account + cover art; I wire SDK ads + QA

AParameters appendix raw values

Full chapter parameters (ambient + fog)
#ambientColor (r,g,b)fog typefog color / range / densityaudio
00.02, 0.02, 0.08nonechapter-1
10.08, 0.04, 0.01linear0.10,0.05,0.02 · 10→60chapter-2
20.02, 0.06, 0.10linear0.05,0.10,0.15 · 15→80chapter-3
30.08, 0.06, 0.04linear0.12,0.08,0.05 · 20→100chapter-4
40.10, 0.06, 0.02linear0.08,0.04,0.01 · 5→30chapter-5
50.06, 0.01, 0.01exponential0.02,0,0 · density 0.003chapter-6
60.30, 0.30, 0.35nonechapter-7
Camera, lighting & timing constants
  • Camera: FOV 55° · far clip 200 · clear (0.02,0.02,0.05) · LERP 0.025 · settle tol 0.01
  • Transition lock: 1200 ms · scroll lerp: 8%/frame · audio crossfade: 800 ms · mute fade: 400 ms
  • Scroll-spacer: 700vh · chapter dead-zone: ~7%
  • Bus volumes: narration 0.9 · score 0.4 · ambience 0.3
File tree
the-way/ ├─ index.html CrazyGames SDK v3 · React root ├─ vite.config.js advancedChunks: playcanvas|react|vendor ├─ src/ │ ├─ App.jsx PlayCanvas app + SceneManager + AudioManager │ ├─ data/chapters.js 7 chapters (scripture·camera·fog·audio) │ ├─ engine/ │ │ ├─ SceneManager.js activation · fog · camera lerp │ │ ├─ CameraController.js LERP interpolation │ │ ├─ chapters/Chapter1-7.js │ │ └─ particles/ starfield·dove·crowd·redRain │ ├─ audio/AudioManager.js Howler 3-bus │ ├─ hooks/ useScrollProgress·useChapter·useReducedMotion·useCrazyGames │ └─ ui/ Overlay·ProgressBar·MuteButton ├─ public/audio/ MISSING: 21 mp3s └─ PUBLISHING.md CrazyGames checklist