DEV Community

koreanDev
koreanDev

Posted on

Claude Code for Solo Developers — Prompt Engineering That Keeps Things Clean

I'm building an iOS reading app by myself. The stack is Flutter, Express/TypeScript, and Supabase. I used Claude Code for most of the heavy lifting — Apple Sign In, account deletion, API client abstraction, design system, card sharing, and localization.

What I found out pretty quickly is that how you write the prompt changes everything. This is a record of what worked, what didn't, and the calls I made along the way.


I wrote prompts with Claude, not for Claude

I didn't start with perfect prompts. I'd explain what I needed, Claude would draft a prompt, and then I'd add my own rules or split the task up before running it.

Error handling is a good example. Claude's first draft looked like this:

Add consistent error handling across all API call sites.
Wrap every API call in try-catch.
Enter fullscreen mode Exit fullscreen mode

Here's what I added on top:

Scan the entire codebase — not just repositories.
- Catch ApiException and rethrow as-is
- Catch all other exceptions and wrap in ApiException(statusCode: 0, message: e.toString())
Maintain existing feature-first clean architecture.
Enter fullscreen mode Exit fullscreen mode

I knew that "all repository methods" would miss files like auth_repository. So I made it explicit. Claude drafts, I refine, then we run it.


1 — Always declare the scope

This was the most important thing I did. Every prompt had a clear list of what to touch and what to leave alone.

## Constraints
- Only modify setting_page.dart
- Do not modify auth or book features
- Maintain existing feature-first clean architecture
Enter fullscreen mode Exit fullscreen mode

Because of this, I had zero unintended file changes across the whole project. Claude never touched something I didn't ask it to. Every result stayed exactly in the lane I set.


2 — Give architecture context in one line

Early on I wrote "Keep Riverpod pattern." Too narrow. What I actually needed was the whole structure to stay intact.

So I switched to this:

Maintain existing feature-first clean architecture.
Enter fullscreen mode Exit fullscreen mode

One line. Covered Riverpod, directory structure, and file responsibilities all at once. Anthropic's own docs say to think of Claude like a smart new hire with limited context — give enough to work with, but don't over-explain.


3 — Split the work

When you throw too much at once, instructions can conflict or things get dropped. Anthropic's docs recommend giving instructions as sequential steps.

For the design system, I split it like this:

Round 1 — Extract design constants:

Extract design constants into a centralized theme system.
Inside lib/app/:
- app_colors.dart
- app_text_styles.dart
- Update existing theme.dart
Replace all hardcoded color/font values.
Do not change any UI layout or behavior.
Enter fullscreen mode Exit fullscreen mode

Round 2 — Navigation and Settings:

Simplify navigation and complete Settings page.
Reduce bottom tabs to 2: Books and Settings.
Complete Settings page with user info and logout.
Enter fullscreen mode Exit fullscreen mode

Splitting made it easy to verify each result and track down issues if something went wrong.


4 — Product decisions are mine to make

Claude writes good code. It doesn't make good product decisions.

When I needed to store a language setting, Claude suggested a new table and middleware layer. But there was already a language_code column in the DB. I just used that.

Claude tends to over-engineer for flexibility. In solo development, simplicity wins. That call is mine to make.

Same thing with the sentence delete feature. I cut it from the MVP. A bad sentence can just stop being the representative one — and having sentences pile up is actually part of the app's value.


What I didn't know

After the project, I read through Anthropic's official prompt engineering guide. A few things stood out.

XML tags — Wrapping sections in <instructions>, <constraints>, <context> tags helps Claude parse the prompt more cleanly. I used markdown headers (##) the whole time.

Few-shot examples — Including 3–5 examples alongside instructions can significantly improve output quality. I never did this. For consistency-heavy work like design systems, it probably would've helped.

There's also stuff in the docs about parallel tool calls and agent behavior control. Didn't use any of it. Worth looking into for the next project.


Wrapping up

Scope declaration, architecture context, splitting the work — those three things kept everything clean. No unintended changes, no broken structure, results that stayed exactly where I put them.

Prompting is just communication. The clearer you are about what you want, what's off limits, and what the constraints are — the better the output. But what to build, how to break it down, how simple to keep it — that's still on you.

Top comments (0)