Docs

Codex looks like one website; underneath, it is a pnpm workspace with a shared core package and per-game packages. This page walks through that shape, the Warframe import path from Armory, and the deployment footguns that only appear at 2 a.m. when SQLite paths disagree.

Monorepo map

At the repository root, package.json declares workspaces such as:

  • packages/core - shared server/client glue, routing assumptions, database access patterns, auth middleware concepts.
  • packages/games/warframe - Warframe-specific worksheets, rows, and logic.
  • packages/games/epic7 - Epic Seven’s curated collection model.

The root app builds the server bundle and Vite client after the packages compile. If your CI only runs pnpm install at the root, you are fine; if someone tries to “just build the client” from a nested folder without filters, send them back to the README with kindness and a link to pnpm run build.

codex/
  packages/
    core/                 # @codex/core
    games/
      warframe/           # @codex/game-warframe
      epic7/              # @codex/game-epic7
  server/                 # Express host + sync services
  client/                 # React UI

Warframe: why Codex cares about Armory’s disk

Warframe support is not a second independent encyclopedia. Codex reads Armory’s SQLite database (ARMORY_DB_PATH) to understand which names exist in which worksheet buckets - warframes, primaries, companions, modular weapons, and so on. Sync code compares that ground truth to what is already stored in Codex’s own Warframe tables and updates rows accordingly.

If ARMORY_DB_PATH points at yesterday’s file, Codex cannot invent today’s items. Operationally, that means Armory refresh and Codex sync are paired rituals, not independent cron jobs you can set and forget without monitoring.

Epic Seven: curation over crawling

Epic Seven’s package trades the “live API” fantasy for a list that humans can reason about. That is a product choice with engineering consequences: releases are gated on data updates in the package, not on a third-party uptime dashboard.

When you document Epic Seven for the website, emphasize accuracy and stability over freshness bragging rights. Players forgive a day delay; they do not forgive wrong awakenings.

Authentication: stricter than you might guess

AUTH_SERVICE_URL must be a valid https URL with a hostname. Codex’s config throws at startup if you try to sneak http://localhost into production-shaped validation paths-check packages/core/src/config.ts for the exact guardrails.

The login redirect pattern matches the other apps: build a next URL on Codex’s public origin, send the user to Auth’s /login, then resume where they left off.

GAME_HOSTS and multi-game routing

If you operate multiple game experiences behind different hostnames, GAME_HOSTS lets you map host → gameId for routing. This is one of those settings that stays empty until suddenly it is not - usually the day you add a second public hostname for SEO or regional reasons.

Example shape (illustrative, not copy-paste law):

GAME_HOSTS=codex.example.com=warframe, epic.example.com=epic7

Read @codex/core config in the repository for delimiter rules and normalization - blogs go out of date; code does not.

Shared SQLite: absolute paths, shared volumes

The README is blunt for good reason: CENTRAL_DB_PATH and ARMORY_DB_PATH must be absolute. Container-era developers love relative paths that “work on my laptop”; SQLite on a network filesystem that does not honor locking loves them even more, in the way a bonfire loves loose papers.

Deployment recipe that tends to work:

  1. Mount a single volume (or two coordinated volumes) at known mount points.
  2. Set absolute paths inside the container to those mount points.
  3. Ensure only one writer performs schema migrations at a time.

Codex opens the central DB in WAL mode. That is excellent for concurrency within a single host; it is not a distributed database story.

CORS and ALLOWED_APP_ORIGINS

If you front Codex with another origin - for example, a marketing site calling APIs - ALLOWED_APP_ORIGINS participates in server CORS configuration. Empty is fine until it is not; keep a short internal note of which origins are allowed in prod and why.

Building and validating like you mean it

pnpm run build packages + typecheck + server + client
pnpm run validate format, lint, typecheck, tests

pnpm run build is the “did we ship a coherent workspace?” button. validate is the “would CI let me merge?” button. Using both before tagging saves everyone the emotional cost of a Friday revert.

Testing philosophy

Vitest runs across the workspace. For Codex, prioritize tests around sync edge cases, auth middleware assumptions, and anything that parses user-visible worksheet state. Those are the places where “it rendered” and “it was correct” diverge.