

Also from Kynth Studios


Also from Kynth Studios


Also from Kynth Studios
1# AGENTS.md — Vibe Code Stack For CEOs23AI-first Turborepo monorepo (pnpm 11, Node 22, TypeScript strict): 3 frontend4apps + 3 backend services + 3 shared packages, deployed to Cloudflare and5private AWS EC2 infrastructure.67- This file is the single source of truth for agent behavior. `CLAUDE.md` is a8 symlink to it — always edit `AGENTS.md`.9- This is intentionally the ONLY `AGENTS.md` in the repo (no nested10 per-workspace files) — rules are scoped per workspace inside this file to11 avoid drift. Don't create nested agent files.12- When a rule here conflicts with existing code, follow the rule and flag the13 code.1415## Monorepo map1617| Workspace | Package | What it is | Deploys to |18|-----------|---------|------------|------------|19| `apps/dapp` | `@apps/dapp` | Next.js 16 App Router (vinext/Vite) | Cloudflare Workers |20| `apps/admin` | `@apps/admin` | React 19 SPA (Rsbuild + React Router, no RSC) | Cloudflare Pages |21| `apps/landing` | `@apps/landing` | Astro static site (zero JS by default) | Cloudflare Workers |22| `services/trading-rpc` | `@services/trading-rpc` | NestJS host on Fastify: Connect for edge + native Nest gRPC for Node services | AWS EC2 (Docker/ECR/SSM) |23| `services/admin-rpc` | `@services/admin-rpc` | Admin-facing NestJS RPC facade; calls trading-rpc over native gRPC for coin data | AWS EC2 (Docker/ECR/SSM) |24| `services/api-gateway` | `@services/api-gateway` | Edge gateway Worker (Hono: request-id, CORS, self-hosted Durable Object rate-limit, opt-in JWT auth, upstream proxy) | Cloudflare Workers |25| `packages/protocol` | `@packages/protocol` | Protobuf schemas, buf codegen → `src/gen/` | — |26| `packages/api-core` | `@packages/api-core` | Shared RPC impl + CORS-aware fetch handler | — |27| `packages/api-client` | `@packages/api-client` | Typed Connect-RPC browser client | — |2829Rule scope: Server/Client Component rules apply to `apps/dapp` only. All three30frontend apps use an FSD-inspired layered architecture with explicit31`bootstrap`/`screens` names and framework-specific entrypoints documented below.32The backend slice architecture applies to `packages/api-core` + `services/*`33(see Architecture rules).34Everything else (naming, testing, git, security) applies repo-wide.3536## Tech stack (mind the major versions — APIs differ across generations)3738| Layer | Tool + version |39|-------|----------------|40| Framework (dapp) | Next.js 16 App Router on vinext 0.1 (Vite) |41| UI | React 19 · Panda CSS 1.x + Ark UI 5 (headless) |42| Language | TypeScript 6, `strict: true` |43| Validation | Zod **4** (not v3 — different error/message APIs) |44| Server state | TanStack Query 5 |45| Client/URL state | Zustand 5 · nuqs 2 |46| Forms | react-hook-form 7 + Zod resolver |47| Server actions | next-safe-action **8** |48| Tables | TanStack Table 8 |49| HTTP | ofetch 1 (via shared `xhr`) · Connect-RPC 2 (`@connectrpc/*`) |50| API server (Node) | NestJS 11 + Fastify 5 + ConnectRPC 2 + native Nest gRPC · edge gateway on Hono 4 |51| Database | PostgreSQL 18 · Drizzle ORM 0.45 + Drizzle Kit 0.31 on node-postgres 8 |52| Auth | iron-session 8 (encrypted cookies) |53| Admin | Rsbuild 2 (Rspack) · React Router **7** |54| Landing | Astro 7 |55| Testing | Vitest 4 + Testing Library + MSW 2 + Playwright |56| Lint/format | Biome 2 + ESLint 10 (flat config) + buf |57| Monorepo | Turborepo 2 + pnpm 11 workspaces |5859## Commands6061```bash62mise run setup # install locked tools + frozen dependencies6364mise run dev # native apps + managed PostgreSQL/VPC infra65mise run dev:web | dev:admin | dev:landing # one frontend66mise run dev:api | dev:admin-api | dev:gateway | dev:backend # backend topology67mise run dev:infra:stop # stop native-development Docker infra6869mise run typecheck # tsc --noEmit, all 9 workspaces70mise run check:ci # Biome (read-only), whole repo71mise run lint # ESLint / Biome / buf / architecture checks72mise run test # toolchain tests + Vitest, all workspaces73mise run test:coverage # enforce dapp/admin logic coverage thresholds74mise run build # production builds75mise run check # Biome auto-fix + format76mise run verify # all definition-of-done gates, sequentially77mise run test:docker # Docker builds + PostgreSQL backup/restore integration78mise run test:protocol # codegen drift + protobuf breaking check79mise run security:audit # high-severity dependency audit8081mise run docker:start # full Docker development stack82mise run docker:start:dapp | docker:start:admin | docker:start:landing83mise run docker:start:api-gateway | docker:start:admin-rpc | docker:start:trading-rpc84mise run docker:stop | docker:check85mise run terraform:check # fmt + provider-backed validate; never apply8687# pnpm is internal; use it directly only for targeted commands without a mise task.88pnpm --filter @apps/dapp test # one workspace89pnpm --filter @apps/dapp exec vitest run <path-to-test-file> # one test file90mise run test:e2e # Playwright (apps/dapp/e2e/); needs browsers installed91```9293## Definition of done9495Run these before declaring any task complete. CI runs exactly the same gates.9697- [ ] `mise run typecheck` — zero errors98- [ ] `mise run check:ci` — zero errors99- [ ] `mise run lint` — zero errors100- [ ] `mise run test` — all pass; new logic has tests101- [ ] `mise run test:coverage` — frontend feature/entity logic meets thresholds102- [ ] `mise run build` — if you touched build-relevant code or config103- [ ] `mise run test:e2e:production` — production-server browser behavior104- [ ] `mise run test:protocol` — generated contracts and compatibility105- [ ] `mise run security:audit` — no known high-severity dependency issue106- [ ] `mise run test:docker` — release images and PostgreSQL recovery path107108Deploys are CI-gated only (`.github/workflows/deploy.yml`; `develop` → staging,109`main` → production). NEVER deploy from a local machine.110111## Architecture rules112113### Dapp architecture — FSD-inspired layered frontend114115Next.js framework entrypoints stay outside the FSD root. They are thin adapters116that delegate to the appropriate Bootstrap segment or Screen public API:117118```text119apps/dapp/120 app/ Next pages/layout/Route Handlers only121 proxy.ts Next proxy entrypoint only122 instrumentation*.ts Next instrumentation entrypoints only123 src/124 bootstrap/ app composition: routes, providers, metadata,125 errors, proxy, instrumentation, styles126 screens/{home,sign-in,account,not-found}/127 complete route screens; api/model/ui + public API128 features/sign-in/ reusable sign-in interaction; api/model/ui129 entities/session/ session domain API/model + client/server APIs130 shared/ api, config, focused lib/*, routes, ui131 styled-system/ generated Panda code; never hand-edit132```133134Conceptual dependency direction is one-way:135136```text137Next framework entrypoints → bootstrap → screens → widgets → features → entities → shared138```139140Layers are optional. `widgets` is intentionally absent until a reusable,141self-contained UI block exists. `bootstrap` and `shared` contain segments rather142than slices. The explicit names keep framework-owned `app/` distinct from143application composition and avoid the overloaded FSD `app`/`pages` terminology.1441451. Imports point downward only. Same-layer slices are isolated and MUST NOT146 import each other.1472. Every slice and every `bootstrap`/`shared` segment exposes a Public API. External148 consumers never deep-import internals. All frontend-local module specifiers,149 including imports inside one slice, use absolute aliases (`@/` for `src/` and150 dapp-only `@root/` when a source module must reach the workspace root).1513. Server-only exports use `index.server.ts`; client-only exports use152 `index.client.ts`. Never mix a `server-only` module into a client API.1534. Segments are purpose-named (`api`, `model`, `ui`, `config`), never154 essence-named (`components`, `hooks`, `types`, `services`, `utils`). Focused155 Shared libraries live under `shared/lib/[purpose]/index.ts`.1565. `app/`, root proxy, and root instrumentation files contain only framework157 contracts, static Next exports, and public-API delegation—zero business logic.1586. Steiger enforces the standard lower FSD layers/public APIs; ESLint covers the159 project-specific `bootstrap`/`screens` layers and framework entrypoints. Run160 `pnpm --filter @apps/dapp lint:architecture` after structural changes.1617. `src/styled-system/**` is generated Panda code and the only top-level FSD162 exception. Never hand-edit it.1638. Monorepo boundaries remain: `packages/` → `packages/` only; `services/` →164 `packages/` only; nothing imports from `apps/`.165166### Admin architecture — FSD-inspired layered frontend167168`apps/admin` uses explicit application layers and purpose-named segments:169170```text171src/172 bootstrap/ entrypoint, providers, router, global styles173 screens/[name]/ complete route screens; api/model/ui + index.ts174 widgets/app-shell/ reusable protected-route layout175 features/[action]/ reusable product interactions (currently absent)176 entities/{session,user}/ domain models, data access, queries + index.ts177 shared/ api, config, focused lib/*, model, routes, ui178```179180Dependency direction is strictly downward: `bootstrap → screens → widgets →181features → entities → shared`. Layers are optional: admin currently has no `features/`182because sign-in, create-user, and service-health are each used by only one page183and therefore belong to those Screen slices. Do not create a layer or slice merely184to make the folder tree look complete.1851861. Slices on the same layer are isolated and MUST NOT import each other.1872. Every slice and every `bootstrap`/`shared` segment exposes a Public API (`index.ts`);188 external consumers never deep-import internals. Same-slice imports also use189 the absolute `@/` alias; relative frontend imports/exports are rejected.1903. Segment names describe purpose (`ui`, `api`, `model`, `config`), never file191 essence (`components`, `hooks`, `types`, `services`, `utils`). Focused Shared192 libraries use `shared/lib/[purpose]/index.ts`.1934. `bootstrap/router` only composes Screen and Widget Public APIs. Route screens194 and screen-specific data/UI live in `screens/[name]`, not in `bootstrap`.1955. Add an Entity for a business noun reused by higher layers. Add a Feature only196 for a meaningful interaction reused across pages or independently consumed.1976. Steiger checks the standard lower FSD layers; ESLint checks direction,198 isolation, and Public APIs for `bootstrap`/`screens`. Run199 `pnpm --filter @apps/admin lint:architecture` after structural changes.2007. `src/styled-system/**` is generated Panda code and the only top-level FSD201 exception. Never hand-edit it.202203### Landing architecture — FSD-inspired layered frontend204205`apps/landing` uses Astro route entrypoints in `astro/pages/` and layered206application code in `src/`. Its current direction is `Astro entrypoints →207screens → widgets → shared`; `features` and `entities` are intentionally absent208until the product has reusable user interactions or domain entities. SEO and209global styles are Shared segments because this static app needs no Bootstrap210layer.2112121. Imports point downward only. Slices on the same layer never import each other.2132. Every slice and every `shared` segment exposes an `index.ts` Public API;214 external consumers never deep-import internals. All local Astro/TypeScript215 module specifiers use the absolute `@/` alias, including same-slice imports.2163. Segment names describe purpose (`ui`, `model`, `config`, `seo`, `styles`),217 never file essence (`components`, `hooks`, `types`, `data`).2184. `astro/pages/` contains thin framework entrypoints only. Screen composition219 lives in `src/screens/[name]`; independent page blocks live in `src/widgets`.2205. A static section describing product features is a widget, not an FSD feature.221 Add an FSD feature only for a reusable user interaction that provides value.2226. Run `pnpm --filter @apps/landing lint:architecture` after structural changes.223224### Backend architecture — Feature-first pragmatic Hexagonal225226The backend is a **coarse-grained modular system** organized by business227capability. The default unit of change is a vertical slice under `features/`.228Inside a slice, use Hexagonal architecture (Ports & Adapters) only where a real229domain invariant or external boundary justifies it. Simple RPCs stay simple;230complex capabilities may grow `domain/`, `application/`, `adapters/`, and231`infra/` inside their own slice. This is NOT the frontend's FSD pattern.232233| Boundary | This repo |234|----------|-----------|235| **Published contract** | `packages/protocol` — Protobuf service/method definitions |236| **Shared multi-runtime RPCs** | `packages/api-core` — capability slices shared by Node and Workers |237| **Service capability** | `services/*/src/features/[capability]` — one isolated vertical slice |238| **Driving adapters** | service-root `adapters/` — Hono, Fastify, Cloudflare bindings |239| **Driven adapters** | feature-local `infra/` — providers, storage, VPC/DO adapters behind ports |240241**The Dependency Rule** — across workspaces: `services/* → api-core → protocol`.242Inside a service, composition/config/root adapters consume feature Public APIs;243inside a feature, dependencies point inward: `adapters/infra → application →244domain`. Features NEVER import one another. Shared policy/logging primitives may245be imported by application code but contain no feature business logic. Domain246and application code import no Hono, Connect, Cloudflare, Fastify, Request, or247Response runtime types.248249**Shared application core (`packages/api-core`):**250251```252packages/api-core/src/253 adapters/connect/ Connect route/fetch adapters + Connect error mapping254 features/[capability]/ schema + pure service + thin Connect handler + index.ts255 shared/ transport-neutral config/CORS helpers; zero business logic256 index.ts PUBLIC package barrel — the ONLY service import surface257```258259`api-core` is not a dumping ground. Add a capability there only when the same260behavior genuinely runs in more than one runtime. Service-owned business261capabilities stay in their owning service.262263**Node service (`services/trading-rpc`):**264265```266src/267 index.ts composition root; the only env reader268 adapters/http.adapter.ts Nest/Fastify host + Connect plugin + gRPC listener269 adapters/http/ Nest HTTP controllers270 adapters/grpc/ shared native Nest gRPC controllers271 platform/nest/ root module, interceptors, lifecycle providers272 features/market-data/ reference capability; see features/README.md273 domain/ value objects, aggregate data, domain errors + ports274 application/ input port + use case275 adapters/connect/ Connect response/error mapping276 adapters/grpc/ Nest controller + Zod pipe + safe RPC filter277 infra/coingecko/ provider-specific outbound adapter278 infra/postgres/ Drizzle schema/repository + generated migrations279 market-data.module.ts feature-local Nest DI wiring280 index.ts PUBLIC feature API281 config/ validated runtime config282 infra/ transport selection + Protobuf asset resolution283```284285`trading-rpc` is a Nest hybrid application with two intentional listeners.286Cloudflare `api-gateway` calls the Connect endpoint through the private VPC287`Fetcher` binding. Node microservices call the separate native Nest gRPC port.288Both inbound adapters resolve the same feature input port from Nest DI; domain289and application code remain framework-free. Raw Connect plugin requests use290Fastify/Connect cross-cutting hooks; Nest guards, pipes, filters, and291interceptors apply to the native gRPC and Nest HTTP controllers, not implicitly292to Connect routes.293294**Admin service (`services/admin-rpc`):**295296```297src/298 index.ts composition root; the only env reader299 adapters/http.adapter.ts Nest/Fastify host + Connect plugin + gRPC listener300 features/authentication/301 domain/ credential-verifier and token-issuer ports302 application/ Login use case303 adapters/{connect,grpc}/ AuthService validation and safe error mapping304 infra/{configured,jwt}/ constant-time credentials + signed JWT adapter305 authentication.module.ts306 index.ts PUBLIC feature API307 features/coin-information/308 domain/ coin primitives, typed error, trading-rpc port309 application/ admin GetMarkets input port + orchestration310 adapters/{connect,grpc}/ AdminService transport validation/error mapping311 infra/grpc/ native gRPC TradingService client adapter312 coin-information.module.ts313 index.ts PUBLIC feature API314 platform/nest/ root module, interceptors, lifecycle providers315 config/ validated runtime config and downstream timeout316 infra/ transport selection + Protobuf asset resolution317```318319`admin-rpc` exposes `auth.v1.AuthService/Login` and320`admin.v1.AdminService/GetMarkets` over Connect and native gRPC. Authentication321validates server-side configured credentials and issues a short-lived HS256 JWT322using the same environment secret enforced by api-gateway. The market-data323application use case calls a transport-neutral driven port; the324feature-local gRPC adapter calls `trading.v1.TradingService/GetMarkets` on325`TRADING_RPC_GRPC_URL`. It validates the downstream response with Zod, applies326`TRADING_RPC_TIMEOUT_MS`, and maps transport/response failures to a typed safe327domain error. CoinGecko and market persistence remain owned by `trading-rpc`.328329**Edge gateway (`services/api-gateway`):**330331```332src/333 index.ts Cloudflare composition root334 adapters/ generic Worker/Hono composition only335 cloudflare/ runtime binding types336 http/ app, error, request-scope, runtime middleware337 features/338 README.md capability clone guide + naming contract339 access-control/340 application/ authorization input/output ports + use case341 adapters/http/ capability-owned Hono middleware342 infra/hono/ JWT verifier implementation343 index.ts PUBLIC feature API344 rate-limiting/345 domain/ policy, identifier, token-bucket aggregate + port346 application/ consume-token + enforce-rate-limit use cases347 adapters/{http,cloudflare}/348 Hono middleware + Durable Object inbound adapter349 infra/cloudflare/ Durable Object port/repository implementations350 index.ts PUBLIC feature API351 rpc-routing/352 domain/ typed routing errors353 application/ endpoint port + routing use case354 adapters/http/ catch-all Hono handler355 infra/{api-core,cloudflare}/356 local endpoint + private Trading RPC proxy357 index.ts PUBLIC feature API358 shared/{access-policy,logging}/359 cross-feature policy and logging ports/adapters360 config/ validated bindings + operational options361```362363Hard rules (enforced by `scripts/check-backend-architecture.ts` through each364workspace's `lint:architecture` command):3653661. Every feature exposes `features/[capability]/index.ts`; production consumers367 outside the slice import only that Public API. Tests may import the unit under368 test directly.3692. Same-layer feature slices are isolated and MUST NOT import one another. Move370 a genuinely shared primitive downward into `shared/`; otherwise compose above.3713. **Handlers/adapters are thin** — validate external input, invoke the use case,372 and map domain results/errors to the transport. They contain no business rules.3734. **Application use cases** own orchestration, depend only on domain models,374 ports, and allowed Shared primitives, and are unit-tested (target ≥ 80%).3755. **Domain code** owns invariants and imports only its own domain. It never376 references frameworks, generated contracts, runtime globals, or outer layers.3776. Add ports/repositories only for real external boundaries or persistence that378 must be substituted or isolated. Do not create controller/service/repository379 chains, generic repositories, or interfaces for pure local helpers.3807. Validate ALL external input with **Zod at the handler/adapter boundary**381 (`Z`-prefixed schema; proto gives structural types, Zod gives semantic ones).3828. Services throw typed domain errors. Connect/HTTP/gRPC adapters map them to safe383 transport errors/envelopes and NEVER leak internal messages.3849. Env/secrets are read only in the composition root or validated runtime-config385 boundary. Import `@packages/api-core` only via its root barrel.38610. After structural changes run all four relevant `lint:architecture` commands;387 the shared checker automatically discovers every `features/*` directory.38811. All backend services use TypeScript-only source and service-local389 architecture scripts. All local imports use configured390 aliases (`@/`, `@scripts/`, and the narrow `@repo/architecture-checker`391 tooling alias); relative imports are rejected by their architecture392 checkers.39312. All backend services require a validated `SERVICE_NAME` runtime value.394 Composition roots inject it into health and telemetry adapters; production395 code MUST NOT hardcode, derive, or silently default the logical service396 identity. Worker resource names, package names, and runtime labels are397 separate concerns.398399### HTTP layer400401- Components MUST NOT call `fetch()`/axios.402- `apps/dapp` data flows UI → model hook → same-slice `api/` → a configured403 transport from `@/shared/api`. ConnectRPC modules use typed shared clients;404 REST/BFF modules use `xhr`. Components call neither transport directly.405- `apps/admin` slice `api/` modules use `apiClient` from `@/shared/api`406 (Connect-RPC client with the auth interceptor pre-wired). Only407 `shared/api/api-client.ts` may call `createApiClient` directly.408409### Server vs Client Components (`apps/dapp` only)410411- Default is a Server Component. Add `'use client'` ONLY for `useState`,412 `useEffect`, `useRef`, event handlers, `useQuery`, or `window`/`document`.413- NEVER `'use client'` on `layout.tsx`. Push the directive as deep as possible.414- Fetch data in Server Components when possible (e.g. read iron-session415 server-side instead of a client fetch).416417## Naming conventions418419| Thing | Convention | Example |420|-------|------------|---------|421| Component file | kebab-case | `user-profile.tsx` |422| Component export | PascalCase | `export function UserProfile()` |423| Hook file | `use-` + kebab | `use-user-profile.ts` |424| Zod schema | `Z` prefix | `const ZUser = z.object(...)` |425| Type (derived or re-exported) | `T` prefix | `type TUser = z.infer<typeof ZUser>` |426| Constant | SCREAMING_SNAKE | `API_ROUTES.GET_USER` |427| Zustand store | `use` + Name + `Store` | `useUserStore` |428| Service | camelCase + `Service` | `userService` |429| Default export | ONLY `page.tsx`, `layout.tsx`, `not-found.tsx`; framework-native `.astro` component exports are also allowed | — |430431## Code patterns432433```typescript434// features/sign-in/model/login.schema.ts — schema first, type derived435export const ZLoginInput = z.object({436 email: z.email(),437 password: z.string().min(1),438})439export type TLoginInput = z.infer<typeof ZLoginInput>440441// features/sign-in/api/login.api.ts — same-slice I/O through Shared442export const login = (input: TLoginInput): Promise<void> =>443 xhr(API_ROUTES.AUTH_LOGIN, { method: 'POST', body: input })444445// features/sign-in/model/use-login.ts — model orchestrates its slice API446export const useLogin = () => useMutation({ mutationFn: login })447448// features/sign-in/index.ts — minimal client public API449export { LoginForm } from '@/features/sign-in/ui/login-form'450451// features/sign-in/index.server.ts — separate server-only public API452import 'server-only'453export { verifyCredentials } from '@/features/sign-in/model/verify-credentials.server'454```455456Import order: React/Next → external packages → `@/shared/*` → `@/entities/*` →457`@/features/*` → `@/widgets/*` → `@/screens/*` → `@/bootstrap/*` → `@root/*` →458styles. Frontend source, tests, and framework entrypoints never use relative459module specifiers; framework-generated files are the only exception. `import type`460last.461462## Error handling463464- Error boundaries (`error.tsx` per dapp route segment; router `errorElement`465 in admin) MUST report via `Sentry.captureException` and show a generic466 message — NEVER render raw `error.message`.467- Services throw typed domain errors; adapters map HTTP errors to them.468- Server Actions return `{ success, data?, error? }` — never throw, never echo469 internal error text to the browser.470- NEVER swallow errors — log via `logger`, then re-throw or return error state.471 Failed queries in lists/tables show an error + retry, not an empty state.472- 404s: `notFound()` from `next/navigation` — never return null UI.473474## Security475476- Application configuration MUST use the validated env module477 (`apps/dapp/src/shared/config/env.ts`, `apps/admin/src/shared/config/env.ts`).478 Direct reads are allowed only for framework/tool-owned execution flags such as479 `NODE_ENV`, `CI`, `NEXT_RUNTIME`, and build-plugin switches inside framework480 config, instrumentation, test-runner config, or validated config adapters.481 Document every application variable in the workspace `.env.sample`.482- Validate ALL external input with Zod at trust boundaries (server actions,483 route handlers, RPC handlers).484- Server modules use `import 'server-only'`.485- CSP: dapp builds a nonce-based CSP in `src/bootstrap/proxy/proxy.ts`, delegated by486 root `proxy.ts` — the nonce and CSP MUST be set on request headers (not only487 the response). Admin/landing ship static headers via `public/_headers`.488- Backend CORS is allowlist-driven via `CORS_ORIGINS` (handled in489 `packages/api-core` and the Node RPC services).490- NEVER: committed secrets, `eval()`, `new Function()`,491 `dangerouslySetInnerHTML` without DOMPurify.492493## Performance & accessibility494495- dapp images: `next/image` with explicit dimensions — never raw `<img>`.496- Code-split at route level (`React.lazy` in admin; `next/dynamic` +497 `{ ssr: false }` for heavy below-the-fold dapp components).498- No barrel re-exports that break tree-shaking — `export type` separately.499- WCAG 2.2 AA: semantic HTML (never `<div>` + onClick), keyboard navigation,500 meaningful `alt`, a visible `<label>` or `aria-label` per input, contrast501 ≥ 4.5:1. Ark UI handles a11y — don't override `aria-*` without reason.502503## Testing504505| Workspace | Test location |506|-----------|---------------|507| `apps/dapp` unit | `src/__test__/**` (mirrors `src/`) |508| `apps/dapp` E2E | `e2e/*.test.ts` (Playwright; fixtures in `e2e/fixtures/base.ts`) |509| `apps/admin` unit | `src/__test__/**` (mirrors `src/`) |510| `services/*`, `packages/*` | colocated `src/*.test.ts` |511512- Dapp and admin tests mirror FSD paths, import the unit under test directly,513 and mock only the lower-layer I/O boundary when isolation is needed.514- Any mock of `index.server.ts` MUST use a factory so Vitest does not evaluate515 the real `server-only` graph first.516- Mock env config where needed:517 `vi.mock('@/shared/config', () => ({ env: { ... } }))`.518- Naming: `describe('[ServiceName]')` > `it('should [behavior] when [condition]')`.519- Test behavior/outcomes, never implementation details. Coverage target ≥ 80%520 for feature/entity `api` and `model` logic.521522## Git & PRs523524Enforced by husky hooks (`.husky/validate-commit.sh`, `validate-branch.sh`) —525off-format commits/branches are rejected locally.526527- Commit header (Conventional Commits): `type(scope)[!]: description`528 - Types: `build|chore|ci|docs|feat|fix|hotfix|perf|refactor|release|revert|style|test`529 - Scope: optional, lowercase — use the workspace or area you touched, e.g.530 `(dapp)`, `(admin)`, `(landing)`, `(trading-rpc)`, `(gateway)`, `(protocol)`, `(infra)`531 - `!` after type/scope marks a breaking change532 - Keep the header ≤ 100 chars (soft limit — hook only warns)533 - `Merge/Revert/fixup!/squash!` headers bypass validation534 - Examples: `feat(dapp): add user profile page` ·535 `fix(trading-rpc): handle empty echo payload` ·536 `refactor!: drop the legacy RPC client`537- Branch: `type(scope)/short-kebab-description` — lowercase kebab; scope538 optional. Examples: `feat(dapp)/user-profile`, `chore/upgrade-turborepo`.539 Exempt: `main|develop|staging|release/*|hotfix/*|dependabot/*|renovate/*`.540- PR: title follows the commit convention; body has Summary, Test plan,541 Breaking changes.542- Keep PRs at or below 150 changed files and 20,000 changed lines. A deliberately543 larger atomic migration requires explicit human scope review and the544 `large-change-reviewed` label before CI may proceed.545- Versioning/changelogs are automated (release-please manifest mode) — NEVER546 hand-edit `CHANGELOG.md` or `version` fields.547548## Deployment549550- `infra/docker` is the single source of truth for all Dockerfiles and Compose551 configuration. Workspaces MUST NOT contain their own Dockerfiles. Keep one552 Dockerfile per deployable image and environment differences in Compose553 overlays; run `make check-docker` after changes.554- All application deploys are CI-driven via `.github/workflows/deploy.yml`, gated on a555 green CI run: push to `develop` → staging; push to `main` → production556 (behind a required manual approval in the GitHub `production` Environment).557 NEVER run `wrangler deploy` / `pnpm deploy:*` from a local machine.558- Cloudflare targets use `wrangler.jsonc` `env.staging` / `env.production`559 blocks with distinct worker names — deploys MUST pass an explicit560 `--env staging|production`.561- Rollback: `wrangler rollback --env production` (Workers keep prior versions).562- `services/{admin-rpc,trading-rpc}` build Docker images from563 `infra/docker/{admin-rpc,trading-rpc}.Dockerfile` (multi-stage, non-root,564 `/healthz` healthcheck); `infra/docker/postgres.Dockerfile` supplies the565 existing PostgreSQL 18 + pgBackRest/R2 recovery runtime. All three images566 deploy to one private EC2 host per environment. Terraform under567 `infra/terraform` owns VPC, fixed EC2, protected encrypted EBS, ECR, IAM,568 Secrets Manager, KMS, observability, Cloudflare Tunnel, and Workers VPC Services. Infrastructure569 plan/apply runs only through `.github/workflows/terraform.yml`; never apply570 Terraform locally. Application CI uses GitHub OIDC, immutable ECR commit-SHA571 tags, ECR vulnerability scanning, and SSM rollout—never SSH. AWS RDS is not572 part of this topology; do not bypass the repository's Docker PostgreSQL573 backup/PITR/restore design.574- Secrets are provisioned per environment via GitHub Environment575 secrets/vars and `wrangler secret put` — never committed, never in576 `wrangler.jsonc` `vars`.577578## Gotchas (read before debugging)579580- **`server-only` under Vitest**: the package throws when imported outside RSC.581 It is globally mocked in dapp test setup; a `vi.mock` of any module that582 imports it MUST provide a factory (auto-mocks still evaluate the real module583 first).584- **Turbo strict env mode**: a new build-time env var MUST be added to the585 `build.env` allowlist in `turbo.json`, or it is silently stripped from the586 build AND excluded from the cache key.587- **Generated code — never hand-edit**: `packages/protocol/src/gen/**`588 (regenerate with `pnpm --filter @packages/protocol generate`) and589 `apps/*/src/styled-system/**` (Panda CSS, regenerated by `prepare`).590- **`wrangler.jsonc` files are JSONC** — comments are allowed and load-bearing;591 don't "fix" them into plain JSON.592- **Dependency overrides** live in `pnpm-workspace.yaml` (`overrides:`), not in593 `package.json` — pnpm 11 ignores the `package.json` `pnpm` field.594- **dapp reads `.env` at build time** — `.env*` files are part of turbo's build595 inputs; changing one invalidates the cache (by design).596597## Anti-patterns598599| ❌ Never | ✅ Instead |600|---------|-----------|601| `fetch()`/axios in a component | model hook + same-slice API |602| Raw `fetch()` in API modules | `@/shared/api` (dapp) / `@/shared/api` client (admin) |603| `'use client'` on `layout.tsx` | Server Component always |604| `useState` for form fields | react-hook-form |605| `console.log` | `logger` from `@/shared/lib/logger` |606| Hardcoded URLs | `API_ROUTES` / `WEB_ROUTES` from `@/shared/routes` |607| Deep slice imports from another slice/framework file | the slice Public API |608| Relative frontend import/export | the configured `@/` or `@root/` alias |609| Cross-slice imports on the same layer | compose above or extract downward |610| `any` / `as any` | `unknown` + type guard |611| Application env read outside a config boundary | validated env config module |612| Default export on non-page files | named exports |613614## MCP tools (when available)615616- **code-review-graph** — use before reading raw files:617 `semantic_search_nodes` (find symbols), `get_impact_radius` (blast radius618 before refactoring), `detect_changes` (staged-change risk),619 `query_graph pattern="callers_of"` (find callers).620- **Context7** — current library docs: `resolve_library_id` →621 `get_library_docs` (prefer over stale training data).622
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| n8n-io/n8npackages/@n8n/agents/AGENTS.md · 201k | AGENTS.md | buildteststylearch+3 | 100/100 | 14 days ago | |
| aaif-goose/gooseAGENTS.md · 53k | AGENTS.md | setupbuildtestlint-format+7 | 100/100 | 8 days ago | |
| duckduckgo/content-scope-scriptsspecial-pages/AGENTS.md · 70 | AGENTS.md | buildteststylearch+3 | 100/100 | 14 days ago | |
| deepseek-ai/deepseek-harnessnative/landlock-run/AGENTS.md · 104k | AGENTS.md | setupteststylearch+3 | 100/100 | today | |
| code-yeongyu/oh-my-openagentpackages/web/AGENTS.md · 68k | AGENTS.md | setupbuildtestlint-format+6 | 100/100 | 13 days ago | |
| TryGhost/Ghoste2e/AGENTS.md · 55k | AGENTS.md | setupteststylearch+2 | 100/100 | today | |
| mui/material-uiAGENTS.md · 99k | AGENTS.md | setupbuildtestlint-format+9 | 100/100 | 14 days ago | |
| elastic/elasticsearchx-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/ml/AGENTS.md · 78k | AGENTS.md | buildtestlint-formatstyle+2 | 100/100 | 14 days ago |
A badge carrying the measured quality of the strongest agent config file in this repository, out of 100. It reads from this index every time somebody loads your page, so it changes when the measurement changes and there is nothing to keep up to date. Free, no account, and the value is not something you or we can set by hand.
[](https://rulestack.kynth.studio/configs/noahduongmaster-vibe-code-stack-for-ceos-agents)Would rather not hotlink us? Every badge is also served in shields.io’s endpoint schema, so shields renders the image and your readers never talk to our domain:
Published by Toolproof, the masthead over this index and eight others. The method behind the number is at toolproof.kynth.studio/methodology, and the whole thing is readable as JSON with no key at /api.
(0.60)
(0.60)