---
id: building-the-game/001
title: One repo, one site: the workspace merged into land-of-lor, the site on spellgrove.com
epic: building-the-game
state: review
priority: 1
blocked_by: []
estimate: L
created: 2026-09-03
updated: 2026-09-03
claimed_by: null
claimed_at: null
delivers: []
review_artifact: workshop/epics/building-the-game/tasks/001-migration-and-domain.md
---

## What was done (2026-09-03, laptop session)

- **The `lor-workspace` repo merged into `land-of-lor`** with `git subtree add` (history kept):
  its root became `workshop/` (epics, deliverables, decisions, brand, historic-docs,
  `marketing/` — was `marketing-and-communication/` — `WHY.md`, its `README.md` and
  `CLAUDE.md`); its `site/` became `site/` at the repo root; `godot-setup-for-pocs/` became
  `tools/godot-setup/`. `setup-subrepos.sh`, `deploy-watch.sh`, `ssh_droplet.py` and the
  disabled GitHub workflow were dropped from the moved tree. The workspace repo itself is now a
  thin coordinator: README, a pointer `CLAUDE.md`, `setup-subrepos.sh`, `.gitignore`.
- **Every path the site reads re-pointed** (`astro.config.mjs`, `content.config.ts`,
  `brand.ts`, `taskPath.ts`, `about`, `PICKUP.md.ts`, `design-brief.md.ts`,
  `validate-epics.mjs`); `repoLink.ts` maps the old workspace roots onto the new folders so
  older epic prose keeps linking; `export-web.sh`'s embed path follows the site; the build
  output default is `site/dist` (the droplet sets `OUT_DIR`).
- **Nav:** "The World" became the **Building the Game** submenu — The Building Blocks
  (`/building`, the landing), The World, and Elements / Creatures marked *soon*.
- **The site is built on the game droplet**: content checkout `/opt/lor/content` (origin =
  GitHub over the deploy key `~lor/.ssh/lor_deploy_key`), `/opt/lor/bin/site-build.sh` run by
  `lor-site-build.timer` every 2 minutes (fetch, compare origin/master to the last-built SHA,
  ff-only pull, `npm ci && npm run build` into `/var/www/spellgrove.new`, swap; log at
  `/opt/lor/site-build.log`; `--force` builds the local checkout even when the fetch fails).
  Caddy serves `spellgrove.com` (site + `/director/` + `/game/<port>` + `/download/`),
  `www` redirects to the apex, `staging` answers a placeholder. A 2 GB swapfile was added
  (the box had none; the Astro build wants headroom). Certificates issued by Let's Encrypt
  on first request.
- **The old host** `lor.kris.ai-task-runner.com` now serves a redirect page to spellgrove.com
  at every path that existed (its final build is archived on that host as
  `/root/lor-public-site-final-20260903.tar.gz`); the host cron entry `lor-deploy-once` was
  removed.
- **DNS:** Kris set the three A records (`@`, `www`, `staging` → 209.38.29.22) on Namecheap.
- Also folded in: the local authoring hub (`tools/hub-ui/index.html`) and hexagram 2
  renamed **Dirt**.

## Waiting on Kris

- **The deploy key.** `~lor/.ssh/lor_deploy_key.pub` on the droplet (label
  `lor-game-server-01-deploy-readonly`) must be added at
  github.com/krisrandall/land-of-lor/settings/keys **with write access**. Until then the
  timer's fetch fails (logged, harmless) and a rebuild needs a bundle pushed by hand plus
  `site-build.sh --force`; after it, every push to `master` is live within two minutes.

## Verify

```bash
ssh -i .secrets/lor_runner_key lor@209.38.29.22 tail -5 /opt/lor/site-build.log   # "build OK"
curl -sI https://spellgrove.com/ https://spellgrove.com/building https://spellgrove.com/world | grep HTTP
curl -sI https://www.spellgrove.com/ | grep -i location                           # -> https://spellgrove.com/
curl -s https://lor.kris.ai-task-runner.com/ | grep -o 'spellgrove.com'           # the redirect
```

## Assumptions

- `workshop/` as the folder name for the merged workspace; `site/` at the top level because it
  is the game's face now, not the workshop's.
- Older epic prose keeps its workspace-relative paths; the site's link mapper translates them
  rather than rewriting history.
- The game client keeps `lor-server.cocreations.com.au` for now (server-architecture/018).