AI-Friendly Coding Patterns
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
- Try the Flask Prompt Generator
- Read Clean Routes with the OpenAI API
- Build a Complete Flask + PostgreSQL App
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.