# Repository Guidelines ## Project Structure `src/` holds the React client: components in `src/components/`, hooks in `src/hooks/`, lesson data in `src/data/`, and CSS in `src/styles/`. `server.ts` is the Bun entrypoint; server-only code lives in `server/` (`auth.ts`, `db.ts`, `config.ts`). Nix files are split between `flake.nix`, generated `bun.nix`, and reusable deployment pieces in `nix/`. ## Local Development - `bun install`: install dependencies from `bun.lock`. - `bun run dev`: start the Bun server with HMR on port `5174`. - `bun run lint`: run ESLint. - `bun run typecheck`: run `tsc -b`. - `bun run build`: bundle the Bun server into `build/`. - `bun run update:bun-nix`: regenerate `bun.nix` after dependency changes. Run `bun run lint && bun run typecheck && bun run build` before opening a PR. ## Coding Conventions TypeScript is strict on both client and server. Follow the existing style: single quotes in frontend files, PascalCase component filenames, `useX` hook names, and lowercase data/config modules. Keep runtime configuration in `server/config.ts` rather than scattering `process.env` reads. ## Bun2nix Setup This repo uses Bun as the package manager and `bun2nix` for reproducible Nix builds. The flow is: - `bun.lock` is the source of truth for JS dependencies. - `bun.nix` is generated from `bun.lock` with `bun run update:bun-nix`. - `flake.nix` imports the `bun2nix` overlay and exposes `packages..default` plus `nixosModules.default`. - `nix/package.nix` uses `bun2nix.fetchBunDeps` with `bun.nix`, runs `bun run build`, and installs the bundled `server.js` plus frontend assets as the `leo-ed` executable. Whenever dependencies change, update both `bun.lock` and `bun.nix` in the same commit. CI checks that `bun.nix` matches the lockfile by regenerating it and failing on diff. ## Server and Deployment Model This repo is the application source, not the full server configuration. Production is intended to be managed from a separate NixOS infra repo that imports this flake and sets `services.leo-ed.package = inputs.leo-ed.packages.${pkgs.system}.default;`. The included module in `nix/module.nix` defines the systemd service, runtime env (`APP_ORIGIN`, `PORT`, `SQLITE_PATH`, `SESSION_COOKIE_SECURE`), and persistent state directory. `server/config.ts` exists so production behavior is explicit: WebAuthn origin/RP ID, SQLite path, bind host, and secure cookies should come from NixOS service configuration, not reverse-proxy accident. ## Forgejo and Woodpecker Forgejo should be the canonical remote and PR system. Woodpecker runs repo CI from `.woodpecker.yml`: install deps in the flake dev shell, lint, typecheck, build, regenerate `bun.nix`, and `nix build .#default`. That validates the app package only. Production deployment belongs in the separate infra repo. The expected flow is: - merge app changes in Forgejo - update the infra repo input that pins this app revision - let Woodpecker in the infra repo run `nixos-rebuild --target-host ...` Keep app CI and host deployment separate; this repo proves the package is buildable, while the infra repo owns the actual VPS switch. ## PR Guidance Use focused, imperative commit messages such as `auth: honor configured app origin` or `nix: package app with bun2nix`. PRs should list verification steps and mention any dependency updates, `bun.nix` regeneration, or NixOS module changes.