GESHDO

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.

code-guide.md
## 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.

markdown
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 applicable

Simplify Conditionals

Reduce nested if/else blocks into cleaner patterns.

markdown
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 expressions

Modernize Legacy Code

Convert older JS patterns to modern ES2024+ syntax.

markdown
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