---
id: world-map-and-portals/005
title: The authored world of Spellgrove, its loader, and the public map endpoint
epic: world-map-and-portals
state: done
priority: 2
blocked_by: []
estimate: M
created: 2026-08-15
updated: 2026-08-18
claimed_by: null
claimed_at: null
delivers: []
review_artifact: land-of-lor/game/content/spellgrove.world.json
---

## What landed

- **`game/content/spellgrove.world.json`** — nine areas and ten portals, the design's approved
  topology verbatim, including the deliberate hard cases: a one-way into a dead end, a
  `home_area` portal, hidden portals, an area you can see but not enter, and a nested room.
  Areas and portals reference each other by slug and the file carries no database ids, which is
  what lets the same file load into a local database and production independently.
- **`npm run load-world`** — idempotent, keyed on slug, validating the whole graph (every
  endpoint resolves, no two portals share a cell *including* two-way return legs, every cell
  inside its area's grid) before it touches the database. Rows with a NULL slug — players' own
  worlds and homes — are never touched, and authored rows missing from the file survive unless
  `--prune` is passed.
- **`GET /director/world-map.json`** — the director's first unauthenticated read surface. Both
  visibility passes happen server-side: a logged-out caller gets public areas in full, private
  ones **fogged** to a position and an opaque id (no name, no slug, no size, no rules, no
  owner), and hidden portals not at all. 60s in-process memo, ETag, and permissive CORS with a
  `PUBLIC_MAP_ALLOWED_ORIGINS` override.
- **`join_public_world` lands players in the authored Village**, falling back to the old
  name-based find-or-create when the slug isn't present, so an unseeded database still works.

## Verification

`public-map.test.ts` asserts a logged-out response contains none of the private areas' names,
slugs, sizes, rules or database ids anywhere in the body, and that hidden portals are absent.
`loadWorldContent.test.ts` loads the committed file twice and asserts identical row ids.