ai-coding intermediate

AI-Friendly Coding Patterns

min read Frederick Tubiermont

AI-Friendly Coding Patterns

In 2026, writing code for AI comprehension is as important as writing for humans.

Principle: Explicit Over Implicit

The problem isn't decorators — @login_required from Flask-Login is perfectly fine to use. The issue is custom, project-specific decorators that silently inject data or transform the request in ways AI can't see.

❌ AI Struggles With This

# Custom decorators that inject things invisibly
@inject_current_user       # injects `user` into kwargs somehow
@auto_validate(UserSchema) # silently transforms request.json
@cache_result(ttl=300)     # may return early without running the function
def update_profile():
    # Where does `user` come from?
    # Has request data already been transformed?
    # Will this function even execute if cached?
    pass

✅ AI Loves This

from flask import request
from flask_login import login_required, current_user
from utils.db import get_db

@app.route('/profile/<int:user_id>', methods=['POST'])
@login_required  # fine: explicit, well-documented, widely understood
def update_profile(user_id):
    # Input validated explicitly
    name = request.form.get("name")
    if not name or len(name) < 2:
        return "Name too short", 400

    # Database updated explicitly
    with get_db() as conn:
        with conn.cursor() as cur:
            cur.execute(
                "UPDATE users SET name = %s WHERE id = %s",
                (name, user_id)
            )
            conn.commit()

    return "Updated successfully"

Standard decorators like @login_required, @app.route(), or @app.before_request are fine — they're in the AI's training data and do one obvious thing. The issue is home-grown decorator stacks that hide data flow.

Pattern: Direct Database Queries

AI can write reliable SQL. AI struggles with ORM abstractions.

❌ AI Hallucinates

# SQLAlchemy
user = User.query.join(Profile).filter(
    User.active == True,
    Profile.verified == True
).options(
    joinedload(User.posts).subqueryload(Post.comments)
).first()

✅ AI Gets It Right

with get_db() as conn:
    with conn.cursor() as cur:
        cur.execute("""
            SELECT u.*, p.*
            FROM users u
            JOIN profiles p ON p.user_id = u.id
            WHERE u.active = TRUE AND p.verified = TRUE
            LIMIT 1
        """)
        user = cur.fetchone()

Pattern: Vanilla JavaScript

❌ React Requires Managing Complexity

// Which React version? Client or Server component?
// Hooks API? Context? Redux? Zustand?
const [data, setData] = useState([]);
useEffect(() => {
  // Correct pattern depends heavily on React version + config
  // RSC vs client components, app router vs pages router...
}, [data]);

✅ Vanilla JS Has No Moving Parts

// Clear, direct, no build step
async function loadData() {
  const response = await fetch('/api/data');
  const data = await response.json();

  const container = document.getElementById('data-list');
  // Note: only interpolate trusted server data here.
  // If any field can contain user input, sanitize it before inserting via innerHTML.
  container.innerHTML = data.map(item => `
    <div class="item">
      <h3>${item.title}</h3>
      <p>${item.description}</p>
    </div>
  `).join('');
}

document.addEventListener('DOMContentLoaded', loadData);

The AI Prompt Formula

Good prompts for Flask Vibe stack:

Create a Flask route that:
1. [Specific action]
2. Uses psycopg2 with parameterized queries
3. Returns JSON or renders [template.html]
4. Includes error handling for [specific cases]
5. No ORM, no SQLAlchemy

Use vanilla JavaScript for:
1. [Frontend interaction]
2. Fetch API for AJAX
3. No React, no build tools
4. ES6+ syntax

Why This Works

  • AI training data: More examples of vanilla JS and raw SQL than framework magic
  • Verification: Easy for you to verify the generated code
  • Debugging: When something breaks, you can find it in 30 seconds
  • Iteration: AI can modify working code reliably

Real Example

Prompt:

"Create a Flask route that fetches the 10 most recent blog posts from a PostgreSQL table named 'posts' with columns: id, title, content, created_at. Use psycopg2. Return JSON."

AI Output (reliable):

from flask import jsonify
from utils.db import get_db

@app.route("/api/posts")
def get_posts():
    try:
        with get_db() as conn:
            with conn.cursor() as cur:
                cur.execute("""
                    SELECT id, title, content, created_at
                    FROM posts
                    ORDER BY created_at DESC
                    LIMIT 10
                """)
                posts = cur.fetchall()
        return jsonify([dict(p) for p in posts])
    except Exception as e:
        return jsonify({"error": str(e)}), 500

First try. Works immediately. No debugging.

Next Steps

Was this helpful?

Get More Flask Vibe Tutorials

Join 1,000+ developers getting weekly Flask tips and AI-friendly code patterns.

No spam. Unsubscribe anytime.