AI Skill Report Card
Creating Local HTML Apps
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 = ``; } </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
Step-by-step Process
-
Start with HTML skeleton
- Use semantic HTML5 elements
- Include viewport meta tag for mobile
- Add charset UTF-8
-
Add styling
- Embed CSS in
<style>tags for single-file apps - Use external CSS:
<link rel="stylesheet" href="styles.css"> - Include responsive design basics
- Embed CSS in
-
Implement functionality
- Embed JavaScript in
<script>tags - Use external JS:
<script src="script.js"></script> - Handle user interactions with event listeners
- Embed JavaScript in
-
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
localStoragefor 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">