This is a submission for the Sanity Challenge, Path Two: Vibe-Code Something Strange.
What I Built
Apex Bestiary is an interactive archive of cryptid sightings. Reports appear as signals on a world map, but the map is only the beginning of the investigation. Each signal opens a dossier with the witness account, an illustration, observed traits, a credibility index, and the folklore behind the entity.
The entity archive gives every creature a full profile: its physical description, defining traits, region, origin story, threat assessment, and a timeline of filed sightings. Selecting a report compares the witness’s observations with the traits recorded in the creature’s canonical profile.
I also added a connection board for following reports that might relate to one another. It distinguishes two kinds of links:
- Archived links come from explicit references between sighting documents in Sanity.
- Possible matches are leads calculated from reports of the same entity that share an observed trait and occurred within 100 km and 365 days of each other.
A possible match is a reason to investigate, not proof that two witnesses saw the same thing. Keeping those categories separate makes the board useful without overstating the evidence.
Visitors can file their own report by choosing a location on a map, describing the encounter, adding observed traits and environmental conditions, and optionally attaching an audio testimony. New reports enter the archive for review with a calculated credibility index.
Demo
No login is needed to explore. For a quick tour, start on the field map and select Random transmission. Open the entity’s complete profile from its dossier, choose a report in the sighting timeline, and follow its links in the connection board.
Video
Screenshots
Code and Content Model
The frontend uses Astro, React, Leaflet, and OpenStreetMap. Sanity Content Lake and Studio hold the archive’s structured content. The application is deployed on Vercel, which also runs the server-side route for submitting reports.
The core model has three document types:
Creature ── referenced by ──> Sighting <── references ── Region
│
└── corroboratedBy[] ──> Sighting
A creature stores its illustration, names, physical description, distinctive traits, folklore origin, and threat level. A region stores geographic and folklore context. A sighting stores the location, witness account, observed traits, conditions, review status, credibility index, optional audio, and references to corroborating reports.
GROQ projections resolve the creature and region associated with a sighting. Sanity listeners let the map and archive react when reports change. The reporting route creates a sighting and writes its calculated credibility score back to Sanity. The connection board uses the stored references for archived links and computes possible matches separately in the frontend.
My Build Process
1. Build relationships before drawing pins
A location alone tells very little of a story. Modeling creatures, regions, and sightings as related documents let each map signal open a meaningful case file. The same relationships now power the entity profiles, sighting timelines, and connection board.
2. Give the map its own visual language
I designed the map as a field instrument: dark cartography, animated signals, scanning details, and controls for locating or discovering a case. Selecting a signal moves the map toward it and opens a dossier, so the geography and the account remain connected.
During testing, an earlier vector-style map provider was blocked by a content filter. The reports still appeared, but the underlying map did not. I switched to Leaflet with OpenStreetMap raster tiles and added a loading state tied to the tile layer. That failure improved the reliability of the experience.
3. Turn the bestiary into an investigation
The archive grew from a collection of creature descriptions into a place where reports can be examined. Visitors can search and filter entities, move between profiles, read sightings in chronological order, compare observed and canonical traits, and jump from a report back to its location on the map.
The connection board extends that investigation. It draws reports and their links on a map while clearly labeling inferred leads. The interface uses a shared header and a more legible type scale across the map, archive, and report form.
4. Use sound only when the visitor asks for it
The map’s Field receiver uses Web Audio to synthesize a subtle signal after a visitor turns it on. The entity archive has a separate, optional background track. Neither starts automatically.
Music track: Abyss by Tetuano
Source: https://freetouse.com/music
No Copyright Music (Free Download)
5. Build, inspect, and revise
I built this with Codex as a coding partner through a series of focused iterations. The work included the content model, live map, report flow, illustrated dossiers, entity archive, trait comparison, connection board, and visual consistency across pages. Testing in the browser exposed practical issues, from missing map tiles to cramped typography, that shaped the final interface.
Sanity Project Details
-
Sanity project ID:
en0s05um -
Dataset:
bestiary
The schema definitions are public in backend/schemaTypes. They are the core of the project: the frontend is designed around the relationships and editorial context in those documents, rather than using Sanity as a generic key-value store.
Agent Session
What I learned
Structured content made the archive feel alive. A report can lead to an entity, a region, a witness account, a set of traits, and another report. Sanity provides those relationships; the interface turns them into an investigation.
The most useful design decision was to show where the evidence ends. An explicit case reference and a nearby report with similar traits are both interesting, but they mean different things. Making that distinction visible gives visitors room to explore without presenting a theory as a fact.



Top comments (0)