From 75c40cfb730064837c55e7e692a973d580f26569 Mon Sep 17 00:00:00 2001 From: Zaldimmar Date: Fri, 25 Sep 2026 03:20:11 -0500 Subject: [PATCH 1/2] Added update CLAUDE.md --- CLAUDE.md | 61 ++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 54 insertions(+), 7 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 529ced8..4c37542 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,12 +1,59 @@ # NGU-Web +Website for NGU (Next Generation of Unity), a Unity movement organization with regional chapters in the US and internationally. Full-stack app with a public site and a role-based admin panel. + +## Stack +- Frontend: React, TypeScript, Tailwind CSS, React Router, Vite (in `src/`) +- Backend: Hono on Node.js, SQLite (WAL mode, STRICT tables) via better-sqlite3 / node:sqlite (in `server/`) +- Package manager: pnpm only (never npm or yarn) + +## Deployment (production) +- Ubuntu VPS, nginx reverse proxy, systemd service `ngu-api` +- App deployed to `/srv/ngu-api`; database at `/var/lib/ngu/ngu.db` +- Debugging: check `journalctl -u ngu-api -n 40 --no-pager` first. Make sure rsync ran from the repo (not the deployed copy) before restarting the service. +- Never run commands against the production server or database unless explicitly asked. + ## Git workflow - Remote is a self-hosted Forgejo server, not GitHub. Do not use `gh`. -- Use `tea` for pull requests: `tea pr create --base main --head --title "..." --description "..."` -- Never commit directly to main. Create a branch for each change, push it, and open a PR. -- Versions are marked with annotated tags (v1.0, v2.0). Don't create or move tags unless asked. +- Open pull requests with `tea`: `tea pr create --base main --head --title "..." --description "..."` +- Never commit directly to main. Create a branch per change, push it, open a PR. +- Versions are marked with annotated tags (v1.0, v1.3...). Don't create or move tags unless asked. +- `server/dev.db` and other `*.db` files are local only and never committed. -## Project -- Package manager: pnpm (not npm or yarn) -- Frontend: Vite + TypeScript in src/ -- Backend in server/; server/dev.db is local only and never committed \ No newline at end of file +## How to work in this repo +- Read the relevant existing files before writing anything. Follow existing patterns exactly: descriptors, field syntax, extension shape, import conventions. +- Ask questions up front before implementing non-trivial features. +- Prefer targeted edits when surrounding code is stable; full rewrites only when a component is being substantially reworked. +- Fix root causes. No redirect shims or workarounds. +- Keep data logic in the database and presentation logic in code. Make things configurable via constants, not hardcoded in components. +- Name components for what they do, not what they currently filter. + +## Project layout +- All pages use `PageShell.tsx` as the wrapper unless explicitly noted otherwise. +- Pages live in `src/pages/`; section-level components go in `src/pages/sections/`. +- `src/data/` holds only hardcoded data shared across multiple section files (e.g. `historyDecades.ts`, map grid). Everything else comes from SQLite. +- `navConfig.js` is the single source of truth for navigation, routes, and actions (header, footer, pages). +- `api.js` is the shared caching client used by frontend data hooks. +- Logos: org logos in `/org-logos/`, event logos in `public/event-logos/`. The `` component hides itself on load error. + +## Rules and gotchas +- **Role checks must use ladder comparisons, never equality.** Roles rank viewer → editor → admin → superadmin. Use `roleCanWrite(user)` / `roleCanDelete(user)` from `lib/roles` and the minimum-rank helpers (`canWrite`, `canDelete`, `isSuper`, `atLeast`). `role === "admin"` silently excludes higher roles and has caused repeated bugs. +- **Imports need explicit extensions** (`.ts`, `.tsx`, `.js`) everywhere. +- **Vite resolves `.js` before `.ts`**, so a `.js` and `.ts` file with the same base name will import the wrong one. Give new hooks distinct names. +- **Don't use `fallback: EMPTY` in api.js hooks.** It silently returns empty arrays and hides server errors; let the error state surface. + +## Admin CRUD engine +Descriptor-driven: `server/admin-crud.js` and `admin-schema.js` (server) and `adminSchema.js` (client) generate SQL and form fields from declarative entity configs. Adding an entity should mean adding a descriptor, not new CRUD code. +- Child collections are deleted and reinserted wholesale. Unsafe for entities referenced by foreign keys elsewhere. +- `reindex: false` prevents cross-entity sort order collisions. +- The `OMIT` sentinel distinguishes unsent fields from deliberate clears. +- `admin-schema-sync.js` runs at boot and throws if descriptors don't match live `PRAGMA table_info`. If boot fails after a schema change, update the descriptor or migration so they agree. +- `admin-cli.js` imports `ROLES` and `destroyAllSessionsFor` from `auth.js`. Keep it that way to prevent drift. + +## Migrations +- Sequential files: `001_`, `002_`, ... +- The runner may drop statements after a `BEGIN...END` trigger body. Put each `CREATE VIEW` in its own migration file with no `BEGIN...END` block. +- `PRAGMA foreign_keys = OFF` must be set outside transactions when cascading constraints are involved. + +## Integrations +- Church Center (ngu.churchcenteronline.com): Planning Center embeds for giving and the calendar. \ No newline at end of file From 32d04b63e95e1ba5850903e41807f32f62b9ff80 Mon Sep 17 00:00:00 2001 From: Zaldimmar Date: Fri, 25 Sep 2026 03:24:00 -0500 Subject: [PATCH 2/2] Add commands section to CLAUDE.md and fix role/logo details Co-Authored-By: Claude Opus 5.5 --- CLAUDE.md | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 4c37542..e04f6b2 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,3 +1,7 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + # NGU-Web Website for NGU (Next Generation of Unity), a Unity movement organization with regional chapters in the US and internationally. Full-stack app with a public site and a role-based admin panel. @@ -7,6 +11,21 @@ Website for NGU (Next Generation of Unity), a Unity movement organization with r - Backend: Hono on Node.js, SQLite (WAL mode, STRICT tables) via better-sqlite3 / node:sqlite (in `server/`) - Package manager: pnpm only (never npm or yarn) +## Commands +Frontend (repo root): +- `pnpm dev` / `pnpm build` / `pnpm preview`: Vite +- `pnpm format`: oxfmt +- `pnpm exec tsc`: type-check (`noEmit`; there is no separate lint or typecheck script) +- There is no test suite. + +Backend (`server/`, Node >= 22). The server reads `HOST` (default `127.0.0.1`), `PORT` (default `3001`) and `DB_PATH` (default `./ngu.db`); locally, use `DB_PATH=./dev.db`: +- `DB_PATH=./dev.db pnpm dev`: run with `node --watch` +- `DB_PATH=./dev.db pnpm migrate`: apply migrations without starting the server +- `DB_PATH=./dev.db node src/seed.js`: rebuild content tables from `src/data/`. It wipes every content table first (feedback is kept). Run it from the repo, not the deployed copy. +- `DB_PATH=./dev.db node src/admin-cli.js add|list|passwd|role|disable|enable ...`: the only way accounts are created + +In dev, Vite proxies `/api` to the target set in `vite.config.ts`, so the API must listen on that port. + ## Deployment (production) - Ubuntu VPS, nginx reverse proxy, systemd service `ngu-api` - App deployed to `/srv/ngu-api`; database at `/var/lib/ngu/ngu.db` @@ -34,10 +53,10 @@ Website for NGU (Next Generation of Unity), a Unity movement organization with r - `src/data/` holds only hardcoded data shared across multiple section files (e.g. `historyDecades.ts`, map grid). Everything else comes from SQLite. - `navConfig.js` is the single source of truth for navigation, routes, and actions (header, footer, pages). - `api.js` is the shared caching client used by frontend data hooks. -- Logos: org logos in `/org-logos/`, event logos in `public/event-logos/`. The `` component hides itself on load error. +- Logos: org logos in `public/org-logos/` (served at `/org-logos/`), event logos in `public/event-logos/`. The `` component hides itself on load error. ## Rules and gotchas -- **Role checks must use ladder comparisons, never equality.** Roles rank viewer → editor → admin → superadmin. Use `roleCanWrite(user)` / `roleCanDelete(user)` from `lib/roles` and the minimum-rank helpers (`canWrite`, `canDelete`, `isSuper`, `atLeast`). `role === "admin"` silently excludes higher roles and has caused repeated bugs. +- **Role checks must use ladder comparisons, never equality.** Roles rank viewer → editor → admin → superadmin. Use the minimum-rank helpers from `src/lib/roles.ts` (`canWrite`, `canDelete`, `isSuper`, `atLeast`). Where a local variable shadows the name, import with an alias, e.g. `canWrite as roleCanWrite`. `role === "admin"` silently excludes higher roles and has caused repeated bugs. - **Imports need explicit extensions** (`.ts`, `.tsx`, `.js`) everywhere. - **Vite resolves `.js` before `.ts`**, so a `.js` and `.ts` file with the same base name will import the wrong one. Give new hooks distinct names. - **Don't use `fallback: EMPTY` in api.js hooks.** It silently returns empty arrays and hides server errors; let the error state surface.