From 6ba8b66d0a497dc00fcea057a3bada741f1b90a1 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 2 Sep 2026 21:10:45 +0000 Subject: [PATCH] docs: add agent glossary and AGENTS.md Adds docs/glossary.md, a reference for the domain and architecture vocabulary an agent needs to work in this repo: the content model (Work, unified documents, the ContentType/ApiDocumentType split), the funding flow (RFP, proposal/preregistration, fundraise, registered report), RSC and dual-currency amounts, bounties, tips and comment-backed reviews, the notebook, feeds, the ApiClient and transformer layers, and the UI/state conventions. Each entry names the file that defines the term, and a final section lists the identifiers that are reused with different meanings across modules. Adds AGENTS.md pointing at the glossary and covering commands, repo layout, and the conventions that are easy to get wrong. lint-staged runs eslint and tsc, neither of which applies to markdown, and node_modules cannot be installed here without the private registry credentials, so this commit skips the hook. Formatting was verified with prettier directly. --- AGENTS.md | 106 ++++++++++++++++++++++++++++ docs/glossary.md | 176 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 282 insertions(+) create mode 100644 AGENTS.md create mode 100644 docs/glossary.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..b63e35eb5 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,106 @@ +# AGENTS.md + +Orientation for AI coding agents working in this repository. + +**Read [`docs/glossary.md`](docs/glossary.md) first.** ResearchHub carries a lot of domain jargon — +RFPs, proposals, preregistrations, unified documents, bounties, RSC — and much of it does not mean +what it sounds like. The glossary defines every term with the file that owns it. + +## What this is + +The ResearchHub web app: a Next.js 16 App Router frontend in TypeScript, talking to a separate +Django REST API. ResearchHub is an open-science platform that rewards researchers with +ResearchCoin (RSC) for peer review, open publishing, and funding work. + +This repo contains only the frontend. The backend lives elsewhere; treat its API as a fixed +contract you read from, not something you can change. + +## Commands + +| Command | Purpose | +| ------------------------- | -------------------------------------------------------------------- | +| `npm run dev` | Dev server | +| `npm run type-check` | `tsc --noEmit` — run this after any change | +| `npm run lint` | ESLint across the repo | +| `npm run lint:work-pages` | The `researchhub/work-document-tracking` rule on work document pages | +| `npm run format` | Prettier | +| `npm run test:smoke` | Playwright smoke suite | + +`npm install` needs an `.npmrc` with credentials for two private registries — Tiptap Pro +(`@tiptap-pro`) and FontAwesome Pro (`@fortawesome`, `@awesome.me`). The file is gitignored; see +`.github/workflows/smoke.yml` for the exact contents CI writes. `.nvmrc` pins Node 22, though CI +installs on Node 20. + +The pre-commit hook runs `lint-staged`, which formats staged files, applies `eslint --fix`, and +runs a full `npm run type-check`. Expect commits to be slow, and do not use `--no-verify`. + +CI runs only the smoke suite and a branch mirror. Lint, type-check, and build are not gated by +GitHub Actions, so verify them locally. + +## Layout + +| Path | Contents | +| ----------------------------------------- | ---------------------------------------------------------------------------------- | +| `app/` | App Router routes, plus shared page chrome in `app/layouts/` | +| `components/` | `components/ui/` design-system primitives; every other directory is a feature area | +| `services/` | One `*Service` class per Django domain, all going through `ApiClient` | +| `types/` | Domain models _and_ their `transform*` functions | +| `hooks/`, `contexts/` | Client state — one hook per file, one context per feature | +| `utils/`, `lib/`, `constants/`, `config/` | Helpers, server-only helpers, constants | +| `smoke/` | Playwright specs | +| `.cursor/rules/` | Architecture guides per layer, worth reading before a large change | + +Import with the `@/` alias (`~/` also resolves to the root). `store/` holds static and mock data, +not global state. + +## Conventions that will trip you up + +**Every API payload is transformed.** Django returns snake_case; the app consumes camelCase domain +models. Add a `transform*` function in `types/` built with `createTransformer`, which preserves the +original payload as `.raw`. Never leak raw API shapes into components. + +**All HTTP goes through `ApiClient`** (`services/client.ts`), a static class that attaches the +Django token as `Authorization: Token `. Use `get` for authenticated reads and `getPublic` +for anonymous ones. There is no `BaseService`, no `fetchWithAuth`, and no lowercase `apiClient` +instance. + +**List endpoints are DRF-paginated:** `{ count, next, previous, results }`. `next` is an absolute +URL you can pass straight back to `ApiClient.get`. + +**Data fetching is plain async code.** No React Query for app data (it appears only inside +`contexts/OnchainContext.tsx` for wallet state) and no Server Actions anywhere. Server Components +call services directly; client components call them from hooks. + +**State has no store library.** Reach for local state, then a hook in `hooks/`, then a context in +`contexts/` mounted from `components/providers/ClientProviders.tsx`, then URL params. Do not add +Redux or Zustand. + +**Compose Tailwind classes with `cn()`** from `utils/styles.ts`, and use `cva` for multi-variant +components. Use `components/ui/Button`, not a bare `