# How to Prompt AI Coding Tools Like a Senior Dev (2026)

> Source: <https://dev.to/stacknotice/how-to-prompt-ai-coding-tools-like-a-senior-dev-2026-3bh9>
> Published: 2026-05-27 18:35:56+00:00

Two developers use the same AI tool. One gets working code in 30 seconds. The other gets a broken mess and spends an hour fixing it.

The difference isn't the tool. It's the prompt.

AI coding tools are pattern matchers with enormous context windows. Feed them a clear pattern and they complete it brilliantly. Feed them ambiguity and they invent assumptions — usually wrong ones.

The common mistakes:

The fix isn't a different AI tool. It's a different way of writing prompts.

Every effective coding prompt has three parts:

```
[CONTEXT] Given this [file/system/function],
[CONSTRAINT] following these [conventions/rules],
[TASK] do [specific, scoped thing].
```

**Bad prompt:**

"Add a delete button"

**Good prompt:**

"In

`src/components/ProjectCard.tsx`

, add a delete button that calls the`deleteProject`

Server Action from`src/actions/projects.ts`

. On click, show a confirmation dialog using the existing`AlertDialog`

from shadcn/ui. After deletion, call`revalidatePath('/dashboard')`

. Follow the existing error handling pattern: catch errors and show a toast with sonner, don't throw."

Same request. The second one takes 40 extra seconds to write. The output is production-ready instead of a starting point that needs an hour of cleanup.

For building new features. The most common — and the easiest to get wrong.

**Template:**

```
Add [feature] to [file/component].
It should [behavior description].
Use [specific library/pattern] — not [what to avoid].
Follow the existing pattern in [example file or function].
The return/export should look like: [description].
```

**Example:**

```
Add pagination to `getUserProjects` in `src/lib/queries.ts`.
It should accept `{ page: number, limit: number }` and return
`{ data, total, hasMore }`.
Use Drizzle's `.offset()` and `.limit()` — not cursor-based pagination.
Follow the same select pattern as `getUserById`: select specific
columns, never `select *`.
Type the return with a `PaginatedResult<T>` generic.
```

For debugging. The mistake is not giving enough context about expected vs actual behavior.

**Template:**

```
[function/component] in [file] is broken.
Expected: [what should happen]
Actual: [what is happening]
Error: [exact error message if any]
Relevant context: [the failing code + what it calls]
```

**Example:**

```
The `createProject` Server Action in `src/actions/projects.ts`
returns { error: "Unauthorized" } even when the user is logged in.

Expected: creates the project and returns { data: project }.
Actual: always hits the requireAuth() error branch.
Error: no error message, just the unauthorized return.

requireAuth() is in `src/lib/auth.ts` — pasting it below.
The user is definitely authenticated (visible in Clerk dashboard).
```

For improving existing code without breaking it. The critical constraint: **specify what must not change**.

**Template:**

```
Refactor [function/file] to [improvement goal].
Keep: [API, behavior, types that must stay identical]
Change: [what should change]
Don't: [specific things to avoid]
```

**Example:**

```
Refactor `UserTable.tsx` to extract the row actions into a
separate `UserTableActions` component.

Keep: the exact same props API on UserTable, same visual output,
same TypeScript types.
Change: move the action buttons and their handlers to
`UserTableActions.tsx`.
Don't: change how the parent passes data, don't add new dependencies.
```

For generating tests. Be explicit about the library, what to cover, and what to mock.

**Template:**

```
Write [unit/integration] tests for [function/component] in [file].
Testing library: [Vitest/Playwright/etc.]
Cover: [list of specific scenarios]
Mock: [external dependencies to mock and why]
Don't test: [implementation details to avoid]
```

**Example:**

```
Write Vitest unit tests for the `createProject` Server Action
in `src/actions/projects.ts`.

Cover:
- success case (user authorized, valid input)
- validation failure (name exceeds 50 chars)
- unauthorized user (requireAuth throws)
- database error (insert fails)

Mock: `src/lib/db.ts` (mock insert to return a fake project),
`src/lib/auth.ts` (mock requireAuth).
Don't test the actual database or actual auth — only the action's logic.
```

For understanding unfamiliar code. The mistake: asking for a general explanation.

**Bad:**

"Explain this code"

**Good:**

"Explain what this Drizzle query does. Specifically: what does

`.$onConflictDoUpdate`

do, and why is`target: [users.clerkId]`

needed? Give me a one-sentence summary of the overall effect on the database."

Focused questions get focused answers. "Explain this code" gets a wall of text that covers things you already know.

For updating code to a new API version.

**Template:**

```
Migrate [file] from [old API] to [new API].
Breaking changes to handle: [list specific breaking changes]
Don't change: [function signatures your app uses]
Reference: [paste the relevant migration docs]
```

**Example:**

```
Migrate `src/lib/auth.ts` from Clerk v4 to Clerk v5.
Breaking changes: `auth()` is now async, `clerkMiddleware` replaces
`withClerkMiddleware`, user object shape changed.
Don't change the signatures my app uses: requireAuth() and getAuthUser().

Here are the relevant Clerk v5 migration notes:
[paste the breaking changes section from the docs]
```

The single biggest factor in output quality is context. AI tools can only use what you give them.

`/lib`

")The best context is the minimum needed to be unambiguous.

Tip (Claude Code):With Claude Code, you don't need to paste code into the prompt. Just reference the file path — "in`src/actions/projects.ts`

" is enough, Claude Code reads it automatically. Save the pasting for specific snippets you want to highlight.

The problem with writing good prompts is repeating your conventions every time: "use cuid2 for IDs, use Server Actions not API routes, return `{ data }`

or `{ error }`

..."

With Claude Code, you write them once in a `CLAUDE.md`

file at the root:

```
# CLAUDE.md

## Stack
- Next.js 15 App Router, TypeScript strict mode
- Drizzle ORM + Neon (PostgreSQL)
- Clerk auth, Zod validation, shadcn/ui
- Biome for linting and formatting

## Conventions
- cuid2 for all IDs, never auto-increment integers
- Soft-delete users (deletedAt), never hard delete
- Server Actions for mutations, not API routes
- Import env from `@/lib/env`, never `process.env` directly
- `requireAuth()` at the top of every protected action
- Return `{ data }` or `{ error: string }`, never throw from actions
- Error messages lowercase, no periods

## File structure
- Server Actions: `src/actions/[feature].ts`
- DB queries: `src/lib/queries.ts`
- Shared types: `src/types/[domain].ts`
```

Claude Code reads this at startup and applies these rules to every prompt automatically. You never have to say "use cuid2" again — it just does it.

The single skill that separates developers who get great results from those who get frustrated: breaking tasks down to the right size.

**Don't:**

"Build me user authentication with sign-up, login, social auth, Google OAuth, password reset, email verification, session management, and account settings page."

**Do:**

`requireAuth()`

helper in `src/lib/auth.ts`

" → done`/dashboard`

routes" → done`(dashboard)/settings/page.tsx`

" → doneEach step is a 30-second prompt with a clear, verifiable output. The combined result is identical to the big request — but with zero hallucinated architecture, and you understand every line.

**The rule:** if a prompt would take more than 5 minutes for a human to fully spec out, it's two prompts.

**Architecture decisions:**

"Should I use microservices or a monolith?"

AI will give you a reasonable-sounding answer based on generic patterns. It doesn't know your team size, your traffic, your runway. Decide this yourself first, then ask AI to implement your decision.

**Business logic:**

"What should happen when a user cancels their subscription?"

This is a product decision with revenue implications. Define it yourself, then implement it.

**Security auditing:**

"Is this code secure?"

AI can write secure code when you ask for it. It will not spontaneously catch every vulnerability in existing code. Use dedicated tooling for audits.

**Anything you won't read:**

If you're going to copy AI output without reading it, stop. You're shipping code you don't understand. When it breaks — and it will — you won't know where to look.

**Before (30 seconds to write, 45 minutes to fix):**

"Add search to the projects list"

**After (90 seconds to write, works first time):**

"Add search to

`src/app/(dashboard)/projects/page.tsx`

. It should use a URL search param (`?q=`

) so search state persists on refresh. Filter the results from`getUserProjects`

where`name`

contains the query (case-insensitive). Use a debounced input — debounce 300ms using`useDebounce`

from`src/hooks/useDebounce.ts`

. Don't add any new dependencies."

**Before:**

"My form isn't submitting"

**After:**

"The

`CreateProjectForm`

in`src/components/CreateProjectForm.tsx`

doesn't call the Server Action when submitted. React Hook Form's`handleSubmit`

is wired up but the action (`createProject`

from`src/actions/projects.ts`

) never fires — confirmed with console.log at the top of the action. No browser errors. Pasting both files below."

**Before:**

"Clean up this file"

**After:**

"The

`src/lib/db.ts`

file has three inline helper functions (`withRetry`

,`paginate`

,`softDelete`

) that are now used in 6+ places. Extract them to`src/lib/db-helpers.ts`

and update all imports. Don't change the function signatures or behavior — only the location."

The best way to get better at prompting is to notice when you get a bad result and ask why.

`CLAUDE.md`

Every bad output is feedback on the prompt. Fix the prompt, not just the output.

The developers getting 10x from AI tools aren't using a different tier or a different model. They're spending 60 extra seconds writing a better prompt. That's the entire edge — and it compounds every single day.

Full guide with CLAUDE.md templates and Claude Code workflow:

[https://stacknotice.com/blog/ai-coding-prompts-senior-2026](https://stacknotice.com/blog/ai-coding-prompts-senior-2026)
