What This Thing Actually Is

Gus Was A Friendly Ghost is a small indie project — part ambient audio player, part ARG-style walkthrough tool, part interactive fiction engine. It came out of a two-person team in 2023, and it's one of those things that looks simple on the surface but has enough moving pieces under the hood to make it annoying if you don't know how it ticks. The core idea: you run a local instance, feed it your own asset library (audio files, scanned images, whatever), and it generates a "ghost story" mode where audio plays, text unlocks, and certain conditions trigger events. It's designed to feel like a haunted house simulation, but it's more of a framework than a finished product. The download sits on GitHub. The repo is called something like gus-friendly-ghost. Clone it, then run npm install. That part is straightforward. Where people get stuck is the asset pipeline. The README mentions supported formats, but it doesn't clearly explain that the audio analyzer only processes WAV and OGG files natively — MP3s will silently fail and you won't get any error message, which is frustrating. I spent about three hours once trying to debug what I thought was a broken event trigger, only to realize the audio file had been imported as an MP3 and the system just skipped it entirely. The workaround was running every file through a quick ffmpeg conversion first: ffmpeg -i input.mp3 -ar 44100 -ac 2 output.wav. Do that before dropping files into your asset folder and you save yourself a lot of head-scratching. The config file is JSON-based and lives at the root. You need to set up scenes, trigger zones, and audio mappings. Here's the thing most people miss: the trigger system uses distance-based proximity calculations, not collision detection. That means if you place a trigger zone ten meters from a speaker, the system calculates whether your virtual "listener" is close enough based on a radial distance check. It's simpler than proper physics, which is both a blessing and a curse. The blessing is performance — my laptop ran it fine at 60fps with twelve active scenes. The curse is that if you want tight, room-scale interaction, you have to manually tune the trigger radii per scene instead of relying on the engine to figure it out. Default radii are too generous for small rooms.

Building Your First Scene

I'll walk through what I consider the minimum viable setup. Start by creating a scenes/ folder in your project root. Each scene gets its own subfolder. Inside each folder, you need three things: a scene.json manifest, an audio/ subfolder, and optionally an images/ subfolder for visual backdrops. The scene.json structure looks like this: { "name": "Hallway", "ambient_track": "hallway_loop.wav", "trigger_zones": [{"id": "door_open", "radius": 3.5, "position": {"x": 12.0, "y": 0.0, "z": 8.0}, "on_enter": ["play_sfx_door_creak", "unlock_text_01"]}, {"id": "bookshelf", "radius": 2.0, "position": {"x": 12.0, "y": 0.0, "z": 3.0}, "on_enter": ["play_sfx_scratching", "unlock_text_02"]}], "unlocked_texts": [{"id": "unlock_text_01", "content": "The doorframe is old. You can see the scratches near the bottom."}, {"id": "unlock_text_02", "content": "Dust on the shelf. Something moved it."}] }

Note the position values. They're in meters relative to your world origin, not pixels or grid units. If you mix up coordinate systems between scenes, the triggers won't fire correctly. I learned that the hard way when porting a scene from the demo template — the coordinates were in centimeters, not meters, and none of my triggers activated until I divided everything by 100.

Get the Full Details

Gus Was A Friendly Ghost by Jane Thayer | Read by Grandmama - YouTube
Gus Was A Friendly Ghost by Jane Thayer | Read by Grandmama - YouTube

Common Pitfalls

There are three issues that come up repeatedly. First, the audio crossfade system. Gus blends between tracks when you move between trigger zones, but the crossfade duration is fixed at 1.5 seconds globally. You can't override it per-scene. If you're doing fast-moving scenes with tight audio cues, the crossfade will drown out sudden sounds. There's no built-in bypass. The workaround I use is to set the crossfade source and destination tracks to overlap for at least two seconds so the bleed doesn't cut off mid-word. Second, the text unlock system caches unlocks globally. Once a text is unlocked, it stays unlocked even after you restart. This is intentional design for replayability, but it breaks testing. I had to add a --hard-reset flag to my launch script to clear the cache between test runs. Without it, you're forever chasing phantom unlocks that you already triggered an hour ago. Third, there's no multiplayer or network mode. People ask about this because the ARG elements suggest it could be shared. It can't. Each instance is local-only. If you want a shared experience, you have to run multiple instances and sync them manually, which is not trivial. I once tried coordinating three separate instances across a local network for a LAN event. The audio drift between machines was about 400 milliseconds per session, and it made everything feel broken. Don't bother with the sync hack. It's not worth it.

Performance Notes

The engine is Node-based, which means it's not going to run smoothly on anything older than a mid-2010s machine. I've seen it choke on systems with less than 8GB RAM when you have more than five scenes loaded simultaneously. The CPU usage spikes during audio decoding, especially with OGG files. If you're building a dense scene with a lot of overlapping audio layers, convert everything to WAV and keep the sample rate at 44100 Hz. Higher rates don't improve perceived quality in this engine — they just slow things down because the decoder wasn't optimized for 48000 Hz playback. One optimization that actually works: disable the image backdrop rendering if you don't need it. The image loader is single-threaded and will block the main loop for about 200 milliseconds per large PNG. I cut my average frame time in half by removing backdrops from most scenes and switching to pure audio-only triggers. It changes the feel of the experience, but performance-wise it's the single biggest win you can get.

Should You Use It?

If you're looking for a polished, out-of-the-box haunted experience, this isn't it. It's a framework. You build the experience yourself. The documentation is sparse, the community is small, and support is essentially "submit an issue and hope." But if you're into interactive audio design, amateur horror game development, or just want to tinker with a system that does something unusual, it's worth the effort. I've been running it for about two years across six different projects. It handles the core loop well — audio triggering, text unlocking, spatial awareness — but anything beyond that requires you to modify the source or accept gaps. The best use case I've found is combining it with a simple VR rig or even a phone gyroscope app to create location-based audio experiences. Drop it in a physical space, map the trigger zones to real-world distances, and you get something that feels genuinely unsettling because the audio responds to your actual movement. That's where this project shines. Everything else is just good enough to be useful and broken enough to be interesting.

"Gus Was A Friendly Ghost" Photographic Print for Sale by SaulsBoutique | Redbubble
"Gus Was A Friendly Ghost" Photographic Print for Sale by SaulsBoutique | Redbubble