Purpose
Review code changes to detect bugs, design violations, spec violations, and security risks in the fullcase-web Next.js 16 + TypeScript + Firebase client-SDK app.
Serves as the shared ruleset for both automated PR reviews (referenced by subagents) and local manual reviews (direct invocation).
Review Procedure
Step 1: Obtain the review target
Obtain the diff based on the provided arguments.
When a PR number is specified:
bashgh pr diff <PR-number>
When a branch is specified:
bashgit diff <base-branch>...<target-branch>
If the base branch is omitted, default to main.
When nothing is specified (local review of own changes):
bashgit diff git diff --cached git status --short
If there are untracked new files, read the file contents directly for review.
For PR reviews (via the review-pr command): the diff is provided by the caller. Skip this step.
Step 2: Load project rules
Read AGENTS.md and CLAUDE.md at the project root to understand project-specific rules. AGENTS.md is the canonical source of truth for architecture, data model, folder layout, and code-style rules.
Step 3: Execute review
Review the diff based on the "Review Criteria" below. If there are no findings, report "No issues found".
Step 4: Quality check
Before outputting findings, self-check against the following:
- Does the finding match a pattern in
examples/bad-review.md? - Is it something ESLint / Prettier /
tsc --noEmitwould catch? - Is it a personal preference with no objective basis?
Exclude any findings that match.
Step 5: Output
Output only findings that pass the quality check.
Review Criteria
Must detect
- Bugs / Logic errors — Unintended behavior, missed edge cases, unhandled
null/undefined, missingawait, stale closures, unsubscribed listeners - Security — Hardcoded secrets, unsafe input, PII leaks, auth-guard bypasses, storage path abuse, open redirects,
dangerouslySetInnerHTMLwithout sanitization - Design violations — Firebase SDK called directly from React components,
firebase-adminusage, Server Actions / Route Handlers used for Firestore or Storage, types defined outsidetypes/, manual edits tocomponents/ui/, raw<img>instead ofnext/image - Firestore data-model violations — Writing date as
new Date()/ ISO strings instead ofserverTimestamp()/Timestamp; missingmemberIdsupdate when adding a member; inconsistent collection paths (e.g.,testcasesvstestCases) - Invite / Auth flow defects — Incorrect handling of
pendingInviteinsessionStorage; invite batch not atomic;(dashboard)/layout.tsxguard weakened or replaced with serverredirect()
Must NOT flag
- Issues detectable by linter / formatter — Prettier formatting, semicolons, single-quote rule,
simple-import-sort, unused-imports,max-lenwrapping - Auto-generated files —
.next/,next-env.d.ts, generated types - Naming preferences without basis — Do not flag if naming follows project conventions (kebab-case files, PascalCase components, camelCase hooks/services, SCREAMING_SNAKE_CASE env/constants)
- Code outside the diff — Unchanged code is out of scope
- Test coverage alone — Do not flag missing tests unless there is a concrete bug risk
Severity Definitions
| Level | Icon | Definition | Examples |
|---|---|---|---|
| CRITICAL | 🔴 | Security vulnerability, data loss / leak risk, guaranteed production breakage | Secret leak, auth guard bypass, dangerouslySetInnerHTML with raw user input, firebase-admin used on client |
| HIGH | 🔴 | Mandatory rule violation, definite bug | Firebase SDK imported into a component, any type, date stored as ISO string, <img> instead of next/image, missing await on async write |
| MEDIUM | 🟡 | Quality / performance improvement | Unnecessary onSnapshot where getDocs suffices, missing loading/error in a hook, N+1 Firestore reads, inline object prop causing memoized-child re-renders |
| LOW | 🟢 | Minor improvement suggestion | Small refactor opportunity, non-critical naming polish, optional comment |
Output Format
Each finding must be written in English.
🔴 [CRITICAL] `path/to/file.tsx:42` Firebase SDK is imported directly inside a React component. Project rule: components consume hooks; hooks call services; only services touch the Firebase SDK. Suggestion: Move the Firestore call into `services/<feature>-service.ts` and expose it via a hook under `hooks/`.
When there are no findings:
✅ No issues found
Project-Specific Checkpoints
Architecture & Data Access
- Component → Hook → Service → Firestore SDK. Never skip a layer.
services/*contains pure async functions with zero React imports.hooks/*always exposeloadinganderror.firebase-adminis forbidden. Server Actions / Route Handlers are forbidden for Firestore / Storage operations.- Types live in
types/and are imported via@/types.
Next.js 16 App Router
- Route groups:
(auth)public,(dashboard)protected,invite/[token]public. (dashboard)/layout.tsxmust be a client component and redirect viarouter.replace('/login')insideuseEffect. Never use the server-onlyredirect()helper.- Use
next/imageeverywhere;firebasestorage.googleapis.comandlh3.googleusercontent.commust be innext.config.tsremotePatterns. - Use
next/fontfor fonts; never add raw<link>font tags.
TypeScript
strict: true. Neverany(explicit or implicit).- Use
unknown+ narrowing,Omit<T, 'id'|'createdAt'|'updatedAt'>for create payloads,Partial<Pick<T, ...>>for update payloads.
Firestore
- Always
serverTimestamp()orTimestampfor date fields. Nevernew Date()or ISO strings in stored values. - Use
writeBatchfor multi-document logical operations (e.g., invite accept). - Use
setDoc(..., uid)— notaddDoc— when a document ID must equal the user's UID. - Update
projects/{id}.memberIdswhenever a member is added/removed (security rules depend on it).
Forms & UI
- Forms use
react-hook-form+zod+ shadcnFormprimitives. - shadcn
AlertDialogfor all destructive confirmations. Skeletonfor loading states — not spinner-only screens.- No CSS files, no CSS modules, no inline
styleprops (unless Tailwind cannot express the value). No custom classes inglobals.css. components/ui/is shadcn CLI output — never manually edit.
Error Handling
- All async component actions wrapped in
try/catch. - User-facing errors via
toast.error(...)with a human-readable message; never raw Firebase error codes. console.erroronly whenprocess.env.NODE_ENV !== 'production'.- No
console.login committed code.
Security & PII
- Firebase config only via
process.env.NEXT_PUBLIC_FIREBASE_*. - No user emails / names / phone numbers in logs. Full UIDs too — prefer last-4-only (
...ab12). - Storage paths must match the documented prefixes; enforce the documented MIME/size caps.
- Validate invite tokens before writing
members/memberIds.
Reference Examples
Refer to the following for review quality standards:
- Good review examples:
examples/good-review.md - Anti-patterns to avoid:
examples/bad-review.md
Post-review feedback:
If you discover missed issues or new pitfalls from this review, add them to the checklist via /update-review-checklist.


