Skip to content

Latest commit

 

History

History
71 lines (60 loc) · 3.81 KB

File metadata and controls

71 lines (60 loc) · 3.81 KB

AGENTS.md

Guidance for AI coding agents working in this repository. CLAUDE.md is an identical copy for tools that read that filename; keep both in sync.

Project

Serql — Google Search Console analytics. Next.js 16 App Router (Turbopack), React 19, TypeScript 5 strict, Tailwind v4, shadcn/ui, Drizzle ORM on Postgres (Neon or any Postgres), Clerk auth, Upstash-compatible Redis (optional), Google APIs for GSC data. Open core: AGPL-3.0 core plus a commercially licensed enterprise layer in src/ee/ (Stripe billing, marketing/legal pages, telemetry, support widget). Read docs/ARCHITECTURE.md before larger changes.

Commands

npm run dev            # dev server
npm run verify         # eslint (zero warnings) + tsc — run before claiming done
npm run test:unit      # core unit tests, no credentials needed (node:test via tsx)
npm run test:ee-unit   # enterprise-layer unit tests, no credentials needed
npm test               # Playwright e2e (needs a running app + Clerk + GSC data; see tests/README.md)
npm run db:generate    # Drizzle migration from schema changes
npm run db:migrate     # apply migrations
docker compose up -d postgres   # local Postgres; add --profile redis for a Redis REST proxy

Layout

  • src/app/(app)/ — authenticated shell. layout.tsx calls requireAppUser() (Clerk) then getAppEntitlement() from @/lib/access as the access gate.
  • src/app/(auth)/, src/app/share/[token]/ (public read-only), src/app/api/*.
  • src/app/page.tsx renders src/components/core-home.tsx unless NEXT_PUBLIC_EE_MARKETING=true, which swaps in src/ee/marketing.
  • src/lib/access/ — the only core module that imports @/ee/billing. With STRIPE_SECRET_KEY unset it uses the "unlimited" provider (everyone has access, no seat/property limits). Core code reads entitlement.limits and entitlement.canSponsorMembers; it never reads billing tiers directly.
  • src/ee/ — enterprise layer. src/ee/index.ts holds the env predicates (isBillingEnabled, isMarketingEnabled, …). Route files under src/app/ that belong to ee are one-line re-export shims.
  • src/config/site.ts — every URL, name, cookie domain, and support address. Never hardcode serql.io; use siteConfig, publicUrlFor(), appUrlFor().
  • src/config/csp.ts — CSP built from configured integrations.
  • src/lib/db/schema.ts — single-file Drizzle schema. src/lib/db/index.ts picks the Neon or node-postgres driver from DATABASE_URL / DB_DRIVER.
  • src/lib/auth/requireAppUser(), getAccessiblePropertyIds(), authorizeProperty() (all API routes must scope by these).
  • src/lib/gsc/ — GSC queries, caching (Redis optional), sync.
  • src/lib/google-oauth/ — 3-legged Google OAuth; tokens AES-encrypted at rest with TOKEN_ENCRYPTION_KEY; OAuth state lives in an encrypted cookie.
  • src/hooks/ TanStack Query hooks; src/components/ui/ shadcn primitives.

Rules

  • Core (src/ outside src/ee/) must not import @/ee except via src/lib/access/ and the allowlisted shims. ESLint and the CI boundary job enforce this. Do not add new allowlist entries without a reason.
  • Do not edit src/ee/** unless the task is explicitly about the hosted product; it is under a different license.
  • API routes: authorize with getAccessiblePropertyIds() / authorizeProperty(), return errors via handleApiError(), never leak stack traces.
  • Zero ESLint warnings. Path alias @/*src/*. Unit tests are colocated *.test.ts(x) and must run without env vars or network.
  • Never commit .env*, credentials, or Playwright .auth/ state.
  • Env is read from .env.local in dev; see .env.example for every variable.

Maintainer tooling (optional)

Maintainers track work with Beads (bd prime, bd ready, bd close). It is not required for contributors and is not part of the build.