How to write clear, complete development prompts that produce predictable, secure, and maintainable code with examples and a sample Express.js JWT login implementation
In this lesson you’ll learn how to write development prompts that produce predictable, secure, and maintainable code from an AI assistant. Clear, specific prompts reduce incorrect assumptions, unnecessary back-and-forth, and security oversights.
When a prompt is vague, the assistant fills gaps with assumptions. Sometimes those guesses match your intent; often they do not. The minimal example below shows how ambiguity quickly leads to unintended behavior.
Copy
* Welcome to the assistant!cwd: /Users/jeremy/Repos/Claude Code Course/Express-login-demo> Make a login screen
Because the project folder contains “Express-login-demo”, the assistant assumes an Express-based solution. It may begin exploring the repository and proposing an Express implementation — fine if that’s your intent, but problematic if you expected a different stack or a different authentication flow.The assistant might try discovery commands like:
Copy
find /Users/jeremy/Repos/Claude\ Code\ Course/Express-login-demo -type f -name "*.js" -o -name "*.json" -o -name "*.html" -o -name "*.css" | head -20
If the repository is empty, this leads to unnecessary exploration and follow-up questions, slowing development. Vague prompts also cause missing concerns (validation, error handling, security requirements) because the model must guess which constraints matter to you.
A better prompt — be explicit about intent and constraints
A good prompt explicitly states the stack, the endpoint, validation rules, authentication expectations, and desired responses. This reduces ambiguity and lets the assistant produce runnable code with fewer clarifications.Example improved prompt:
Copy
Create a POST /api/auth/login endpoint using Express.js with the following requirements:Input:- email (string, required, must be a valid email)- password (string, required, min 8 characters)Process:- Validate input using express-validator- Check if user exists in PostgreSQL database- Compare password using bcrypt- Generate JWT token with 24h expirationResponse:- Success: { token, user: { id, email, name } }- Failure: Appropriate error message and status codeInclude error handling for database failures and validation errors.
Because this prompt specifies technology, validation, security, and responses, the assistant can generate a complete implementation with far fewer clarifying questions.
Example project changes the assistant might create
Below are concise, corrected snippets that implement the requirements above. These files illustrate a minimal but production-minded Express + PostgreSQL + JWT authentication flow.package.json (created by initialization)
const { Pool } = require('pg');const pool = new Pool({ host: process.env.DB_HOST, port: Number(process.env.DB_PORT || 5432), database: process.env.DB_NAME, user: process.env.DB_USER, password: process.env.DB_PASSWORD,});pool.on('connect', () => { console.log('Connected to PostgreSQL database');});pool.on('error', (err) => { console.error('Unexpected error on idle client', err); process.exit(-1);});module.exports = pool;
schema.sql (table for users)
Copy
-- Connect to database: \c express_login_demoCREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, email VARCHAR(255) UNIQUE NOT NULL, password_hash VARCHAR(255) NOT NULL, name VARCHAR(255), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
Status-code guidance (common HTTP status codes used here)
Status Code
Use Case
400
Validation errors (bad input)
401
Invalid credentials / unauthorized
503
Database connection or service unavailable
500
Generic server error
To use the endpoint: set up your PostgreSQL database, configure credentials in .env, run schema.sql to create the users table, install dependencies (npm install), and start the server (npm start or npm run dev).
Use a concise formula to craft prompts that minimize follow-up:
Context: Describe the environment or codebase (stack, existing endpoints, naming conventions, constraints).
Action: Exactly what you want done (for example, “Create POST /api/auth/login endpoint”).
Details: Validation rules, libraries to use, security requirements, response shapes, and error handling.
Examples: Provide sample request/response payloads or short output examples to set expectations.
Tip: Put the most important constraints (stack, required libraries, validation rules, and response format) at the start of the prompt. Spending a minute to write a clear, complete prompt often saves 10+ minutes of revision.
Clear: Avoid ambiguity and name the exact behavior you expect.
Complete: Include all requirements and constraints up front.
Contextual: Provide relevant background—existing patterns, environment, or architecture decisions.
When your prompt is clear, complete, and contextual and includes a short example of expected output, the assistant will produce focused, usable code with minimal rework.