Effective Prompting for Code

Prompting Fundamentals for Code

4 min read

The quality of AI-generated code directly depends on the quality of your prompts. This lesson teaches the foundational techniques that separate average results from excellent ones.

The Anatomy of a Good Prompt

┌─────────────────────────────────────────────────────────────┐
│                    Effective Code Prompt                    │
├─────────────────────────────────────────────────────────────┤
│ 1. CONTEXT                                                  │
│    - What exists already?                                   │
│    - What technologies are in use?                          │
│                                                             │
│ 2. TASK                                                     │
│    - What do you want created/changed?                      │
│    - What's the expected behavior?                          │
│                                                             │
│ 3. CONSTRAINTS                                              │
│    - What must it work with?                               │
│    - What patterns to follow?                              │
│                                                             │
│ 4. OUTPUT FORMAT (optional)                                │
│    - File structure?                                       │
│    - Documentation style?                                  │
└─────────────────────────────────────────────────────────────┘

The CRISPE Framework

A structured approach for code prompts:

Component Description Example
Context Project background "This is a Next.js 14 app using Prisma"
Role Who the AI should be "Act as a senior backend developer"
Instructions What to do "Create a user authentication system"
Specifics Technical details "Use JWT, bcrypt, httpOnly cookies"
Patterns Examples to follow "Match the style in auth.service.ts"
Exclusions What to avoid "Don't use deprecated APIs"

Good vs Bad Prompts

Example 1: Creating a Function

Bad:

Create a function to validate email

Good:

Create an email validation function:
- TypeScript, exported from src/utils/validation.ts
- Accept string, return boolean
- Handle edge cases: empty string, missing @, multiple @
- Include JSDoc comment
- Match the validation pattern used in src/utils/phone.ts

Example 2: Building a Component

Bad:

Make a login form

Good:

Create a LoginForm component for our Next.js app:

Requirements:
- Email and password fields with validation
- "Remember me" checkbox
- Submit button with loading state
- Error message display
- Use React Hook Form with Zod validation
- Follow the styling in src/components/forms/SignupForm.tsx
- Add accessibility attributes (aria-labels, etc.)
- Include TypeScript interfaces for props

Example 3: Refactoring

Bad:

Refactor this code to be better

Good:

Refactor src/services/payment.ts:

Goals:
- Extract Stripe logic into src/services/adapters/stripe.ts
- Create PaymentProvider interface for payment gateways
- Keep the same public API (no breaking changes)
- Add proper error handling with custom exceptions
- Maintain existing test coverage

The refactored code should allow adding PayPal in the future
without modifying the main payment service.

Context Is King

Providing Project Context

Method 1: Direct Description

This is a React 18 e-commerce app using:
- TypeScript strict mode
- Tailwind CSS for styling
- React Query for server state
- Zustand for client state
- Next.js 14 App Router

Method 2: Reference Files

Looking at the patterns in:
- @src/components/ProductCard.tsx
- @src/hooks/useProducts.ts

Create a similar component for displaying user profiles.

Method 3: Constraints

Must work with:
- Our existing auth middleware
- The User type from src/types/user.ts
- The API client in src/lib/api.ts

Specificity Levels

Match your specificity to task complexity:

Level 1: Quick Fixes

Fix the TypeScript error on line 42 of src/utils/format.ts

Level 2: Small Features

Add a "copy to clipboard" button to the CodeBlock component
that shows a checkmark for 2 seconds after copying.

Level 3: Medium Features

Implement pagination for the user list:
- Use cursor-based pagination
- Show 20 users per page
- Add "Load more" button
- Preserve scroll position
- Handle loading and error states

Level 4: Large Features

Create a notification system:

Database:
- Notification model with type, message, readAt, userId
- Relations to User model

API:
- GET /api/notifications (with pagination)
- PATCH /api/notifications/:id/read
- POST /api/notifications/read-all

Frontend:
- NotificationBell component with unread count
- NotificationDropdown with infinite scroll
- Mark as read on click

Real-time:
- WebSocket connection for new notifications
- Sound notification option

The Iteration Principle

Don't expect perfection on the first try:

Round 1: Generate initial code
Round 2: "Add error handling for network failures"
Round 3: "Make the loading state more user-friendly"
Round 4: "Add unit tests for the main function"
Done: Production-ready code

Common Mistakes

1. Being Too Vague

❌ "Make it work" ✅ "Handle the case where the user is not authenticated"

2. Assuming Context

❌ "Add it to the form" ✅ "Add the phone field to the UserProfileForm component in src/components/forms/"

3. Missing Constraints

❌ "Create an API endpoint" ✅ "Create an API endpoint following our existing pattern in src/app/api/users/route.ts"

4. Overloading Single Prompts

❌ "Build the entire authentication system with social login, email verification, password reset, and two-factor auth" ✅ Start with core auth, then iterate to add features

Templates for Common Tasks

Bug Fix Template

Bug: [What's happening]
Expected: [What should happen]
Location: [File and line if known]
Steps to reproduce: [How to trigger]
Related code: @[relevant file]

Feature Template

Feature: [Name]

User Story:
As a [user type], I want to [action] so that [benefit].

Technical Requirements:
- [Requirement 1]
- [Requirement 2]

Acceptance Criteria:
- [ ] [Criterion 1]
- [ ] [Criterion 2]

Patterns to follow: @[example file]

Prompting Truth: A well-crafted prompt takes 30 seconds but saves 10 minutes of iteration. Invest in your prompts.

In the next lesson, we'll explore advanced techniques like few-shot prompting and chain-of-thought. :::

Quiz

Module 4: Effective Prompting for Code

Take Quiz