Better Intra — Agent Guide

Quick start

npm install
npm run build:firefox   # single production build for Firefox
npm run build:chrome    # single production build for Chrome
npm run dev:firefox     # watch + web-ext hot-reload

Project structure

Build quirks

Always set both TARGET and BUILD_OUT_DIR env vars (cross-env handles this). The build pipeline is: tsc → vite build (content script) → vite build --config vite.popup.config.ts (popup) → vite build --config vite.background.config.ts (background service worker).

cross-env TARGET=firefox BUILD_OUT_DIR=dist-firefox tsc && cross-env TARGET=firefox BUILD_OUT_DIR=dist-firefox vite build && cross-env TARGET=firefox BUILD_OUT_DIR=dist-firefox vite build --config vite.popup.config.ts && cross-env TARGET=firefox BUILD_OUT_DIR=dist-firefox vite build --config vite.background.config.ts

dev scripts

Framework & toolchain

DaisyUI note

daisyUI is scoped to shadow DOM roots (see style.css root: config). Only these components are included: button, toggle, input, select, label, card, tab, modal, divider, swap, status, stat, badge, countdown, avatar, indicator, list, loading, skeleton, progress, steps, join, dropdown, menu, alert. Tailwind content detection is scoped to src/ via source("../") so docs/GIFs don’t generate CSS.

Testing

Tests use Vitest with jsdom environment and global API. Run npm test (single pass) or npm run test:watch (watch mode). Test files: tests/config.test.ts, tests/marks.test.ts, tests/visuals.test.ts, tests/friends.test.ts. Setup: tests/setup.ts. Config: vitest.config.ts.

PWA versioning

Bump the PWA version at commit time, following semver (keep better-intra-pwa/package.json and package-lock.json in sync, then rebuild). Do not bump for uncommitted edits — a batch of changes since the last commit shares the current version and gets a single bump when committed.

The version is injected at build time as __APP_VERSION__ (see better-intra-pwa/vite.config.ts) and shown in Settings → About & Debug. The extension package version is separate — do not bump it for PWA changes.

Do not bump the better-intra-pwa submodule pointer in the parent repo’s commits.

Extension mechanics

Worker (better-intra-worker/)

Two KV namespaces

Commands

cd better-intra-worker
npm install
npm run dev       # wrangler dev
npm run deploy    # wrangler deploy
npx wrangler kv:namespace create EVAL_KV       # first time, paste id into wrangler.json
npx wrangler secret put DISCORD_BOT_TOKEN       # set Discord bot token

Unified evaluations architecture

Worker cron (*/5 * * * *) fetches 42 API /v2/me/scale_teams for each user, detects state changes (null → booked → revealed), sends Discord DMs, and stores pending notifications in EVAL_KV. Extension background service worker polls /evaluations?action=pending every 5 min and shows Chrome notifications from whatever pending list the cron prepared. No 42 API call from the extension side.

CI

DOs and DON’Ts

NEVER delete from remote D1

Never run destructive commands against the remote D1 database (DELETE, DROP, TRUNCATE, wrangler d1 execute --remote with destructive SQL, etc.). Remote data is not reproducible. To change stored state, rely on the application’s own INSERT OR REPLACE writes or non-destructive updates; ask the user before any statement that removes rows or schema.

No linter; Prettier for formatting

Prettier is used for formatting (editor-level; no committed config). No ESLint or similar configured.