Writing a Functional Requirements Document with Claude Code

SERIES: AI-POWERED DEV WORKFLOW · POST 2 OF 10

If the BRD is the “what,” the FRD is the “how.” Jump straight from a BRD to writing code without one, and you will spend weeks in a loop of “that’s not what I meant” conversations. I know because I’ve been on both sides. As the developer who got a vague requirement and had to guess. And as the PM realising mid-sprint that I never actually specified what should happen when a file upload fails.

The FRD stops that loop before it starts. It tells your developer exactly what to build, what the edge cases are, what “done” looks like, and what the system should do when things go sideways. This post shows how to write one using Claude Code — continuing with the ClientHub project from Post 1.

If you haven’t read Post 1 yet, start there. This post picks up directly from the BRD we built.

The Difference Between a BRD and an FRD

Here’s the quickest way I explain it to anyone new on a project.

The BRD is written for the client and the PM. The FRD is written for the developer and QA. Same project, same requirements — completely different level of detail.

BRD says thisFRD says this
“Users must be able to log in securely.”User goes to /login. Enters email + password. Submits. Valid: redirect to /dashboard. Invalid: inline error under password field. 5 failed attempts in 10 min: lock account, send reset email, show lockout message on screen.
“Clients must be able to review deliverables.”Client receives email within 5 min of upload. Clicks through to deliverable detail page. Sees file preview or download link. Clicks Approve or Reject. Comment required on Reject — form blocked if field is empty. Status update and notifications fire on both outcomes.
“The system should perform well and be secure.”All API routes require valid session token (JWT, 24h expiry). Dashboard page target: under 2s load on 4G. File upload limit: 50MB, enforced server-side. No raw SQL — parameterised queries only throughout.

A developer can build from the right column. They cannot build from the left column without making a dozen decisions you didn’t realise you were delegating to them. And those unspecified decisions are exactly where bugs and misalignments come from.

What Every FRD Entry Needs

I break every FRD feature into six parts. Some features need all six. Smaller ones might only need four. But in my experience, the part you skip is always the part someone asks about two weeks into build.

1. Feature Name and Description

One sentence. What it does and who it is for. Plain language — this is not a marketing blurb.

2. User Stories

Written as: “As a [role], I want to [action] so that [outcome].” Write one per user type that touches this feature. ClientHub’s Deliverable Approval Workflow has four: PM, Client, Developer, and System.

3. Acceptance Criteria

The checklist that tells QA when the feature is done. Every criterion should be binary — pass or fail, no interpretation required. “The approval flow should work smoothly” is not a criterion. “Comment field is required on rejection; form does not submit if empty” is.

4. Business Rules

The logic and constraints. Who can do what. What triggers what. What cannot happen. “Clients can only view deliverables on projects they are invited to” is a business rule. “Approved deliverables cannot be rejected after the fact” is a business rule.

5. Edge Cases

What happens when things go wrong, go slowly, or arrive in an unexpected order. File upload fails mid-transfer. Two users approve simultaneously. Email notification fails. File size hits the limit. These are where bugs live — and they never make it into the happy path.

6. UI/UX Notes

What should the screen show? What do the buttons say? What confirmation does the user see before a destructive action? Not a full design spec — that is the designer’s job. But enough that the developer is not making interface decisions alone.

How to Prompt Claude Code to Write the FRD

Start from the BRD, not a blank page. Claude already knows the project from the context in Post 1. If you are continuing the same session, it has that context. If you are starting fresh, paste the BRD file first.

Step 1 — Get the Feature List First

Before writing any spec, ask Claude to list what it plans to specify. This is the cheapest possible checkpoint — far easier to fix a missing feature at this stage than after you have written the spec.

PROMPT 1 - Extract Feature List from BRD

Read the BRD in docs/ClientHub-BRD-v1.md.
List every distinct feature that needs a functional specification.
Group them by area (e.g. Authentication, Project Management,
Deliverables, Invoicing, Notifications).
Do not write any specs yet. Just give me the feature list so I
can review it before we start writing.

For ClientHub, Claude identified 14 features across five areas. Two of them — project archiving and bulk deliverable upload — were not explicitly in my BRD but made sense from the context. I added archiving to scope and moved bulk upload to out-of-scope. That kind of early catch is exactly why you do this step.

Step 2 — Write One Feature Spec at a Time

Once the feature list is agreed, go one feature at a time. Give Claude the structure explicitly — otherwise it invents its own, and you end up with inconsistent formatting across features.

PROMPT 2 - Write FRD Entry (one feature at a time)

Write the full FRD entry for: Deliverable Approval Workflow.
Use exactly this structure:
- Feature Name and Description (1 sentence)
- User Stories (one per role: PM, Client, Developer)
- Acceptance Criteria (specific, binary, testable)
- Business Rules (constraints and logic)
- Edge Cases (at least 5)
- UI/UX Notes (what the screen should show or do)
- Dependencies (what must exist before this can be built)
Be specific. No vague language like "should work correctly."
Write acceptance criteria a QA engineer can test directly.

Step 3 — Push for More Edge Cases

Claude’s first draft on edge cases is usually decent. But it is not complete. After each feature spec, I always run this:

PROMPT 3 - Edge Case Review

Review the edge cases you listed for the Deliverable Approval Workflow.
What did you miss? Think about:
- Two users performing the same action at exactly the same time
- A required external service being unavailable (email, file storage)
- A user attempting an action they are not permitted to do
- Data at the boundary of a limit (file size, character count, time window)
- A slow connection causing the action to time out mid-way
Add any missing edge cases to the spec.

For ClientHub, this caught two things the first pass missed: what happens when two client stakeholders try to approve simultaneously, and what the system should do if the file storage service returns an error after the upload starts but before it completes. Both became business rules.

Step 4 — Check Role-Based Behaviour

This is the step I see people skip most often. Every feature that involves multiple user types needs to state explicitly what each role can and cannot do. Without this, the developer makes it up.

PROMPT 4 - Role-Based Behaviour Check

Review the Deliverable Approval Workflow FRD entry.
For every action in this feature, confirm which user roles can perform it
and which roles cannot. Format it as a table:
Action | PM | Client | Developer | Admin
If any role behaviour is not explicitly stated in the current spec,
add it to the Business Rules section.

Step 5 — Save the Complete FRD

PROMPT 5 - Save the FRD

Compile the complete FRD for ClientHub with all features we have specified.
Save it as docs/ClientHub-FRD-v1.md.
Use consistent section headers across all feature entries.
Add a table of contents at the top with a link to each feature section.

The Full FRD Entry: Deliverable Approval Workflow

Here is what Claude produced for ClientHub’s most complex feature. I made a few edits — mostly cutting over-explained sentences — but the structure and content are what came out of four prompt exchanges:

Feature Description

Allows a PM to upload a file deliverable to a project for client review. The client is notified, reviews the file, and either approves it or rejects it with a written comment. All relevant parties are notified of the outcome and every state change is recorded in the audit log.

User Stories

  • As a PM, I want to upload a deliverable to a project so the client can review and approve it without exchanging email attachments.
  • As a Client, I want to be notified when a deliverable is ready so I can respond quickly without the PM having to follow up.
  • As a Client, I want to approve or reject a deliverable with a written comment so my feedback is recorded and the team knows what to fix.
  • As a Developer, I want to know when a deliverable I worked on has been approved or rejected so I know whether to move on or prepare a revision.

Acceptance Criteria

  • PM can upload files up to 50MB (PDF, PNG, JPG, DOCX, ZIP accepted)
  • Client receives email notification within 5 minutes of deliverable upload
  • Deliverable detail page shows: file name, upload date, uploader, preview (PDF/images) or download button (all types)
  • Approve and Reject buttons visible to Client role only
  • Comment field: optional on Approve, required on Reject
  • Submitting Reject with empty comment: validation error shown, form blocked
  • On Approve: status → “Approved”, PM and Developer receive email notification
  • On Reject: status → “Needs Revision”, PM and Developer receive email containing the client’s comment verbatim
  • Every state change recorded in audit log with timestamp and user ID
  • PM can upload revised file — creates new version (v2, v3…), resets status to “Pending Review”

Business Rules

  • Only the project-owning PM or an Admin can upload deliverables
  • Clients can only view deliverables for projects they are invited to
  • Client role: upload button not shown; cannot initiate upload
  • Once a deliverable is Approved, status is immutable — cannot be rejected
  • A deliverable under review cannot be deleted; only superseded by a new version
  • Developer role: read-only — can view deliverables but cannot approve, reject, or upload
  • Version history always visible in reverse chronological order (v3, v2, v1)

Edge Cases

  • Two client stakeholders approve simultaneously: last-write-wins, both actions logged, one notification sent
  • File upload fails mid-transfer: no partial file saved, error shown, retry does not create a duplicate deliverable entry
  • Email notification fails to send: retry up to 3x at 5-min intervals; if all fail, PM receives in-app alert
  • File exceeds 50MB: error shown before transfer begins, nothing uploaded
  • Rejection submitted without comment: inline validation error, form blocked until comment field has at least 10 characters
  • PM uploads new version while current version is Approved: modal warning — “This deliverable is already approved. Upload anyway?”
  • Client account deactivated after approval: approval record retained and attributed to the (now inactive) account

UI/UX Notes

  • Approve button: solid green, labelled “Approve Deliverable”
  • Reject button: outlined red, labelled “Request Revision”
  • Both buttons trigger a confirmation modal before final submission
  • “Needs Revision” status card: client comment shown in a highlighted block
  • Version history panel: version number, upload date, status, uploader name
  • Status badge colours: Pending Review (amber), Approved (green), Needs Revision (red)

Dependencies

  • Project creation flow (projects must exist before deliverables can be added)
  • User auth and role system (enforces PM / Client / Developer restrictions)
  • Email notification service (for client and developer alerts)
  • File storage service (S3 or equivalent; 50MB limit enforced server-side)

Three FRD Mistakes I Still See on Every Project

Acceptance criteria that nobody can test

“The approval flow should work smoothly” is not a criterion. “Client receives email within 5 minutes of PM upload” is. If your QA engineer cannot write a test step from it, rewrite it.

Quick fix: add this prompt after each feature — “Rewrite these acceptance criteria so that each one is a clear pass/fail test.”

Missing role-based behaviour

Every feature with multiple user types needs to say what each role can and cannot do. I have seen FRDs that describe the happy path for the PM and leave the developer to figure out what the client and developer roles see. Claude will check this for you — use Prompt 4 on every feature without exception.

No edge cases at all

The happy path is easy. Edge cases are where bugs live. If your FRD has no section covering what happens when things go wrong, your developer will handle them however they feel like — inconsistently across the codebase. Run Prompt 3 on every feature. It takes two minutes and saves several bug reports.

What Is Next

You now have a BRD and an FRD for ClientHub. Before these go to the client or get handed to the dev team, they need to be aligned with each other. BRD requirements with no FRD spec. FRD features with no business justification. These gaps are common and they surface at the worst possible times.

Post 3 covers exactly that: using Claude to cross-check your BRD and FRD, generate a traceability matrix, and fill gaps before they reach development.

Next in this series: Post 3 — Aligning Your BRD and Functional Document Using Claude

Got questions? Drop them in the comments — I read every one.