AI Skill Report Card

Creating Local HTML Apps

A-85·Feb 20, 2026·Source: Web

Quick Start

Create a single HTML file with embedded CSS and JavaScript:

HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>My Local App</title> <style> body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; } .container { background: #f5f5f5; padding: 20px; border-radius: 8px; } </style> </head> <body> <div class="container"> <h1>Local HTML App</h1> <input type="text" id="input" placeholder="Enter text"> <button onclick="processInput()">Process</button> <div id="output"></div> </div> <script> function processInput() { const input = document.getElementById('input').value; const output = document.getElementById('output'); output.innerHTML = `<p>You entered: <strong>${input}</strong></p>`; } </script> </body> </html>

Workflow

Progress:

  • Create base HTML structure with DOCTYPE and meta tags
  • Add CSS styling (embedded or external)
  • Implement JavaScript functionality (embedded or external)
  • Test in browser by opening file directly
  • Add data persistence if needed (localStorage)
  • Optimize for offline usage
  1. Start with HTML skeleton

    • Use semantic HTML5 elements
    • Include viewport meta tag for mobile
    • Add charset UTF-8
  2. Add styling

    • Embed CSS in <style> tags for single-file apps
    • Use external CSS: <link rel="stylesheet" href="styles.css">
    • Include responsive design basics
  3. Implement functionality

    • Embed JavaScript in <script> tags
    • Use external JS: <script src="script.js"></script>
    • Handle user interactions with event listeners
  4. Test locally

    • Open HTML file directly in browser
    • Test all features work offline
    • Verify on different browsers

Examples

Example 1: Todo List Input: Need a simple task manager Output:

HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Todo List</title> <style> body { font-family: Arial, sans-serif; margin: 20px; } .completed { text-decoration: line-through; opacity: 0.6; } input[type="text"] { padding: 8px; margin: 5px; } button { padding: 8px 12px; margin: 2px; } ul { list-style: none; padding: 0; } li { padding: 8px; border-bottom: 1px solid #eee; } </style> </head> <body> <h1>Todo List</h1> <input type="text" id="taskInput" placeholder="Add new task"> <button onclick="addTask()">Add</button> <ul id="taskList"></ul> <script> let tasks = JSON.parse(localStorage.getItem('tasks') || '[]'); function renderTasks() { const list = document.getElementById('taskList'); list.innerHTML = tasks.map((task, index) => `<li class="${task.completed ? 'completed' : ''}"> <input type="checkbox" ${task.completed ? 'checked' : ''} onchange="toggleTask(${index})"> ${task.text} <button onclick="deleteTask(${index})">Delete</button> </li>` ).join(''); } function addTask() { const input = document.getElementById('taskInput'); if (input.value.trim()) { tasks.push({text: input.value, completed: false}); input.value = ''; saveTasks(); renderTasks(); } } function toggleTask(index) { tasks[index].completed = !tasks[index].completed; saveTasks(); renderTasks(); } function deleteTask(index) { tasks.splice(index, 1); saveTasks(); renderTasks(); } function saveTasks() { localStorage.setItem('tasks', JSON.stringify(tasks)); } renderTasks(); </script> </body> </html>

Example 2: Calculator Input: Need a basic calculator Output:

HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Calculator</title> <style> .calculator { width: 300px; margin: 50px auto; background: #333; padding: 20px; border-radius: 10px; } .display { width: 100%; height: 60px; font-size: 24px; text-align: right; padding: 0 10px; margin-bottom: 10px; background: #000; color: white; border: none; } .buttons { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; } button { height: 60px; font-size: 18px; border: none; border-radius: 5px; cursor: pointer; } .num { background: #666; color: white; } .op { background: #ff9500; color: white; } .eq { background: #ff9500; color: white; grid-column: span 2; } </style> </head> <body> <div class="calculator"> <input type="text" class="display" id="display" readonly> <div class="buttons"> <button onclick="clearAll()">C</button> <button onclick="clearEntry()">CE</button> <button onclick="addToDisplay('/')" class="op">÷</button> <button onclick="addToDisplay('*')" class="op">×</button> <button onclick="addToDisplay('7')" class="num">7</button> <button onclick="addToDisplay('8')" class="num">8</button> <button onclick="addToDisplay('9')" class="num">9</button> <button onclick="addToDisplay('-')" class="op"></button> <button onclick="addToDisplay('4')" class="num">4</button> <button onclick="addToDisplay('5')" class="num">5</button> <button onclick="addToDisplay('6')" class="num">6</button> <button onclick="addToDisplay('+')" class="op">+</button> <button onclick="addToDisplay('1')" class="num">1</button> <button onclick="addToDisplay('2')" class="num">2</button> <button onclick="addToDisplay('3')" class="num">3</button> <button onclick="calculate()" class="eq">=</button> <button onclick="addToDisplay('0')" class="num">0</button> <button onclick="addToDisplay('.')" class="num">.</button> </div> </div> <script> function addToDisplay(value) { document.getElementById('display').value += value; } function clearAll() { document.getElementById('display').value = ''; } function clearEntry() { const display = document.getElementById('display'); display.value = display.value.slice(0, -1); } function calculate() { const display = document.getElementById('display'); try { display.value = eval(display.value.replace('×', '*').replace('÷', '/')); } catch { display.value = 'Error'; } } </script> </body> </html>

Best Practices

  • Use semantic HTML - <header>, <main>, <section>, <article>
  • Include viewport meta tag for mobile responsiveness
  • Store data locally with localStorage for persistence
  • Handle errors gracefully with try-catch blocks
  • Use external files when app grows beyond 500 lines
  • Test offline functionality - works without internet
  • Validate inputs before processing user data
  • Use consistent naming for functions and variables

Common Pitfalls

  • Don't use eval() for user input (security risk)
  • Don't forget charset declaration - causes encoding issues
  • Don't rely on server features - no PHP, databases, or server-side code
  • Don't use absolute paths - breaks when moving files
  • Don't skip error handling - apps crash on invalid input
  • Don't ignore mobile users - always include viewport meta tag
  • Don't hardcode file paths - use relative paths for portability

File Structure for Multi-file Apps

project/
├── index.html
├── styles.css
├── script.js
└── assets/
    ├── images/
    └── fonts/

Link files relatively:

HTML
<link rel="stylesheet" href="styles.css"> <script src="script.js"></script> <img src="assets/images/logo.png" alt="Logo">
0
Grade A-AI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
15/15
Workflow
13/15
Examples
20/20
Completeness
18/20
Format
15/15
Conciseness
14/15