Prompt Engineering for Developers: Getting the Most Out of Claude Code
Claude Code can generate impressive code, but it can also waste hours if you don't know how to brief it properly. Here's how to structure your prompts to get clean, documented, deployment-ready code.
The Problem You Know Too Well
You ask Claude to generate a function. It spits out 200 lines of code. Looks clean, well-indented, with comments. You test it. It crashes. You ask for a fix. New version. New bug. After 45 minutes of back-and-forth, you could've coded the function yourself in 20 minutes.
The problem isn't Claude. It's your prompt.
Claude Code (via Claude 3.5 Sonnet or Opus) is one of the best models for code generation. But like any powerful tool, it needs precise instructions. A vague prompt = generic code that misses the mark.
Here's how to brief Claude like a senior dev briefs a junior.
The Prompt Structure That Changes Everything
The best code prompts follow this 5-part structure:
1. Technical Context
Don't make Claude guess your stack. Be explicit:
Project: Node.js REST API with Express and TypeScript
Node version: 18.x
Database: PostgreSQL with Prisma ORM
Authentication: JWT via custom middleware
2. Clear Functional Objective
Not "create a payment function." Instead:
Create a POST /api/payments endpoint that:
- Accepts an amount and a Stripe payment_method_id
- Validates that the user is authenticated
- Creates a Stripe PaymentIntent
- Saves the transaction to DB with "pending" status
- Returns the payment object with client_secret
3. Constraints and Standards
This is where 90% of devs forget to specify:
Constraints:
- Use async/await (no .then())
- Error handling with try/catch and appropriate HTTP codes
- Input validation with Zod
- Logging with Winston on all errors
- Unit tests with Jest
4. Expected Output Format
Be specific:
Provide:
1. Controller code
2. Zod validation schema
3. TypeScript types
4. 3 unit tests (success, invalid amount, unauthenticated user)
5. Example curl request
5. Concrete Example (Optional but Powerful)
Show an example of what you want:
Expected response example:
{
"success": true,
"payment": {
"id": "pay_123",
"amount": 2999,
"status": "pending",
"client_secret": "pi_xxx_secret_yyy"
}
}
Complete Prompt Example
Here's a real prompt that generates directly usable code:
Context:
- Express + TypeScript API
- JWT auth via requireAuth middleware
- Stripe SDK v12
- Prisma ORM
Task:
Create a POST /api/subscriptions/cancel endpoint that allows an authenticated user to cancel their Stripe subscription.
Business logic:
1. Get subscription_id from req.user (injected by middleware)
2. Cancel subscription via Stripe API (cancel_at_period_end: true)
3. Update status in DB (subscriptions table, status field = 'canceling')
4. Return end-of-access date
Constraints:
- Validation: verify subscription belongs to the user
- Error handling: handle case where Stripe is down
- Log all errors with Winston
- Code tested with Jest (at least 2 tests)
Output format:
1. TypeScript controller
2. Required types
3. Jest tests
4. JSON response example
Don't generate config files (Stripe, Prisma), assume they exist.
Patterns That Save Time
Pattern 1: Ask for Pieces, Not Everything at Once
Rather than "create a complete app," break it down:
Step 1: Create just the Prisma schema for User and Subscription
Step 2: Create the auth service (login/register)
Step 3: Create CRUD endpoints for subscriptions
Claude performs better on focused tasks.
Pattern 2: Ask It to Explain Before Coding
For complex logic:
Before coding, explain in 5 steps how you would implement a Redis-based rate limiting system for this API. Once validated, you'll code it.
This prevents going in the wrong direction.
Pattern 3: Specify the Level of Comments
Comments:
- No obvious comments (like "// Loop through items")
- Comment only non-obvious business logic
- JSDoc docstrings on public functions only
By default, Claude over-comments. Guide it.
Mistakes That Waste Your Time
Mistake 1: Too Vague Prompt
❌ "Create a search function" ✅ "Create a searchUsers function that takes a query string, searches name and email fields via Prisma, returns max 20 results, with pagination"
Mistake 2: Forgetting Dependencies
❌ "Use Redis" ✅ "Use ioredis v5, connection already configured in lib/redis.ts, use async/await methods"
Mistake 3: Not Asking for Tests
If you don't explicitly ask, Claude won't generate them. Result: you have to write them yourself afterward.
Mistake 4: Accepting Code Without Error Handling
Always enforce:
Every async function must have try/catch
Every error must be logged
Return appropriate HTTP codes (400, 401, 404, 500)
How KayaPrompt Helps You Industrialize This
If you find yourself copy-pasting the same technical context in every prompt (your stack, your constraints, your code standards), that's exactly the problem KayaPrompt solves.
You create a prompt template with your variables:
Context: {{tech_stack}}
Task: {{feature_description}}
Constraints: {{code_standards}}
Tests: {{test_type}}
Then you only fill in the variables specific to each new feature. The rest (your stack, your conventions, your quality requirements) is already there.
It's like having a senior dev who already knows your codebase and standards.
Your Checklist Before Sending a Code Prompt
Before hitting Enter:
- I specified the language AND version
- I listed the libraries used
- I described the expected behavior in 3-5 points
- I specified the expected error handling
- I asked for tests (or not, depending on the case)
- I indicated the exact output format
- I provided an example result if it's complex
If you check these 7 boxes, your prompt will generate 10x more usable code.
Going Further
Claude Code isn't magic. It's a very competent collaborator who needs clear instructions. Treat it like you'd brief a dev joining your team: context, objective, constraints, examples.
The difference between a dev who wastes time with AI and a dev who 10x their productivity? The quality of prompts.
If you want to test your code prompts and improve them with reusable templates, check out KayaPrompt. It's built exactly for this: structure, test, and reuse your best prompts.
Now go code. But this time, with prompts that work.