Code generation with AI requires a different approach than general prompting. The AI needs enough context to understand the codebase, constraints, and quality standards. This lesson covers the techniques that consistently produce production-ready code.
Writing specs for AI coding
The rule: Treat the AI like a junior developer who needs clear specifications.
The specification template
Use this structure for code generation prompts:
## Context
- Tech stack: [React 18, TypeScript, Tailwind, Node.js, etc.]
- Project structure: [relevant files and folders]
- Existing patterns: [how similar features are implemented]
## Task
[Clear description of what to build]
## Requirements
- [Specific requirement 1]
- [Specific requirement 2]
- [Edge case to handle]
## Constraints
- [Technical constraint 1]
- [Technical constraint 2]
## Output format
- [How you want the code presented]
- [What additional info needed (types, tests, etc.)]Specification example
## Context
Building a Next.js 14 app with App Router. Using TypeScript,
Tailwind CSS, and Prisma ORM with PostgreSQL.
Current file structure:
- src/app/page.tsx (home page)
- src/lib/prisma.ts (database client)
- src/components/ui/ (reusable UI components)
## Task
Create a blog post listing page that displays posts from the database.
## Requirements
1. Fetch posts from Prisma (title, slug, excerpt, publishedAt)
2. Display in a responsive grid layout
3. Show "No posts yet" if empty
4. Link each post to /blog/[slug]
5. Format dates nicely (e.g., "January 15, 2024")
## Constraints
- Use Next.js Server Components (no 'use client')
- Must handle database errors gracefully
- Maximum 20 posts per page (pagination not needed yet)
## Output format
- Full TypeScript component code
- Prisma query included
- Type definitions for the post data
- Comments explaining the Server Component approachBeing explicit about edge cases
Requirements:
1. Handle empty input (return null or empty array?)
2. Handle null values in data
3. Handle very long strings (max length?)
4. Handle special characters
5. Handle concurrent requests (if applicable)Context management
AI coding assistants work best when they understand the full picture. Provide context strategically.
What context to include
| Context type | When to include | Example |
|---|---|---|
| Tech stack | Always | "React 18, TypeScript 5.0, Vite" |
| File structure | Complex projects | "Component is in src/components/ and uses utils from src/lib/" |
| Existing code | Modifying existing files | Paste the current file content |
| Dependencies | Using specific libraries | "Using React Hook Form v7, not v6" |
| Configuration | Build/deployment matters | "ESLint strict mode enabled" |
Sharing file contents
When working on existing code, share the relevant context:
I need to modify this function to add error handling:// src/utils/apiWhat is api?A set of rules that lets one program talk to another, usually over the internet, by sending requests and getting responses..ts
export async function fetchUser(id: string) {
const response = await fetch(/api/users/${id});
return response.jsonWhat is json?A text format for exchanging data between systems. It uses key-value pairs and arrays, and every programming language can read and write it.();
}
The API returns:
- 200: { id, name, email }
- 404: { error: "User not found" }
- 500: { error: "Internal server error" }
Please add proper error handling and TypeScript types.Sharing project structure
Here's my project structure:
src/
├── components/
│ ├── ui/ # Reusable UI components
│ └── features/ # Feature-specific components
├── hooks/ # Custom React hooks
├── lib/ # Utilities and config
│ ├── api.ts # API client
│ └── utils.ts # Helper functions
└── types/ # TypeScript types
I'm working in src/components/features/UserProfile.tsx
and need to fetch data using the api client in src/lib/api.tsUsing "@" mentions (Cursor, Copilot)
Some AI coding tools let you reference files directly:
Update the UserProfile component to use the new API format
defined in @src/types/user.tsDebugging with AI
Debugging is where AI shines, if you give it the right information.
The debugging information hierarchy
Essential (always include):
- Error message (full text)
- Code that caused the error
- Expected behavior vs actual behavior
Helpful (include if relevant):
- What you've already tried
- Environment details (browser, Node version, etc.)
- Recent changes to the code
- Related files or dependencies
Debugging prompt template
I'm getting an error I can't figure out.
Error message:[paste full error here]
Code:[paste relevant code]
Expected: [what should happen]
Actual: [what actually happens]
What I've tried:
- [thing 1]
- [thing 2]
Environment: [browser, Node version, etc.]Real debugging example
React useEffect running infinitely
Error: None, but browser freezes
Code:function UserList() {
const [users, setUsers] = useState([]);
useEffect(() => {
fetchUsers().then(data => {
setUsers(data);
});
}); // <-- No dependencyWhat is dependency?A piece of code written by someone else that your project needs to work. Think of it as a building block you import instead of writing yourself. array!
return <div>{users.length} users</div>;
}
Expected: Fetch users once when component mounts
Actual: Fetch runs continuously, freezing the browser
What I tried:
- Added console.log to useEffect - it logs infinitely
- Checked Network tab - requests firing non-stop
Why is this happening and how do I fix it?Asking for debugging strategies
Sometimes you don't know what's wrong:
My app is slow when loading large datasets.
Current implementation:
[code that renders a table with 1000 rows]
What are 3 different strategies to improve performance?
For each, explain:
- The approach
- When it's best used
- TradeoffsCode review prompts
AI makes an excellent code reviewer when you tell it what to look for.
Code review checklist prompt
Review this code for:
1. Security issues
- SQL injection risks
- XSS vulnerabilities
- Unsafe eval() or innerHTML
- Hardcoded secrets
2. Performance problems
- Unnecessary re-renders
- Inefficient algorithms (O(n²) when O(n) possible)
- Memory leaks
3. Code quality
- Readability
- Naming conventions
- Comment quality
- Test coverage
4. Best practices
- Language/framework idioms
- Error handling
- Type safety
Code to review:[paste code]
Specific review types
Security-focused:
You are a security expert. Review this authentication code
for security vulnerabilities. Focus on:
- Password handling
- Session management
- JWT token security
- Rate limitingPerformance-focused:
Review this React component for performance issues.
Check for:
- Missing useMemo/useCallback
- Unnecessary re-renders
- Expensive calculations in render
- Large bundle sizesBeginner-friendly review:
Review this code as if teaching a junior developer.
For each issue:
1. Explain why it's problematic
2. Show the fix
3. Explain the principle behind the fixDocumentation generation
Good documentation is crucial but tedious. AI can help, but you need to guide it.
README generation
Generate a README.md for this project:
Project: [name]
Purpose: [one sentence description]
Tech stack: [technologies]
Key features:
- [feature 1]
- [feature 2]
Include sections for:
1. Installation
2. Usage
3. API (if applicable)
4. Contributing
5. License
Target audience: [who will read this]JSDoc/TypeDoc generation
Add JSDoc comments to this function following these rules:
- Describe what the function does
- Document each parameter with @param
- Document return value with @returns
- Include @throws if it can throw
- Add @example with usagefunction calculateTotal(
items: CartItem[],
discount?: number,
taxRate?: number
): number {
// implementation
}
Inline comment prompts
Add inline comments to this complex algorithm:
- Explain the "why" not just the "what"
- Comment any magic numbers
- Explain non-obvious logic
- Keep comments concise[complex code here]
Documentation from code
Given this API route, generate documentation:// src/app/apiWhat is api?A set of rules that lets one program talk to another, usually over the internet, by sending requests and getting responses./users/route.ts
export async function GET(request: Request) {
const { searchParams } = new URL(request.url);
const page = searchParams.get('page') || '1';
const limit = searchParams.get('limit') || '10';
const users = await prisma.user.findMany({
skip: (parseInt(page), 1) * parseInt(limit),
take: parseInt(limit),
});
return Response.jsonWhat is json?A text format for exchanging data between systems. It uses key-value pairs and arrays, and every programming language can read and write it.({ users, page, limit });
}
Format: OpenAPI/Swagger style
Include: Parameters, responses, error codesTesting strategies
AI can write tests, but you need to specify what kind of coverage you want.
Test generation prompts
Unit tests:
Write Jest unit tests for this function.
Requirements:
- Test happy path
- Test edge cases (empty input, null, undefined)
- Test error conditions
- Use describe/it blocks for organization
- Mock external dependencies[function to test]
React component tests:
Write React Testing Library tests for this component.
Test scenarios:
1. Renders correctly with props
2. Handles user interactions (clicks, inputs)
3. Shows loading state
4. Shows error state
5. Accessibility (if relevant)[component code]
Integration tests:
Write an integration test for this API endpoint.
Test the full flow:
1. Database setup (seed data)
2. HTTP request
3. Response validation
4. Database assertions
5. Cleanup[APIWhat is api?A set of rules that lets one program talk to another, usually over the internet, by sending requests and getting responses. route code]
Test case brainstorming
I'm testing a user registration function.
It should:
- Accept email, password, name
- Validate email format
- Enforce password rules (8+ chars, 1 number, 1 symbol)
- Check email uniqueness
- Hash password before storing
- Return user object (without password)
- Send welcome email
List 10+ test cases I should write, including:
- Happy path
- Validation failures
- Edge cases
- Error scenariosCoverage requirements
Generate tests that achieve:
- 100% line coverage
- All branches tested
- Edge cases covered
Test file structure:
- describe blocks for each main function
- it blocks for each test case
- beforeEach for setup
- afterEach for cleanupQuick reference: code generation checklist
Before submitting a code generation prompt, check:
- [ ] Tech stack specified
- [ ] Constraints listed
- [ ] Edge cases mentioned
- [ ] Output format defined
- [ ] Relevant code/files included
- [ ] Error handling addressed
- [ ] Testing mentioned (if needed)
Code generation with AI is a collaboration. The clearer your specifications, the better the output. Think of it as writing a really good ticket for a junior developer, context, requirements, constraints, and expected output. Master this, and you'll ship code faster while maintaining quality.