Prompting Guide
The Art of Talking to Machines
Mastering the input is key to mastering the output. Here is how we structure our communication with AI to get production-grade results.
Fundamentals
Context is King
Garbage in, garbage out. The most common mistake is assuming the AI knows what's in your head. It doesn't. It only knows what you tell it.
Providing more context might cost more tokens, but it is significantly cheaper than debugging the wrong code. Paste in related files, explain the business logic, and describe the "why", not just the "what".
The Context Checklist
- ✓ Relevant file contents (not just names)
- ✓ Desired output format (e.g., "only the code block")
- ✓ Constraints (e.g., "don't change the API signature")
- ✓ Examples of similar code in the codebase
Technique
Meta-Prompting
Don't know how to articulate your request? Ask the AI to write the prompt for you.
User:
"I need to optimize a React component that renders a large data table. It's laggy. Can you write a detailed prompt for an expert frontend AI to fix this, including what context I should provide?"
AI:
"Here is a prompt you can use: 'Act as a React Performance Expert. I have a `DataTable` component that renders 5000+ rows and causes UI freezing. Attached are `DataTable.tsx` and `Row.tsx`. Please analyze the rendering cycle...'"
Strategy
Model Specialization
The Architect
Reasoning Models
Use reasoning models for high-level planning, complex architectural decisions, and generating implementation plans.
The Builder
Coding Specialists
Use coding specialists for writing the actual code, refactoring, and following the plan generated by the architect.
The Reviewer
General Purpose
Great for general purpose checks, documentation, and finding logical gaps in non-code content.
Environment
Global Context
Every AI conversation starts from zero. Global context files let you encode your team's standards, tech stack, and conventions once so that every prompt — and every team member — starts from the same baseline.
.cursorrules
Cursor's project-level settings file. Loaded automatically into every AI conversation within the project.
AGENTS.md
Used by Gemini CLI, Codex, and other agents. Defines project context, build commands, and coding conventions.
CLAUDE.md / copilot-instructions.md
Claude Code and GitHub Copilot equivalents. Same idea, different filenames depending on the tool.
Why It Matters
- → Consistency: Every developer on the team gets the same AI behavior, regardless of how they phrase their prompt.
- → Less repetition: Stop pasting "use TypeScript, prefer functional components..." into every conversation.
- → Guard rails: Encode anti-patterns the AI should avoid, like over-engineering or swallowing errors.
- → Onboarding: New team members (and new AI sessions) instantly understand the project's norms.
What to Include
- 1. Role definition — tell the AI who it is ("senior React engineer")
- 2. Tech stack — frameworks, libraries, and versions
- 3. Code style — naming, structure, patterns you follow
- 4. Anti-patterns — things the AI should never do
- 5. Build/test commands — so the AI can run and verify its own changes
Example: A Real Code Guide
Here is a production code guide used in a React + TypeScript project. You can copy ready-to-use templates from the Global Context tab below.
## Role
You are a senior React + TypeScript engineer.
## North Star
Prefer the simplest thing that works (**KISS**, **YAGNI**).
Optimize for readability, small components, and testability.
## Constraints
- **Do not over-engineer.** Solve the problem at hand with the minimal necessary abstraction.
- Keep public APIs small. Prefer local state over global unless multiple distant consumers need it.
- Prefer composition over inheritance; prefer data-first over class patterns.
- Strict TypeScript (no `any`, minimal generics, infer where possible).
- Accessibility and DX matter.
- If something adds complexity, explain exactly why it pays for itself.
## Project Context (assume when relevant)
- **Tech:** React (not Next.js), React Router, React Query, Zod, React Hook Form, MSAL-based auth, TanStack Table.
- **Style:** Keep components small and composable. Follow established table and form patterns.
- **Data layer:** Prefer React Query for server state, local `useState` for UI state.
## Code Style
- Avoid over-engineering — prefer clear, direct solutions over clever ones.
- TypeScript: strict. Avoid `any`. Use `unknown` + safe narrowing when needed.
- Prefer function components with explicit props types.
- Name booleans positively (`isOpen`, `hasError`).
- Use discriminated unions instead of flags when modeling states.
- Prefer early returns over deep nesting.
- Don't export things that aren't used outside the file.
## Component Conventions
- One responsibility per component. Extract complex UI into small leaf components.
- **Props:**
- Keep minimal. Use exact prop shapes; avoid optional props unless truly optional.
- Pass data, not render callbacks, unless composability is needed.
- **State:**
- UI state local with `useState`/`useReducer`.
- Cross-cutting state only if multiple distant consumers need it (then consider context or URL params).
- **Effects:**
- Side-effects belong in `useEffect` with correct deps. Avoid work in render.
- Memoize expensive computations with `useMemo` only when profiling shows benefit.
## Data Fetching & Mutations (React Query)
- Use `useQuery`/`useMutation` for server state; set `queryKey`s predictably (`['resource', id]`).
- Normalize inputs (trim/uppercase where needed) close to the boundary.
- Handle loading, empty, error, and success states explicitly.
- Invalidate queries on successful mutations; prefer optimistic updates only when necessary and safe.
- Never swallow errors; surface user-facing messages + log technical details.
## Validation (Zod + React Hook Form)
- Define Zod schemas near the feature. Derive TS types from schemas (`z.infer`).
- Coerce and preprocess at the boundary (numbers, enums).
- Keep form components controlled through RHF; avoid duplicating state.
## Accessibility
- Use semantic HTML and shadcn components correctly.
- All interactive elements keyboard accessible (`Button` over `div`).
- Provide `aria-*` where appropriate; label inputs and landmarks.
- Announce async states (loading/empty/error) in UI.
## Error Handling & UX
- Show specific, actionable errors; avoid "Something went wrong."
- For forms, inline field errors + summary where helpful.
- Guard user actions with confirmations only when destructive/irreversible.
## Performance
- Avoid premature optimization and memoization — measure before optimizing.
- Virtualize long lists/tables if needed.
## Anti-Patterns to Avoid
- **Over-engineering** — resist abstractions until duplication or pain clearly justifies them.
- Overuse of global state/context for local concerns.
- Catching and ignoring errors.
- Coupling components to data fetching without a clear boundary.
- Reusable hooks/components created after only 1–2 uses.
- Over-configurable components; prefer simple, specific ones.
- "Magic" utilities that hide logic and reduce readability.
## Voice & Output Formatting for Explanations
- Be concise. Use bullet points for rationale.
- When proposing changes, show a minimal diff and explain trade-offs.
- Prefer real code over pseudo-code when demonstrating patterns.
Templates
Ready-to-Use Prompts
Battle-tested prompts for refactoring, testing, and documentation. Copy them directly or download as VS Code snippets.
Extract Function
Ask the AI to identify and extract reusable logic into a named function.
Analyze the following code block and extract any repeated or complex logic
into well-named, single-responsibility functions. Preserve the original
behavior exactly. Add JSDoc comments to each extracted function.
```
[paste your code here]
```
Requirements:
- Each function should do ONE thing
- Use descriptive names (verb + noun)
- Add error handling where appropriate
- Include TypeScript types if applicableSimplify Conditionals
Reduce nested if/else blocks into cleaner patterns.
Refactor the following code to reduce conditional complexity.
Use early returns, guard clauses, and lookup objects where appropriate.
The refactored code must be functionally identical.
```
[paste your code here]
```
Preferred patterns:
- Early returns over nested if/else
- Object/Map lookups over switch statements
- Ternary only for simple, single-line expressionsModernize Legacy Code
Convert older JS patterns to modern ES2024+ syntax.
Modernize the following JavaScript code to use current best practices.
```
[paste your code here]
```
Apply these transformations where applicable:
- var → const/let
- function() → arrow functions (where appropriate)
- .then() chains → async/await
- string concatenation → template literals
- require() → import/export
- Array.prototype methods over for loops
- Optional chaining and nullish coalescing
- Object destructuring