SERIES: AI-POWERED DEV WORKFLOW · POST 10 OF 10
Most code reviews I have seen catch style issues and miss security ones. The author forgot to add a comment, the reviewer flags it. The route has no auth check, nobody catches it until a penetration test or a prod incident six months later.
Claude reviews code differently. It does not get tired, does not skip the security section because the meeting is in ten minutes, and does not miss the N+1 query because it is buried in a loop. Give it the right context and a structured prompt, and it returns a review that covers all six dimensions a senior engineer would check — consistently, every time.
The Six Dimensions of a Real Code Review
A thorough review is not “does this look right.” It is six specific checks, each with a different lens:
| Dimension | What to check |
|---|---|
| Correctness | Does the code do exactly what the ticket/FRD says? Not approximately — exactly. Check every acceptance criterion. |
| Security | Unprotected routes, missing auth checks, SQL injection via raw queries, exposed env vars, user input passed directly to the DB. |
| Performance | N+1 queries (fetching inside a loop), missing DB indexes, unnecessary full-table scans, synchronous blocking in async routes. |
| Readability | Function length, variable naming, magic numbers, deeply nested conditionals, unclear return types. |
| Test coverage | Are the new code paths covered? Happy path, at least one negative, any role-based branches. Not whether tests exist — whether the new paths are actually exercised. |
| Edge cases | Null/undefined inputs, empty arrays, concurrent writes, files with 0 bytes, strings that are longer than the DB column allows. |
Setting Claude Up with the Right Context
A review prompt without context produces generic feedback. “This function is long” is not useful. “This function violates the business rule in FRD section 3.2 that says a user cannot approve their own upload” is useful.
Give Claude three things before you paste the code:
PROMPT 1 - Load Context Before Review
1. Load CLAUDE.md from the project root.
This gives Claude your stack, conventions, and business rules.
2. Here is the Jira ticket this code implements:
[Paste the ticket: summary, user story, acceptance criteria]
3. Here is the FRD section this feature is based on:
[Paste the relevant FRD entry]
Read all three. Confirm you are ready to review.
I will paste the code next.
The confirmation step matters. If Claude has processed all three, it will be able to say “this code does not handle the role restriction from FRD section 3.2” rather than “you might want to add access control.” Specificity is the difference between a useful review and a generic one.
The Reusable Code Review Prompt Template
Once the context is loaded, use this template for every review. Copy it, fill in the brackets, and paste the code at the bottom:
REUSABLE CODE REVIEW TEMPLATE
----------------------------------------------
Review the following code for: [file path or feature name]
Check all six dimensions in this order:
1. CORRECTNESS — Does it fully implement the acceptance criteria?
Flag any criterion not covered by the code.
2. SECURITY — Unprotected routes, missing auth, injection risks,
exposed secrets, user input passed unvalidated to DB or storage.
3. PERFORMANCE — N+1 queries, missing indexes, synchronous blocking,
unnecessary re-renders, expensive operations in request path.
4. READABILITY — Naming, function length, magic numbers,
deeply nested logic, unclear return types.
5. TEST COVERAGE — Which new code paths have no test? List them.
6. EDGE CASES — Null inputs, empty arrays, concurrent writes,
boundary values, missing error handling.
For each issue found:
- State the severity: Critical / High / Medium / Low
- Explain the impact in one sentence
- Suggest a specific fix (not "add validation" — show what to add)
If a dimension has no issues, write "No issues found."
[PASTE CODE HERE]
The Worked Example: ClientHub Upload Route
Here is a realistic Next.js API route for the deliverable upload feature. It has three intentional bugs — these are the kinds of issues that slip through human review when the reviewer is moving fast:
// app/api/deliverables/upload/route.ts
import { NextRequest, NextResponse } from 'next/server'
import { prisma } from '@/lib/db'
import { uploadToStorage } from '@/lib/storage'
export async function POST(req: NextRequest) {
// BUG 1: No authentication check.
// Any unauthenticated request can reach this handler.
const formData = await req.formData()
const file = formData.get('file') as File
const projectId = formData.get('projectId') as string
const title = formData.get('title') as string
// BUG 2: No file size or type validation.
// A 2GB video or a .exe will pass straight through.
const fileUrl = await uploadToStorage(file)
const deliverable = await prisma.deliverable.create({
data: { title, fileUrl, projectId, status: "PENDING_REVIEW" },
})
// BUG 3: N+1 query. For each notification recipient,
// a separate DB query fires. 10 team members = 10 queries.
const members = await prisma.projectMember.findMany({
where: { projectId },
})
for (const member of members) {
const user = await prisma.user.findUnique({ // N+1 here
where: { id: member.userId },
})
await sendNotificationEmail(user.email, deliverable.id)
}
return NextResponse.json({ deliverable }, { status: 201 })
}
Running the review template against this route produced five findings across four dimensions. The three intentional bugs were caught, plus two additional issues Claude found that were not planted:
Claude’s Review Output
SECURITY — Critical
Issue: The route has no authentication check. Any request reaching POST /api/deliverables/upload will be processed regardless of whether the caller is logged in.
Impact: Unauthenticated users can upload files to your storage and create deliverable records in your database.
Fix: Add getServerSession() at the top of the handler. Return 401 if no session exists. Also verify that the authenticated user is a PM on the given projectId.
PERFORMANCE — High
Issue: N+1 query inside the notification loop. For each member in projectMembers, a separate prisma.user.findUnique() call fires.
Impact: A project with 15 members triggers 1 + 15 = 16 DB round-trips per upload. At scale this is a significant latency spike.
Fix: Replace the loop with a single query using include or findMany with awhere: { id: { in: memberIds } }clause. Fetch all users in one round-trip, then map over the result.
VALIDATION — High
Issue: No file size or MIME type validation before upload. The file is passed directly to uploadToStorage().
Impact: Any file type or size is accepted. A malicious user can upload a 2GB binary, exhaust storage, or attempt to store executable files.
Fix: Check file.size against the 50MB limit from the FRD before calling uploadToStorage(). Check file.type against an allowlist of permitted MIME types (PDF, PNG, JPEG, DOCX). Return 400 with a clear error if validation fails.
TEST COVERAGE — Medium
No tests exist for this route. The three issues above have no test coverage. At minimum, add integration tests for: (1) unauthenticated request returns 401, (2) oversized file returns 400, (3) valid request creates deliverable and sends notifications.
CORRECTNESS — Low
The route does not verify that projectId is a valid, active project before creating the deliverable. A request with a non-existent projectId will cause a Prisma foreign key constraint error rather than a clean 400 response.
The two additional findings — missing projectId validation and missing test coverage — were not planted. Claude found them because the FRD specifies that projectId must refer to an active project, and because CLAUDE.md states that every API route must have at least one integration test. That is the value of loading context before the review.
Self-Review Before Submitting a PR
The most efficient time to catch an issue is before anyone else sees the code. Use this prompt as the last step before you open a PR:
PROMPT 3 - Self-Review Before PR
Review this code as if you are a senior engineer on this team
who is doing a pre-submission check before I open a PR.
Tell me:
1. What would get flagged in a real code review?
2. What would you not merge without changing?
3. What is fine but could be improved in a follow-up?
Be specific and honest. Do not soften findings.
[PASTE CODE HERE]
Running this prompt before opening a PR on ClientHub caught the missing projectId validation before anyone else saw it. One prompt, two minutes, one less comment in the PR review.
What Claude Can’t Do in Code Review
Claude is not a replacement for running your test suite, doing a staging deployment, or having a senior engineer who knows the production history look at the code. These are the things it cannot catch:
| Limitation | What it means in practice |
|---|---|
| Can’t run tests | Claude reviews code statically. It cannot execute the code, run your test suite, or verify that the output is actually correct at runtime. |
| Can’t catch environment issues | Missing env vars, mismatched DB schema versions, OS-specific path issues — these only appear when the code runs. Claude cannot see your environment. |
| Doesn’t know your traffic | Claude can spot an N+1 query, but it does not know if that route gets called 10 times a day or 10,000. Prioritise its findings based on your own traffic patterns. |
| May miss business context | Claude knows what you gave it. If a business rule lives only in someone’s head and not in the FRD or CLAUDE.md, Claude cannot flag violations of it. |
| Always verify suggested fixes | Claude’s suggested fixes are starting points, not final code. Read them, understand them, test them. Do not paste and ship. |
The rule of thumb: Use Claude to catch what is visible in the code. Use your test suite to catch what only appears at runtime. Use staging to catch what only appears in your environment. They are not substitutes for each other.
The Complete Workflow — All Ten Posts
That is the full series. Ten posts, one project, one complete workflow from idea to shipped code. Here is what you built:
| Post | What you did |
|---|---|
| Post 1 | BRD in 20 minutes — brief Claude on the project, iterate section by section, export a complete document. |
| Post 2 | FRD from BRD — translate business goals into structured functional specifications, one feature at a time. |
| Post 3 | Alignment — build a traceability matrix, find gaps between BRD and FRD before anyone starts building. |
| Post 4 | Client sign-off — generate a client-friendly summary, handle change requests, produce a formal sign-off document. |
| Post 5 | Confluence pages — auto-generate wiki pages with correct markup from your BRD and FRD, push via MCP. |
| Post 6 | Jira tickets — extract epics, stories, and tasks from the FRD, push directly to Jira via the Atlassian MCP. |
| Post 7 | Test cases — generate a complete, FRD-grounded test suite covering positive, negative, edge case, and role-based scenarios. |
| Post 8 | CLAUDE.md — write the context file that makes every coding session start with full project knowledge. |
| Post 9 | Test case review — cross-check against the FRD, find duplicates, generate gap-filling tests before QA. |
| Post 10 | Code review — six dimensions, a reusable prompt template, and an honest list of what Claude cannot do. |
Every post in this series uses a real project, real prompts, and real output. Nothing here is theoretical. You can take any single post and apply it to your next sprint on Monday.
If you have questions, have found a better prompt for any of these steps, or want to share how you have adapted this workflow for your team, drop a comment. I read everything and reply to most of it.
Series complete. All ten posts are free to read and share at kalaatelier.com. If this series saved you time, pass it on to a developer who would use it.