Files
wireguard-ui/AGENTS.md
T
2026-09-12 13:56:36 +01:00

8.9 KiB

Agent Instructions

Read WORKSPACE_MEMORY.md before making structural changes to page code.

Stack

  • Runtime: Bun — not Node. Use bun commands, never npm/npx.
  • Framework: @moduletrace/bunext — not Next.js. Routing is filesystem-based under src/pages/, served by Bun.serve in src/server.ts.
  • Database: @moduletrace/bun-sqlite — MariaDB database. Schema in db/schema.ts, generated types in db/types/db.ts. Config in bun-sqlite.config.ts (DB name rpe.db in ./db).
  • UI: Tailwind CSS v4 + local twui components (src/components/twui) + shadcn/ui (src/components/ui). shadcn/ui configured via components.json (style: radix-vega), CSS entry at src/components/twui/base.css (imported by src/styles/globals.css). Uses @shadcnblocks registry for extra blocks (src/components/shadcnblocks).
  • Icons: lucide-react.
  • Validation: zod v4 ([email protected]).

Entrypoint

src/server.ts — runs bunextInit(), initializes a persistent Piper TTS daemon (global PIPER_MANAGER), starts Bun.serve with WebSocket upgrade on /ws, then starts cron.

Commands

Purpose Command
Dev server bun run dev (runs bun src/server.ts)
Production bun run start (NODE_ENV=production bun src/server.ts)
Type-check only bunx tsc --noEmit
DB schema (tables) bun run db:schema
DB schema (+vectors) bun run db:schema:vector
DB admin UI bun run db:admin
DB backup bun run db:backup
Port SQLite → MariaDB bun run db:port-sqlite
Install (private registry) bun install (uses registry in bunfig.toml)

No linter or formatter configured. Type-check is the primary verification step. 33 project-level .test.ts/.test.tsx files exist but no test runner script is configured — run individual tests with bun test <file>.

Architecture

Root Component & Context

src/pages/__root.tsx — sets up:

  • Layout selection (admin/auth/public)
  • WebSocket connection via useWebSocket + useWebSocketEventHandler
  • AppContext (React context) providing AppContextType globally — includes user data, WebSocket, and sendWebsocketData
  • Server-navigated URL push via server:navigate-to-url WebSocket event

Path Alias

@/* resolves from repo root. Import like @/src/components/ui/button, @/db/types/db, @/external/cloudflare/r2.

Admin Route Hierarchy

Two tiers of admin pages:

  • /admin/* — Resident-facing features: access booking (/admin/access), payments (/admin/payments/*), chat (/admin/chat/*), dependants (/admin/dependants), notifications (/admin/notification), events (/admin/events), settings/profile, support/complaints. Additional sections: association/, devops/, management/, workers/
  • /admin/admin/* — Admin-only features: user management (/admin/admin/users/*), payment schemes, payment management, documents/constitution, chat group management. Requires admin or exco role.
  • /admin/security/* — Security features: gate control, guest access monitoring, dependant verification. Requires security, exco, manager, or aco role.

Admin sidebar navigation data in src/layouts/admin/(data)/. ElevenLabs voice agent widget integrated into admin layout (src/layouts/admin/(partials)/eleven-labs-widget.tsx).

Page Directory Rules

For route-local code under src/pages, use non-routed meta folders:

  • (sections) — page sections
  • (partials) — components used by sections
  • (data) — page-local data
  • (functions) — page-local functions
  • (utils) — page-local utilities
  • (hooks) — page-local hooks

Keep route files (e.g. index.tsx) thin — compose from route-local meta folders.

Dynamic routes use [param] syntax (e.g. [id], [user_type], [key]). Catch-all routes use [[...paths]].

Server functions use index.server.ts alongside index.tsx (e.g. single-document/[id]/index.server.ts).

Shared Code Organization

  • src/hooks/ — Shared React hooks: use-admin-crud-get, use-all-users-list-init, use-annual-dues-status, useAppContext, use-fetch-get, use-form-init, useLocalUser, use-mobile, use-payments-query, use-users-get
  • src/functions/ — Shared functions split by target:
    • src/functions/backend/ — Server-only: DB queries (grab-users in backend/db/), email client, RAG ingest, media upload, embed/face ingest
    • src/functions/frontend/ — Client-safe: CRUD handlers, fetch handlers, Paystack script loader, URL parser
    • src/functions/general/ — Platform-agnostic: join builders in general/joins/ (users, payments, guests, messages, chat groups)
  • src/utils/ — Utility modules: auth, cookies, crypto, CSRF, hashing, contact classification, RAG text chunking, user type parsing. Most have corresponding .test.ts files (auth, cookies, crypto, CSRF, hashing, contact classification, user type parsing).
  • src/dict/ — Dictionaries/constants: user types, access codes, gates, LLM providers/models, TTS voices, WebSocket rooms, messaging types, localStorage keys
  • src/data/ — Static data: app-data.ts (app constants — cookie names, limits, default models, Paystack endpoint), location data, super admin users, role documentation
  • src/types/ — Type definitions (~1,350 lines total across 4 files): index.ts (1,037 lines), sql-joins.ts, paystack.ts, search-api.ts
  • src/lib/ — utils.ts exports cn() (clsx + tailwind-merge), used by shadcn/ui components
  • src/scripts/ — Seed scripts for location and resident data

Component Systems

Directory Description
src/components/twui/ Local design system — publishable package with its own package.json. Contains elements, composites, editors (TinyMCE), form components, MDX support, hooks, layout, SVGs, and utilities
src/components/general/ Shared page components: AI chat, date-picker, logo, Paystack widgets, status-tag, user-avatar, face-search-card, guarantor-preview-modal, guarantor-info-row, etc. (search-select lives in src/components/twui/form/SearchSelect.tsx)
src/components/pages/ Public page components: about/, constitution/, homepage/
src/components/shadcnblocks/ Components from shadcnblocks.com registry (logo)

Conventions

  • Prefer one function/component per file over monolithic files with multiple exports.
  • Modularization is non-negotiable: prioritize modularization over monolithic functions/components. Repeated UI blocks must be extracted into their own reusable components driven by props (e.g. an info row component taking { icon, text }), never repeated inline markup.
  • Every rendered array must have a separate component for each array item. Always extract the item JSX into its own component and render it via items.map((item) => <ItemComponent {...item} />) — never inline the item's JSX inside the map callback.
  • Always use object parameters ({ foo, bar }) instead of comma-separated positional parameters.
  • Prefer existing patterns over new abstractions.
  • .env is gitignored but exists locally with secrets. Do not commit it.
  • secrets/ directory is also gitignored.
  • external/ binary directories (**/models, **/bin, **/x-86, **/arm-64) are gitignored.
  • The bunext.config.ts excludes onnxruntime-node and @xenova/transformers from SSR/page compilation (native modules that must stay server-side).
  • tsconfig.json excludes src/components/twui/mdx, src/components/twui/elements/RemoteCodeBlock.tsx, and src/components/twui/mdx/markdown/MarkdownEditorPreviewComponent.tsx from type-checking.