DEVELOPMENT STANDARDS - AI PROMPT
PURPOSE OF THIS AI PROMPT
What This Document Does
- Provides development standards - Consistent coding practices across all files
- Provides context for AI assistants - Complete information for faster debugging
- Makes debugging rational and easy - Clear patterns and error handling
- Saves time in AI conversations - Context eliminates repetitive explanations
The Debugging Reality
- When Claude has ALL information: Debugging process is almost instantaneous
- When Claude lacks context: Debugging process is sometimes very painful
- Change logs provide context: AI understands file relationships immediately
- Error handling provides clues: Debug messages show exactly what failed
Why These Standards Matter
- No IDE available - Standards compensate for lack of advanced tooling
- Manual debugging required - Clear patterns make problems obvious
- Programs are already complex - Standards keep everything else simple
- Adding complications to complicated systems creates chaos - Simplicity prevents this
- Professional code required - Clean standards support serious applications
CRITICAL REQUIREMENTS - ALL MANDATORY
ERROR HANDLING AND CHANGE LOGS ARE NON-NEGOTIABLE
FILE LENGTH LIMITS ARE HARD LIMITS - CODE OVER 300 LINES WILL BE REJECTED
ERROR HANDLING AND CHANGE LOGS ARE NON-NEGOTIABLE
FILE LENGTH LIMITS ARE HARD LIMITS - CODE OVER 300 LINES WILL BE REJECTED
FILE LENGTH LIMITS (ABSOLUTELY MANDATORY)
Maximum File Sizes - NO EXCEPTIONS
- Python files: 300 lines maximum (HARD LIMIT)
- JavaScript files: 300 lines maximum
- CSS files: 200 lines maximum
- HTML files: 150 lines maximum
Why 300 Lines Maximum
- No IDE available - Must be manageable in basic text editor
- Manual refactoring required - Cannot handle large files
- Debugging becomes impossible - Large files are unmanageable
- Code over 300 lines WILL BE REJECTED
PYTHON CODING STANDARDS (CRITICAL)
NO CLASSES RULE
- NO classes unless absolutely unavoidable
- Small volume application - classes add unnecessary complexity
- Function-based approach only
- Keep everything simple and direct
INDENTATION REQUIREMENTS
- Indent to far left where practical and follows good practices
- Avoid deep nesting - use early returns instead
- Maximum 2-3 levels of indentation
- Break complex conditions into separate functions
EARLY RETURN PATTERN (REQUIRED)
def good_function(user_id): if not user_id: print("ERROR: good_function - Missing user_id") return None conn = get_connection() if not conn: print("ERROR: good_function - No database connection") return None cur = conn.cursor() if not cur: print("ERROR: good_function - No cursor") return None cur.execute("SELECT * FROM users WHERE id = %s", (user_id,)) result = cur.fetchone() if not result: print("ERROR: good_function - User not found") return None print("DEBUG: good_function - User found") return result
ERROR HANDLING REQUIREMENTS (NON-NEGOTIABLE)
- EVERY function MUST have try/except blocks
- EVERY database operation MUST handle MySQLError and generic Exception
- EVERY function MUST print debug messages for success and error cases
- EVERY database connection MUST be properly closed in finally blocks
- EVERY error MUST be logged to console with ERROR: prefix
- EVERY function MUST return sensible defaults on error
- NO operation is too simple to skip error handling
ERROR HANDLING TEMPLATE - USE THIS PATTERN
def example_function_with_mandatory_error_handling(): """ MANDATORY ERROR HANDLING PATTERN Copy this pattern for every function in this module """ # 1. Initialize all variables that need cleanup conn = None cur = None try: # 2. Add debug print at function start print(f"DEBUG: function_name - Starting at {datetime.now()}") # 3. Validate all inputs FIRST if not valid_input: print(f"ERROR: function_name - Invalid input: {input_value}") return default_value # 4. Get database connection conn = get_db_connection() if not conn: print(f"ERROR: function_name - Failed to get database connection") return default_value # 5. Your database operations here cur = conn.cursor(dictionary=True) # ... database operations ... # 6. Success debug message print(f"DEBUG: function_name - Operation successful") return result except MySQLError as e: # 7. Handle database-specific errors print(f"ERROR: function_name - MySQL error: {e}") if conn: conn.rollback() return default_value except Exception as e: # 8. Handle all other errors print(f"ERROR: function_name - Unexpected error: {e}") print(f"ERROR: function_name - Traceback: {traceback.format_exc()}") if conn: conn.rollback() return default_value finally: # 9. ALWAYS clean up resources if cur: cur.close() print(f"DEBUG: function_name - Database cursor closed") if conn: conn.close() print(f"DEBUG: function_name - Database connection closed") print(f"DEBUG: function_name - Function completed at {datetime.now()}")
CHANGE LOG REQUIREMENTS (MANDATORY FOR ALL FILES)
PURPOSE OF CHANGE LOGS
- Saves time when returning to code - Know immediately what file does
- Informs AI assistants - Provides context for code modifications
- Helps users understand - Clear purpose and dependencies at a glance
- Prevents confusion - No guessing about file relationships or routes
- Tracks evolution - See what changed and when for debugging
- Identifies ownership - Know which blueprint or system owns the file
- Provides AI context - Next chat session will be faster with full context
- Shows hierarchy - Which orchestrator, blueprint, or main app controls this file
CHANGE LOG REQUIREMENTS
- EVERY file MUST have a change log at the top with file path
- Change logs MUST be HTML comments for .html files
- Change logs MUST be Python comments for .py files
- Change logs MUST be JavaScript comments for .js files
- Change logs MUST be CSS comments for .css files
- INCLUDE: File path, Document type, Purpose, Version history, Route info, Blueprint info
- Change logs MUST be VISIBLE in browser/editor (no hidden formatting)
- NEVER use brackets or hidden characters that browser can't display
- Add new entries at the top with date and description
FILE NAMING CONVENTIONS
- Python Blueprints: {purpose}_blueprint.py
- JavaScript Modules: {purpose}-{type}.js
- CSS Files: {purpose}.css
- HTML Templates: {purpose}.html
CHANGE LOG TEMPLATE FOR HTML FILES
<!-- CHANGE LOG File: /templates/login.html Document Type: HTML Template Purpose: User login form with 2FA photo upload for area mapping system Main App: area_mapping_app.py Blueprint: auth_blueprint.py Route: /login Context: Federal grant application requires secure user authentication with photo verification JavaScript Orchestrator: login-handler.js CSS Dependencies: login.css Version History: 2025-07-04 v1.1 - Added 2FA photo upload functionality for grant compliance 2025-07-01 v1.0 - Initial creation -->
CHANGE LOG TEMPLATE FOR PYTHON FILES
# CHANGE LOG # File: /routes/auth_blueprint.py # Document Type: Flask Blueprint # Purpose: Authentication routes for login/register with 2FA photo verification # Main App: area_mapping_app.py # Blueprint: auth_blueprint.py (this file) # Routes: /login, /register, /logout # Context: Secure authentication system for area mapping to support federal grant applications # Dependencies: flask, bcrypt, mysql.connector, utils.image_processing # Related Templates: login.html, register.html # Version History: # 2025-07-04 v1.1 - Added photo hash verification for enhanced security # 2025-07-01 v1.0 - Initial creation
CHANGE LOG TEMPLATE FOR JAVASCRIPT FILES
/* CHANGE LOG File: /static/js/login-handler.js Document Type: JavaScript Module (Orchestrator) Purpose: Orchestrates login form submission and 2FA photo handling Main App: area_mapping_app.py Blueprint: auth_blueprint.py Route: /login Context: Handles client-side photo compression and form submission for secure authentication Orchestrator Role: Coordinates photo-compression.js and login-api.js modules HTML Template: login.html Dependencies: photo-compression.js, login-api.js Version History: 2025-07-04 v1.1 - Added photo compression integration 2025-07-01 v1.0 - Initial creation */
CHANGE LOG TEMPLATE FOR CSS FILES
/* CHANGE LOG File: /static/css/login.css Document Type: CSS Stylesheet Purpose: Styling for login and registration forms in area mapping system Main App: area_mapping_app.py Blueprint: auth_blueprint.py Routes: /login, /register Context: Simple black and white styling for professional appearance in grant documentation HTML Templates: login.html, register.html Dependencies: None Version History: 2025-07-04 v1.1 - Added photo upload styling 2025-07-01 v1.0 - Initial creation */
INFORMATION GATHERING REQUIREMENTS (MANDATORY)
ASK FIRST - CODE SECOND
- When user says "don't do any coding yet" - STOP and ASK for information
- NEVER start coding without complete information
- If endpoints are unknown - ASK for exact endpoint names
- If variable names are unclear - ASK for existing naming conventions
- If file structure is unknown - ASK for directory paths
- If dependencies are unclear - ASK for import statements
REQUIRED INFORMATION BEFORE CODING
- Exact endpoint names and routes
- Existing variable naming patterns
- File paths and directory structure
- Database table names and column names
- Function names that already exist
- Blueprint names and registration patterns
SMART QUESTIONING PATTERN
- Ask: "Before I code, can you provide the following information:"
- List exactly what information is needed
- Wait for complete answers before proceeding
- Confirm understanding before writing any code
MANDATORY: ASK BEFORE CODING
When information is missing or unclear - ASK FIRST
Never guess or assume - get exact specifications
"Don't do any coding yet" means STOP and gather information
When information is missing or unclear - ASK FIRST
Never guess or assume - get exact specifications
"Don't do any coding yet" means STOP and gather information
ENDPOINT AND ROUTE ACCURACY
- NEVER change existing endpoint names - Use exact routes as provided
- If endpoint is /upload-photos - DO NOT change to /api/upload-photos
- If endpoint is /login - DO NOT change to /auth/login
- NEVER assume "logical" naming conventions - Use what exists
- Check existing routes before creating new ones
- Hours of debugging result from mismatched endpoint names
VARIABLE AND FUNCTION NAMING
- Use exact variable names as provided in existing code
- Do not "improve" or "standardize" naming without permission
- If user says "photo_id" - do not change to "photoId" or "image_id"
- Consistency with existing code trumps naming preferences
AI HALLUCINATION PREVENTION
- Do not create "logical" endpoints that don't exist
- Do not assume standard REST conventions unless confirmed
- When in doubt, ask for the exact endpoint name
- Reference existing code patterns instead of inventing new ones
CRITICAL: ENDPOINT ACCURACY
Using wrong endpoint names causes hours of debugging
Always use EXACT routes and naming as provided
Never assume or "improve" naming conventions
Using wrong endpoint names causes hours of debugging
Always use EXACT routes and naming as provided
Never assume or "improve" naming conventions
MANDATORY RULES - NO EXCEPTIONS
- ONLY implement what is specifically requested
- NO "helpful" features unless explicitly asked
- NO unnecessary complexity - No icons, animations, pretty styling, or distracting elements
- EVERY additional feature is a potential bug
- Extra code means more things to debug and maintain
- AI creativity is NOT helpful in production code
- Focus ONLY on solving the specific problem stated
- Complex programs need simple components - Do not add to existing complexity
- Function over beauty - Professional and functional without decoration
- Ask before adding ANY enhancements
COMPLEXITY EXAMPLES TO AVOID
- DON'T ADD: Icons, progress bars, loading spinners, animations
- DON'T ADD: Copy buttons, tooltips, help modals, pretty styling
- DON'T ADD: Extra validation, auto-complete, suggestions
- DON'T ADD: Gradients, shadows, hover effects, decorative elements
- DON'T ADD: Auto-save, draft functionality, convenience features
- DON'T ADD: Notifications, alerts, status indicators
- DON'T ADD: Settings, preferences, customization options
- DON'T ADD: Search, filtering, sorting unless specifically requested
SIMPLE EXAMPLES TO FOLLOW
- DO: Basic forms with submit buttons
- DO: Plain text messages and responses
- DO: Standard HTML inputs and elements
- DO: Minimal CSS for layout and readability only
- DO: Console logging for debugging purposes
- DO: Simple success/failure responses
FINAL CHECKLIST FOR EVERY FILE
- Change log at top with complete information
- File follows naming convention
- All functions have error handling
- All database connections properly closed
- Debug messages for success and error cases
- File under 300 lines (MANDATORY)
- NO extra features added
- Only implements what was requested
- Visible change log (no hidden formatting)
- Python code avoids classes and deep nesting
- Uses early return pattern for cleaner code
PROJECT REFERENCE GENERATOR SCRIPT
PURPOSE
- Standalone Python script for any project root
- Recursively scans all files and extracts callable items
- Generates text file for AI assistant context
- Prevents hours of debugging from mismatched endpoint names
- Shows inconsistencies with filename and line numbers
WHAT IT EXTRACTS
- Python Routes: @app.route and @blueprint.route decorators with methods
- Python Functions: All def statements that could be imported or called
- JavaScript Functions: function declarations and const/let function assignments
- AJAX Calls: fetch() and XMLHttpRequest endpoints
- File Locations: Filename and line number for each item (grep-style)
OUTPUT FORMAT EXAMPLE
=== PYTHON ROUTES === /routes/auth_blueprint.py:23: @blueprint.route('/login', methods=['POST']) /routes/auth_blueprint.py:45: @blueprint.route('/upload-photos', methods=['POST']) /routes/mapping_blueprint.py:12: @blueprint.route('/save-mapping', methods=['POST']) === PYTHON FUNCTIONS === /utils/auth_helpers.py:15: def login_user(email, password): /utils/image_processing.py:8: def compress_image(file): /routes/auth_blueprint.py:67: def verify_photo_hash(uploaded, stored): === JAVASCRIPT FUNCTIONS === /static/js/login-handler.js:23: function handlePhotoUpload() { /static/js/login-api.js:15: function submitLoginForm(data) { /static/js/photo-compression.js:8: function compressImage(file) { === AJAX ENDPOINTS === /static/js/login-api.js:25: fetch('/login', { /static/js/photo-upload.js:12: fetch('/upload-photos', { /static/js/mapping-api.js:18: fetch('/save-mapping', {
USAGE
- Drop script in project root directory
- Run: python extract_project_reference.py
- Creates: project_reference.txt
- Copy contents to AI assistant for complete context
- Spot endpoint mismatches and inconsistencies instantly
SCRIPT TEMPLATE
# CHANGE LOG # File: /endpoints.py # Document Type: Python Utility Script # Purpose: Extract all routes, functions, and AJAX calls from project files recursively # Main App: Any Flask project (portable script) # Dependencies: pathlib, re, os, datetime # Context: Creates complete project reference for AI assistants to prevent endpoint mismatches # Version History: # 2025-07-04 v1.1 - Fixed virtual environment scanning, suppressed zero results, show actual endpoints # 2025-07-04 v1.0 - Initial creation with full error handling and extraction logic #!/usr/bin/env python3 """ Project Reference Generator Drop in project root and run to extract all callable items Creates project_reference.txt with complete API/function inventory """ import os import re import traceback from pathlib import Path from datetime import datetime def extract_python_routes(file_path): """ Extract @app.route and @blueprint.route decorators from Python file """ routes = [] try: with open(file_path, 'r', encoding='utf-8') as f: lines = f.readlines() for line_num, line in enumerate(lines, 1): line = line.strip() # Match @app.route or @blueprint.route patterns route_pattern = r'@(?:app|blueprint|[\w_]+)\.route\([\'"]([^\'"]+)[\'"](?:.*methods\s*=\s*\[(.*?)\])?.*\)' match = re.search(route_pattern, line) if match: route_path = match.group(1) methods = match.group(2) if match.group(2) else 'GET' routes.append(f"{file_path}:{line_num}: @route('{route_path}', methods=[{methods}])") # Only show debug message if routes found if routes: print(f"DEBUG: extract_python_routes - Found {len(routes)} routes in {file_path}") return routes except FileNotFoundError: print(f"ERROR: extract_python_routes - File not found: {file_path}") return [] except UnicodeDecodeError: print(f"ERROR: extract_python_routes - Cannot decode file: {file_path}") return [] except Exception as e: print(f"ERROR: extract_python_routes - Error processing {file_path}: {e}") print(f"ERROR: extract_python_routes - Traceback: {traceback.format_exc()}") return [] def extract_python_functions(file_path): """ Extract function definitions from Python file """ functions = [] try: with open(file_path, 'r', encoding='utf-8') as f: lines = f.readlines() for line_num, line in enumerate(lines, 1): line = line.strip() # Match function definitions func_pattern = r'^def\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*\(' match = re.match(func_pattern, line) if match: func_name = match.group(1) # Skip private functions starting with _ if not func_name.startswith('_'): functions.append(f"{file_path}:{line_num}: def {func_name}()") # Only show debug message if functions found if functions: print(f"DEBUG: extract_python_functions - Found {len(functions)} functions in {file_path}") return functions except FileNotFoundError: print(f"ERROR: extract_python_functions - File not found: {file_path}") return [] except UnicodeDecodeError: print(f"ERROR: extract_python_functions - Cannot decode file: {file_path}") return [] except Exception as e: print(f"ERROR: extract_python_functions - Error processing {file_path}: {e}") print(f"ERROR: extract_python_functions - Traceback: {traceback.format_exc()}") return [] def extract_javascript_functions(file_path): """ Extract JavaScript function declarations and assignments """ functions = [] try: with open(file_path, 'r', encoding='utf-8') as f: lines = f.readlines() for line_num, line in enumerate(lines, 1): line = line.strip() # Match function declarations func_patterns = [ r'function\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*\(', r'const\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*function', r'let\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*function', r'var\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*function', r'const\s+([a-zA-Z_][a-zA-Z0-9_]*)\s*=\s*\(', r'([a-zA-Z_][a-zA-Z0-9_]*)\s*:\s*function\s*\(' ] for pattern in func_patterns: match = re.search(pattern, line) if match: func_name = match.group(1) functions.append(f"{file_path}:{line_num}: function {func_name}()") break # Only show debug message if functions found if functions: print(f"DEBUG: extract_javascript_functions - Found {len(functions)} functions in {file_path}") return functions except FileNotFoundError: print(f"ERROR: extract_javascript_functions - File not found: {file_path}") return [] except UnicodeDecodeError: print(f"ERROR: extract_javascript_functions - Cannot decode file: {file_path}") return [] except Exception as e: print(f"ERROR: extract_javascript_functions - Error processing {file_path}: {e}") print(f"ERROR: extract_javascript_functions - Traceback: {traceback.format_exc()}") return [] def extract_ajax_calls(file_path): """ Extract AJAX calls and fetch requests from JavaScript files """ ajax_calls = [] try: with open(file_path, 'r', encoding='utf-8') as f: lines = f.readlines() for line_num, line in enumerate(lines, 1): line = line.strip() # Match fetch() calls and similar AJAX patterns ajax_patterns = [ r'fetch\s*\(\s*[\'"]([^\'"]+)[\'"]', r'\.get\s*\(\s*[\'"]([^\'"]+)[\'"]', r'\.post\s*\(\s*[\'"]([^\'"]+)[\'"]', r'\.put\s*\(\s*[\'"]([^\'"]+)[\'"]', r'\.delete\s*\(\s*[\'"]([^\'"]+)[\'"]', r'XMLHttpRequest.*open\s*\(\s*[\'"][A-Z]+[\'"],\s*[\'"]([^\'"]+)[\'"]' ] for pattern in ajax_patterns: match = re.search(pattern, line) if match: endpoint = match.group(1) ajax_calls.append(f"{file_path}:{line_num}: AJAX call to '{endpoint}'") break # Only show debug message if AJAX calls found if ajax_calls: print(f"DEBUG: extract_ajax_calls - Found {len(ajax_calls)} AJAX calls in {file_path}") return ajax_calls except FileNotFoundError: print(f"ERROR: extract_ajax_calls - File not found: {file_path}") return [] except UnicodeDecodeError: print(f"ERROR: extract_ajax_calls - Cannot decode file: {file_path}") return [] except Exception as e: print(f"ERROR: extract_ajax_calls - Error processing {file_path}: {e}") print(f"ERROR: extract_ajax_calls - Traceback: {traceback.format_exc()}") return [] def extract_project_reference(): """ Main function to recursively scan project and extract all callable items """ output_file = None try: print(f"DEBUG: extract_project_reference - Starting at {datetime.now()}") # Validate current directory if not os.path.exists('.'): print("ERROR: extract_project_reference - Current directory not accessible") return False # File patterns to scan - exclude virtual environments and common non-project directories python_files = [] js_files = [] # Get all Python and JS files while excluding unwanted directories for py_file in Path('.').rglob('*.py'): if not any(pattern in str(py_file) for pattern in ['venv', 'env', '.git', '__pycache__', 'build', 'dist', '.egg-info']): python_files.append(py_file) for js_file in Path('.').rglob('*.js'): if not any(pattern in str(js_file) for pattern in ['venv', 'env', '.git', 'node_modules', 'build', 'dist']): js_files.append(js_file) print(f"DEBUG: extract_project_reference - Found {len(python_files)} Python files") print(f"DEBUG: extract_project_reference - Found {len(js_files)} JavaScript files") if not python_files and not js_files: print("ERROR: extract_project_reference - No Python or JavaScript files found") return False results = [] # Add header with timestamp results.append("=" * 60) results.append(f"PROJECT REFERENCE GENERATED: {datetime.now()}") results.append("=" * 60) results.append("") # Extract Python routes and show them immediately print("\n=== EXTRACTING PYTHON ROUTES ===") results.append("=== PYTHON ROUTES ===") route_count = 0 for py_file in python_files: routes = extract_python_routes(py_file) if routes: for route in routes: print(route) # Show route immediately results.append(route) route_count += len(routes) results.append(f"Total routes found: {route_count}") results.append("") # Extract Python functions print(f"\n=== EXTRACTING PYTHON FUNCTIONS ===") results.append("=== PYTHON FUNCTIONS ===") func_count = 0 for py_file in python_files: functions = extract_python_functions(py_file) results.extend(functions) func_count += len(functions) results.append(f"Total functions found: {func_count}") results.append("") # Extract JavaScript functions print(f"\n=== EXTRACTING JAVASCRIPT FUNCTIONS ===") results.append("=== JAVASCRIPT FUNCTIONS ===") js_func_count = 0 for js_file in js_files: js_functions = extract_javascript_functions(js_file) results.extend(js_functions) js_func_count += len(js_functions) results.append(f"Total JavaScript functions found: {js_func_count}") results.append("") # Extract AJAX calls and show them immediately print(f"\n=== EXTRACTING AJAX ENDPOINTS ===") results.append("=== AJAX ENDPOINTS ===") ajax_count = 0 for js_file in js_files: ajax_calls = extract_ajax_calls(js_file) if ajax_calls: for ajax in ajax_calls: print(ajax) # Show AJAX call immediately results.append(ajax) ajax_count += len(ajax_calls) results.append(f"Total AJAX calls found: {ajax_count}") results.append("") # Write to project_reference.txt output_file = open('project_reference.txt', 'w', encoding='utf-8') output_file.write('\n'.join(results)) total_items = route_count + func_count + js_func_count + ajax_count print(f"DEBUG: extract_project_reference - Generated project_reference.txt with {total_items} items") print(f"DEBUG: extract_project_reference - Routes: {route_count}, Functions: {func_count}, JS Functions: {js_func_count}, AJAX: {ajax_count}") return True except PermissionError: print("ERROR: extract_project_reference - Permission denied writing project_reference.txt") return False except Exception as e: print(f"ERROR: extract_project_reference - Unexpected error: {e}") print(f"ERROR: extract_project_reference - Traceback: {traceback.format_exc()}") return False finally: if output_file: output_file.close() print("DEBUG: extract_project_reference - Output file closed") print(f"DEBUG: extract_project_reference - Function completed at {datetime.now()}") if __name__ == '__main__': print("=" * 60) print("PROJECT REFERENCE EXTRACTOR") print("Scanning project for routes, functions, and AJAX calls...") print("=" * 60) success = extract_project_reference() if success: print("\nSUCCESS: project_reference.txt created!") print("Copy the contents to your AI assistant for complete project context.") else: print("\nFAILED: Could not generate project reference.") print("Check error messages above for details.")
AI ASSISTANT BENEFIT:
When user provides project_reference.txt content, AI has complete context
No more guessing endpoint names or function signatures
Debugging becomes nearly instantaneous with full project inventory
When user provides project_reference.txt content, AI has complete context
No more guessing endpoint names or function signatures
Debugging becomes nearly instantaneous with full project inventory
REMINDERS:
Change logs MUST be visible in browser view-source
NO hidden characters or formatting that browsers can't display
Include ALL relevant information for troubleshooting
Both error handling AND change logs are MANDATORY
SIMPLICITY OVER CLEVERNESS - Simple code is maintainable code
Change logs MUST be visible in browser view-source
NO hidden characters or formatting that browsers can't display
Include ALL relevant information for troubleshooting
Both error handling AND change logs are MANDATORY
SIMPLICITY OVER CLEVERNESS - Simple code is maintainable code