SPB Git
6.0 KB · 29 lines markdown
1# Developer conventions — Note SPBoucher AI23Read this before touching the code. Stack: Next.js 16 (App Router, React 19, TypeScript strict), Tailwind v4 (design tokens in `src/app/globals.css`: `bg`, `bg-elev`, `bg-sunk`, `fg`, `fg-muted`, `fg-faint`, `line`, `accent`, `ai`, `danger`, `success`, `warning`), Drizzle ORM + PostgreSQL 17 + pgvector (`src/db/schema.ts`, **snake_case casing**), pg-boss worker (`src/worker`), official `openai` + `@anthropic-ai/sdk` behind `src/lib/ai`.45## Hard rules6- **Do not edit `src/db/schema.ts` and do not add migrations.** Every table you need already exists (see schema). Flexible data goes in the existing `jsonb` columns (`pages.properties`, `database_properties.config`, `database_rows.values`, `database_views.config`, `ai_executions.*`, `settings`, `dashboard_layouts.widgets`, `experiments.params/metrics`, `references.fields`).7- **Do not add npm dependencies** (no `pnpm add`). Installed and available: next, react, drizzle-orm, postgres, pg-boss, zod, openai, @anthropic-ai/sdk, @tiptap/* (core, react, starter-kit, list, table, image, mention, mathematics, details, code-block-lowlight, drag-handle-react, file-handler, bubble-menu, extensions), lowlight, katex, motion, @tanstack/react-query, zustand, react-force-graph-2d, pdf-parse, mammoth, papaparse, turndown, marked, jszip, bibtex-parse-js, nanoid, sanitize-html, react-markdown + remark-gfm/remark-math/rehype-katex, @dnd-kit/*, cmdk, lucide-react, date-fns, qrcode, otplib, @simplewebauthn/*, @radix-ui/* (dialog, dropdown-menu, popover, tooltip, select, switch, tabs, scroll-area, checkbox, slot, separator, toast, context-menu, avatar), class-variance-authority, clsx, tailwind-merge, tippy.js, pino, dotenv.8- **Never run `pnpm build`, never start anything on port 8480** (a production server is running there). Typecheck with `npx tsc --noEmit`. To try your feature in a browser use `pnpm exec next dev -p <your port>` with the `.env` in the project root (it already points to the real database through an SSH tunnel on 127.0.0.1:15432; if `nc -z 127.0.0.1 15432` fails, run `ssh -f -N -L 15432:127.0.0.1:5432 M4M64c`). Login: username `simon`, password = the value of `OWNER_INITIAL_PASSWORD` in `~/Desktop/Cluster/secrets/note-spboucher-ai/.env` (read it with grep; never print it in your report). The worker is also running (`/tmp/note-worker.log`); you can run a second worker with `npx tsx src/worker/index.ts` if you change handlers (stop it when done).9- Only touch the files/directories assigned to you; do not reformat other files. New routes go in `src/app/(app)/<route>/page.tsx` (server component that calls `requireUserPage()` + `getWorkspace()` then renders a client component).10- Secrets: never log API keys. AI calls go through `src/lib/ai` only (router → providers); record usage with `recordUsage`.11- UI quality bar: minimalist, dense, premium; reuse `src/components/ui/*` primitives (`Button`, `Input`, `Dialog`, `Popover`, `Menu*`, `Tabs*`, `Badge`, `Switch`, `Tip`, `Empty`, `Spinner`, `toast`). Responsive: every screen must work on a 390px-wide phone (stack columns, horizontal scroll for wide tables, touch targets ≥ 40px) and on desktop. Dark mode via tokens only (no hard-coded colours). Keyboard: Escape closes, Enter confirms.1213## Server-side helpers14- `handler(({ req, user, ws, params }) => Response)` from `src/lib/api.ts` wraps a route handler with auth + workspace + error mapping; `parseBody(req, zodSchema)`; `HttpError(status, msg)`; `uuid` zod helper. Example: `src/app/api/pages/[id]/route.ts`.15- `db`, `schema` from `@/db`; `audit(userId, action, target?, detail?)` from `@/lib/audit`.16- Pages service `src/lib/pages/service.ts` (`createPage`, `updatePage`, `getPage`, `listTree`, `softDeletePage`, …). Pages are the universal container: `type` = page | database | research; database rows are pages with `database_id` set (row page content = the row's body).17- Search: `hybridSearch(wsId, q, { limit, pageIds, sourceTypes })`, `indexSource(...)` in `src/lib/search/index.ts`; chunking in `chunk.ts`; embeddings in `embed.ts`.18- AI: `route({ task, tools?, schema?, vision?, estTokens?, preferred? })` from `src/lib/ai/router.ts` returns `{ model, provider, effort, reason }`; then `callAI({ model: model.id, provider, system, messages, jsonSchema?, tools?, effort })` (non-streaming) or `streamAI(...)` (async generator of `{type:"text"|"tool_call"|"done"|"error"}`) from `src/lib/ai/providers.ts`; `sse(generator)` from `src/lib/ai/chat.ts` turns a generator into an SSE Response. Task classes: chat | quick | write | reason | deep | code | extract | longctx | agent | judge. Prompts: `src/lib/ai/prompts.ts` (`INJECTION_GUARD` must be appended to any system prompt that sees workspace content; wrap workspace content in `<workspace>` tags).19- Jobs: `enqueue(QUEUES.x, data)` from `src/lib/jobs`; handlers in `src/worker/handlers/*` (imports must use relative paths like `../../db/index`, not `@/`, and must not import `next/*`).20- Editor JSON helpers (`src/lib/editor/text.ts`): `docText`, `docBlocks`, `toMarkdown`, `emptyDoc`; client: `markdownToDoc` in `src/lib/editor/markdown-client.ts`.2122## Client-side helpers23- `api(url, { method, json })` and `sse(url, body, onEvent, signal)` in `src/lib/client/api.ts`; UI store `useUI()` in `src/lib/client/store.ts` (`openAI({ pageId, prefill })`, theme, panels); `cn`, `timeAgo`, `fmtDate`, `money` in `src/lib/utils.ts`; `Markdown` renderer `src/components/markdown.tsx`; `Editor` (`src/components/editor/Editor.tsx`, props: content, onChange, pageId, editable).24- Pages are opened at `/p/<id>`; `PageView.tsx` renders `DatabaseView` for `type === "database"` and `ResearchPanel` for `type === "research"`.25- React Query keys in use: `["tree"]` (sidebar), `["ai-models"]`, `["convs", pageId]`, `["search", mode, q]`. Invalidate `["tree"]` after creating/renaming/deleting pages.2627## Reporting28When done: run `npx tsc --noEmit` (must be clean for your files), list the files you created/changed, what you verified in the browser or with curl, and anything left incomplete. Do not commit.29
Files · main
Menu

Theme