• Prompt/Deploy
  • Posts
  • How to Write Prompts That Generate Reusable, Maintainable Code

How to Write Prompts That Generate Reusable, Maintainable Code

Most developers prompt for code. The better ones prompt for structure.

If your AI-generated output feels bloated, hard to reuse, or impossible to debug—the problem usually starts upstream: you're asking for implementation before you've defined the architecture.

But here's the reality: not every feature needs elaborate architecture. A contact form doesn't require seven design documents. The skill is knowing when structure matters and how much is enough.

Core Insight: Match Structure to Complexity

Structure-first prompting isn't about creating elaborate architectures for everything. It's about getting the right level of organization for what you're building. Sometimes that's a single file. Sometimes it's a carefully layered system.

The key is asking AI to think about organization before diving into implementation—but only as much as the feature actually needs.

The Spectrum of Structure

Level 0: Single File (Perfect for Simple Features)

When to use: Contact forms, admin tools, one-off utilities

Example prompt:

Create a contact form component with name, email, and message fields. Include validation and error states. Keep everything in one file.

Result: ContactForm.tsx - 150 lines, self-contained, done.

This is fine. Not everything needs to be split into 10 files.

Level 1: Basic Separation (Most Features)

When to use: Standard CRUD, user profiles, settings pages

Example prompt:

Structure a user profile feature. Separate:
- UI components from logic
- API calls from components
Show the file structure and one-line responsibility for each.

Result:

components/
  ProfileView.tsx  // Display user data
  ProfileEdit.tsx  // Edit form
hooks/
  useProfile.ts    // Fetch and update logic
api/
  profileAPI.ts    // HTTP calls

Good enough. This covers 80% of features you'll build.

Level 2: Full Architecture (Complex Systems)

When to use: Payment flows, auth systems, multi-step wizards, features touching 3+ existing systems

Example prompt:

Design the structure for a checkout flow with cart, shipping, payment, and confirmation.
Output:
- Directory structure
- Component responsibilities
- State management approach
- How components communicate

The Reality of Iterative Development

Here's how structure actually evolves when working with AI:

Round 1: Start Simple

You: "Create a login form with email and password"
AI: *Generates single component*
You: *Use it, discover it's getting complex*

Round 2: Refactor When Needed

You: "This LoginForm component is doing too much. 
     Split it into smaller pieces."
AI: *Suggests separation of UI and logic*
You: *Implement the split*

Round 3: Add Structure As You Learn

You: "Now I need 2FA. How should this fit into 
     the current structure?"
AI: *Proposes minimal changes to accommodate*

This is normal and healthy. Architecture emerges through building, not planning.

Working With Your Team's Patterns

Most teams already have conventions. AI should follow them, not reinvent them.

Providing Context That Actually Helps

Instead of lengthy "you are an expert architect" preambles, give AI your actual patterns:

We use:
- Container/Presenter component pattern
- Custom hooks for business logic  
- Separate /api folder for all HTTP calls
- React Query for server state

Following these patterns, structure a user dashboard feature.

When You Don't Have Patterns Yet

If your team hasn't established patterns, use AI to explore options:

Show me 2 ways to structure a notification system:
1. Minimal (fewer files)
2. Scalable (more separation)

Keep explanations to one line per file.

Then pick what fits your team's style and complexity needs.

Real Examples: Structure Scaling in Practice

Example 1: Admin Dashboard → Single File

Requirement: Internal tool to view system metrics
Structure prompt: "Create an admin dashboard. Keep it simple, one file is fine."
Result: AdminDashboard.tsx with inline styles and fetch calls
Time saved: 2 hours of unnecessary abstraction
Lesson: Internal tools don't need elaborate architecture

Example 2: Blog Comments → Basic Separation

Requirement: Comment system with replies
Structure prompt: "Structure a comment system. Separate display from API calls."
Result:

CommentList.tsx (display)
CommentForm.tsx (input)
useComments.ts (logic)

Benefit: Easy to test, clear responsibilities
Lesson: Simple separation covers most needs

Example 3: Payment Integration → Full Architecture

Requirement: Multi-provider payment system
Structure prompt: Full architectural breakdown

"You are an expert software architect specializing in highly maintainable, scalable frontend applications. I need you to design the architecture for a login feature.

**Requirements:**
The feature must support email/password authentication, optional TOTP 2FA, and a basic account recovery flow.

**Instructions:**
Design a complete architectural plan. Do not write full implementation code. Your output must include:

1.  **File & Directory Structure:** A clear file organization following domain-driven principles for a React/TypeScript project.
2.  **Component Hierarchy:** Define the key React components and their single responsibilities.
3.  **State & Logic Management:** Define the custom hooks responsible for state, validation, and business logic.
4.  **Service Abstraction:** Define the API service layer responsible for all external communication.
5.  **Type Contracts:** Provide the essential TypeScript interfaces for data flows (e.g., props, API responses).
6.  **Testing Strategy:** Outline the testing approach for each layer (unit, integration).
7.  **Documentation:** Include a basic structure for a `README.md` file for this feature directory."

Result: 15+ files with clear boundaries

// 1. File & Directory Structure
src/
└── features/
    └── auth/
        ├── components/
        │   ├── LoginContainer.tsx
        │   ├── LoginForm.tsx
        │   ├── TOTPChallenge.tsx
        │   └── __tests__/
        ├── hooks/
        │   ├── useAuthFlow.ts
        │   └── useLoginValidation.ts
        ├── services/
        │   ├── authAPI.ts
        │   └── tokenStorage.ts
        ├── types/
        │   └── index.ts
        └── README.md

// 2. Component Hierarchy & Responsibilities
// - `LoginContainer.tsx`: Orchestrates the entire flow. Manages state via `useAuthFlow`.
// - `LoginForm.tsx`: A pure, controlled UI component for email/password entry.
// - `TOTPChallenge.tsx`: A pure UI component for entering the 2FA code.

// ... (Other sections like Interfaces and Testing Strategy) ...

// 7. README.md Structure
# Authentication Feature
This directory contains all code related to user authentication.
- **/components**: Reusable React components (UI only).
- **/hooks**: Business logic and state management.
- **/services**: API layer abstraction.
- **/types**: TypeScript interfaces for this feature.

Benefit: Different team members could work on different parts
Lesson: Complex systems justify upfront design

Practical Prompting Patterns

Pattern 1: The Quick Structure Check

When starting any feature, take 30 seconds:

"I'm building [feature]. 
Should this be: single file, basic separation, or full architecture?
Why?"

Pattern 2: The Refactor Prompt

When code gets messy:

"This component does: [list responsibilities].
How should I split it up? Keep suggestions minimal."

Pattern 3: The Integration Prompt

When adding to existing code:

"Current structure: [paste file tree].
Adding: [new feature].
Where should new code go?"

Pattern 4: The Pattern Extractor

After building something good:

"I like how this turned out: [paste structure].
Extract the reusable pattern for similar features."

When Structure-First Actually Matters

Always for:

  • Payment or authentication (high risk)

  • Features you'll replicate across projects

  • Systems touching 3+ existing services

  • When onboarding new team members

Sometimes for:

  • Features with complex state

  • When you're stuck on organization

  • First implementation of a new pattern

Skip for:

  • Prototypes or experiments

  • One-off scripts or tools

  • Well-understood CRUD operations

  • When following existing patterns

Common Pitfalls and Solutions

Pitfall 1: Over-Engineering Simple Features

Symptom: 10 files for a contact form
Solution: Start simple, refactor if needed
Prompt fix: Add "keep it simple" to your prompts

Pitfall 2: Under-Engineering Complex Features

Symptom: 500-line components with mixed concerns
Solution: Step back, ask for structure
Prompt fix: "This is getting complex. Suggest a better structure."

Pitfall 3: Ignoring Team Conventions

Symptom: Every feature structured differently
Solution: Document patterns, include in prompts
Prompt fix: Create a team prompt template with conventions

Pitfall 4: Treating Architecture as Sacred

Symptom: Refusing to deviate from initial structure
Solution: Architecture should evolve with understanding
Prompt fix: "Given what we've learned, should we restructure?"

The Reusability Reality

"Reusable architectures" sounds great, but here's the truth:

  • Each project has different constraints

  • Requirements are unique

  • Team conventions vary

What's actually reusable: Patterns and principles, not exact structures.

Better approach: Learn to recognize when you need:

  • Simple colocation (same file)

  • Basic separation (UI/logic split)

  • Full layering (complex systems)

Use AI to apply these patterns to your specific context.

Tool Setup (Keep It Simple)

Model: Any modern AI (Claude 3.5, GPT-4) handles structure well
Integration: Whatever you're already using—no special setup needed
Storage: Don't over-organize prompts. Copy good ones to a team doc
Anti-pattern: Building elaborate prompt management systems

The Compound Effect

This approach creates a practical feedback loop:

right-sized structure → cleaner code → easier maintenance → faster development

More importantly, you develop an intuition for when structure matters. After a few months, you'll instinctively know when to ask for architecture versus diving straight into code.

The Bottom Line

Structure-first prompting is a tool, not a religion. Use it when complexity demands it. Skip it when simplicity suffices. The best architecture is the simplest one that solves your actual problem.

Most features need just enough structure to avoid chaos—usually a simple separation of UI and logic. Save elaborate architecture for the genuinely complex systems that warrant it.

The skill isn't in creating perfect architectures. It's in quickly identifying how much structure you actually need, then using AI to help implement that level of organization. Start simple, iterate as needed, and let structure emerge from real requirements, not theoretical ideals.

This upgrade comes from Stage 2: Forge the Foundation of Prompt-to-ProductionRead the full 6-stage system

Reply

or to participate.