The Portal Keeper.
A little world with a reason to explore it. Turn two mirrors, follow the light and wake a sleeping observatory.
- The work
- Original browser puzzle
- My role
- Creative direction, game design & development
- Built with
- Three.js, React Three Fiber & TypeScript
- Year
- 2026

Make curiosity
playable.
I wanted the portfolio to offer a place to spend a little time, with something to discover through your own actions.
The room begins with an obvious relationship: a light source and a sleeping doorway. Brass instruments invite you to turn them. Every move changes a visible beam, so the scene itself helps explain the puzzle.
I kept the first world small enough to finish. One room, two mirrors and a patterned lens give the journey a clear beginning and a reward. The geometric plants and curious light-moth bring a little life to the machinery.
The beam tells
the truth.
Light follows the instruments. A ray meets each finite mirror surface and reflects according to its angle. The receiver only lights when that calculated path reaches it.
A reflection with somewhere else to go.
The first mirror catches the light, but its angle sends the reflection away from the second. The beam makes that consequence visible.
- Receiver
- Waiting
- Pattern
- Lens not placed
- Portal
- Sleeping
A live diagram using the game’s puzzle model. This example has its own state and leaves your saved game alone.
Discrete turns make the puzzle comfortable on touchscreens and with a keyboard. A bounded reflection loop keeps every configuration finite, including a beam that turns back toward another mirror.
The lens adds a second, visible rule: its asymmetric notch must match the receiver. Progress comes from understanding the objects, with graduated hints available when a player wants a nudge.
A door worth
opening.
When the pattern aligns, plants unfold and the portal reveals a floating garden. Stepping through gives the puzzle a destination beyond its solved state.

The same puzzle.
Two ways inside.
Separating the rules from the renderer made the experience easier to test, restore and offer in different forms.
A small, explicit state
Mirror angles, lens placement and orientation describe the puzzle. Both the 3D room and the playable flat diagram use that state and the same ray calculation. Undo restores earlier snapshots; a reset is reversible too.
Versioned browser saves are validated before restoration. Progress returns without an account, and an invalid save opens a fresh room.
Spend rendering work deliberately
The garden preview uses one bounded render texture. Device pixel ratio is capped, the scene renders on demand, and ambient motion rests when paused, hidden or outside the viewport. The game loads on its own route.
Original geometry gives the room its identity without a library of downloaded models. The small musical notes are synthesized only after sound is enabled.
Keep the player in control
Named HTML buttons provide a complete path through the puzzle. On phones, the controls sit beneath the artwork and focus scrolling accounts for the sticky scene. Text and shape carry clues alongside light and sound.
Reduced motion preserves the puzzle. If WebGL is unavailable or its context is lost, the same room continues in the flat view.
Your turn to
let the light in.
No timer. A few things to figure out. A world waiting on the other side.