Skip to content

Repository files navigation

Yell

A place-rooted, ephemeral public broadcast built on a real-time geographically partitioned map and Cloudflare Durable Objects.

The prototype opens on a living world view and travels globally as one continuous map. The world view subscribes to all 32 top-level 45° regions; finer zoom levels use a 3 × 3 group at the appropriate spatial scale. Those region summaries become screen-space MapLibre clusters rather than visible cell markers, then give way to individual people backed by yells in 0.05° cells. Adjacent levels crossfade so there is no separate travel mode. Each yell has one canonical Durable Object owner with SQLite storage, WebSocket Hibernation, and alarm-driven expiry.

Prerequisites

  • Node.js 20.19 or newer
  • npm 10 or newer
  • A Cloudflare account only when deploying

Commands

npm install
npm run dev
npm run simulate
npm test
npm run typecheck
npm run build
npm run deploy

npm run dev starts Vite at http://localhost:5173 and Wrangler at http://localhost:8787. Vite proxies /api, /cells, /regions, and /yells to the Worker. Both ports are fixed so a duplicate dev session fails immediately instead of sharing local Durable Object storage.

Individual yells render through native MapLibre WebGL circle layers. A compact keyboard and screen-reader surface exposes the same visible yells without duplicating their visual DOM markers.

npm run simulate starts 128 named local activity agents across the world. Eighty percent begin near population-weighted cities, with a softened weighting that creates stronger big-city density without collapsing all activity into megacities. The remaining agents are sampled uniformly across inhabited land, keeping the long tail of the map alive. Agents random-walk locally and write multilingual yells through the real Worker WebSocket route every 8–18 seconds. Some agents then discover a recent yell after a short delay and leave a lightweight reaction or multilingual reply through its real conversation room, so activity grows as a paced conversation rather than one creation burst. Run it alongside npm run dev; press Ctrl+C to stop it. Normal output reports acknowledged yell and response throughput every ten seconds; add --verbose for every yell. Configuration is optional:

npm run simulate -- --agents 256 --interval 5:12
npm run simulate -- --agents 1200 --rate 60 --duration 60

--rate produces one globally paced stream instead of a burst from every agent, and --duration makes a stress run bounded. The simulator counts a yell only after the owning cell broadcasts its acknowledgement and counts a response only after its room acknowledges it. It refuses non-localhost targets, reuses producer connections by owning cell, and does not model the browser's hierarchical read subscriptions.

The simulator's city metadata comes from the CC BY 4.0 world-cities-json dataset, sourced from SimpleMaps. Land sampling uses Natural Earth data through world-atlas.

npm run deploy builds the web client and deploys the Worker. Static web hosting is deliberately not selected in this foundation; apps/web/dist can later be deployed to Cloudflare Pages or served by the Worker once that hosting choice is made.

Repository guide

  • AGENTS.md records persistent implementation guidance, including the official source policy for Durable Objects.
  • PROJECT_BRIEF.md defines the product boundary.
  • ARCHITECTURE.md records data flow and trade-offs.
  • packages/shared owns protocol and geographic indexing code.
  • apps/worker owns the Worker entry point plus the MapCell, MapRegion, and per-yell YellRoom Durable Objects.
  • apps/web owns the React/Vite browser client.

The canonical yell cell is 0.05°; aggregate parents are 0.5°, , and 45°. These are prototype configuration and can be replaced by an H3-backed hierarchy later.

Try the prototype

  1. Run npm run dev.
  2. Open http://localhost:5173 in two tabs.
  3. Select Yell from your location, allow location access, optionally choose a device-local display name, and post a short message from the privacy-softened location.
  4. Select the marker in either tab to see who yelled, its message, and its remaining lifetime. React with a heart, wave, or spark, or send a short reply; the conversation updates live across tabs and disappears with the yell.
  5. The creating device sees a delete action for its yell and for each of its replies. Private deletion capabilities are never broadcast. Deleting a yell closes its room immediately.
  6. Optionally run npm run simulate in another terminal to make the map come alive.

The prototype uses OpenFreeMap's Positron vector style, rendered by MapLibre with automatic OpenFreeMap, OpenMapTiles, and OpenStreetMap attribution. The public OpenFreeMap service needs no API key and is suitable for this experiment, but it offers no SLA; choose a supported or self-hosted provider before a production launch.

About

A map-based social network POC built on a real-time geographically partitioned map and Cloudflare Durable Objects.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages