Courses Vibe Coding Dashboard Lesson 6.2
6.2 Module 6 · Bolt & Full-Stack AI

The Code Editor & File Structure

Code literacy workshop — explore a Bolt-generated file structure through an interactive file tree. Click into components, styles, and utilities. Learn to read (not write) React code to understand what AI built.

File Tree Explorer Code Reading Guide

File Tree Explorer

Click any file in the tree below to view its simplified code with annotations explaining what each section does. This is a typical Bolt-generated React project.

Project Files
0 explored

Select a file to view its contents

Key insight: You do not need to write React code to be effective with Bolt. But recognising the six patterns below — imports, components, state, props, styling, and exports — lets you understand what the AI built, why it structured things a certain way, and how to ask for targeted changes. Code literacy is reading comprehension, not writing ability.

Code Reading Guide — 6 Patterns

Click each pattern to learn what it looks like in code and why it matters for your prompts.

Comprehension Check

Previous: Bolt Quickstart Next: Choosing AI Agents & Models
',a:''}, {ln:11,code:'',a:''} ]}, { id:'src', name:'src/', type:'folder', depth:0 }, { id:'main', name:'main.jsx', type:'file', depth:1, desc:'App entry point', code:[ {ln:1,code:"import React from 'react';",a:'Import — pulls in the React library.'}, {ln:2,code:"import ReactDOM from 'react-dom/client';",a:''}, {ln:3,code:"import App from './App';",a:'Import — loads your main App component.'}, {ln:4,code:"import './index.css';",a:'Import — loads global styles.'}, {ln:5,code:'',a:''}, {ln:6,code:"ReactDOM.createRoot(document.getElementById('root'))",a:'Finds the #root div and renders the App component into it.'}, {ln:7,code:' .render();',a:'Component — is a React component being rendered.'} ]}, { id:'app', name:'App.jsx', type:'file', depth:1, desc:'Main application component', code:[ {ln:1,code:"import { useState } from 'react';",a:'Import — useState is a React hook for managing state.'}, {ln:2,code:"import TodoList from './components/TodoList';",a:'Import — loads the TodoList child component.'}, {ln:3,code:"import AddTodo from './components/AddTodo';",a:''}, {ln:4,code:'',a:''}, {ln:5,code:'export default function App() {',a:'Component + Export — defines and exports the App component.'}, {ln:6,code:' const [todos, setTodos] = useState([]);',a:'State — todos is the data, setTodos updates it. Starts as empty array.'}, {ln:7,code:' const [filter, setFilter] = useState("all");',a:'State — tracks which filter is active (all, active, completed).'}, {ln:8,code:'',a:''}, {ln:9,code:' const addTodo = (text) => {',a:'A function that creates a new todo and adds it to state.'}, {ln:10,code:' setTodos([...todos, { id: Date.now(), text, done: false }]);',a:''}, {ln:11,code:' };',a:''}, {ln:12,code:'',a:''}, {ln:13,code:' return (',a:''}, {ln:14,code:'
',a:'Styling — className is React\'s version of the HTML class attribute.'}, {ln:15,code:'

My Todos

',a:''}, {ln:16,code:' ',a:'Props — passes the addTodo function down to the AddTodo component.'}, {ln:17,code:' ',a:'Props — passes data (todos) and state (filter) to the child.'}, {ln:18,code:'
',a:''}, {ln:19,code:' );',a:''}, {ln:20,code:'}',a:''} ]}, { id:'comp', name:'components/', type:'folder', depth:1 }, { id:'todolist', name:'TodoList.jsx', type:'file', depth:2, desc:'Renders the list of todos', code:[ {ln:1,code:"export default function TodoList({ todos, filter }) {",a:'Props — destructures todos and filter from the props object.'}, {ln:2,code:' const filtered = todos.filter(t => {',a:'Filters the todo array based on the active filter.'}, {ln:3,code:' if (filter === "active") return !t.done;',a:''}, {ln:4,code:' if (filter === "completed") return t.done;',a:''}, {ln:5,code:' return true;',a:''}, {ln:6,code:' });',a:''}, {ln:7,code:'',a:''}, {ln:8,code:' return (',a:''}, {ln:9,code:' ',a:''}, {ln:16,code:' );',a:''}, {ln:17,code:'}',a:''} ]}, { id:'addtodo', name:'AddTodo.jsx', type:'file', depth:2, desc:'Input form for new todos', code:[ {ln:1,code:"import { useState } from 'react';",a:''}, {ln:2,code:'',a:''}, {ln:3,code:'export default function AddTodo({ onAdd }) {',a:'Props — receives the onAdd function from the parent.'}, {ln:4,code:' const [text, setText] = useState("");',a:'State — tracks the input field value.'}, {ln:5,code:'',a:''}, {ln:6,code:' const handleSubmit = (e) => {',a:'Handles form submission.'}, {ln:7,code:' e.preventDefault();',a:'Prevents the page from reloading on submit.'}, {ln:8,code:' if (text.trim()) {',a:'Only adds if the input is not empty.'}, {ln:9,code:' onAdd(text);',a:'Calls the parent function, passing the text up.'}, {ln:10,code:' setText("");',a:'Clears the input field after adding.'}, {ln:11,code:' }',a:''}, {ln:12,code:' };',a:''}, {ln:13,code:'',a:''}, {ln:14,code:' return (',a:''}, {ln:15,code:'
',a:''}, {ln:16,code:' setText(e.target.value)}',a:'Two-way binding: state drives the input, input updates state.'}, {ln:17,code:' placeholder="Add a new todo..." />',a:''}, {ln:18,code:' ',a:''}, {ln:19,code:'
',a:''}, {ln:20,code:' );',a:''}, {ln:21,code:'}',a:''} ]}, { id:'styles', name:'styles/', type:'folder', depth:1 }, { id:'indexcss', name:'index.css', type:'file', depth:2, desc:'Global stylesheet', code:[ {ln:1,code:':root {',a:'CSS custom properties — defines reusable colour values.'}, {ln:2,code:' --bg: #0a0a0a;',a:''}, {ln:3,code:' --text: #e5e5e5;',a:''}, {ln:4,code:' --accent: #84cc16;',a:'The lime accent colour used throughout the app.'}, {ln:5,code:'}',a:''}, {ln:6,code:'',a:''}, {ln:7,code:'body { background: var(--bg); color: var(--text); }',a:'Styling — applies the custom properties to the body.'}, {ln:8,code:'.todo-list li.done { text-decoration: line-through; opacity: 0.5; }',a:'Styles completed todos with a strikethrough.'} ]}, { id:'public', name:'public/', type:'folder', depth:0 }, { id:'favicon', name:'favicon.svg', type:'file', depth:1, desc:'App icon', code:[ {ln:1,code:'',a:''} ]} ]; const patterns = [ { id:'imports', num:1, title:'Imports', icon:'↧', color:'#60a5fa', desc:'Lines at the top that pull in libraries, components, and styles.', why:'Understanding imports tells you what dependencies the project uses and how components connect to each other. When something breaks, the import line often points you to the source.', example:"import { useState } from 'react';\nimport TodoList from './components/TodoList';" }, { id:'components', num:2, title:'Components', icon:'▭', color:'#a78bfa', desc:'Reusable building blocks — each one renders a piece of the UI.', why:'Components are the architecture of a React app. Knowing which components exist tells you how the UI is organised. You can ask Bolt to modify specific components by name.', example:"export default function App() {\n return
...
;\n}" }, { id:'state', num:3, title:'State', icon:'⚙', color:'#fb923c', desc:'Data that changes over time — the dynamic values driving the UI.', why:'State is what makes the app interactive. Understanding state helps you identify where data lives so you can ask Bolt to add features that depend on or modify that data.', example:"const [todos, setTodos] = useState([]);" }, { id:'props', num:4, title:'Props', icon:'↪', color:'#4ade80', desc:'Data passed from a parent component down to a child component.', why:'Props show the data flow between components. When a child component is not behaving correctly, the issue is often in what props it receives from its parent.', example:"" }, { id:'styling', num:5, title:'Styling', icon:'🎨', color:'#f472b6', desc:'How components get their visual appearance — CSS classes, inline styles, or CSS-in-JS.', why:'Recognising styling patterns lets you make precise visual requests. Instead of "make it look better," you can say "change the className on the list items" or "update the CSS custom properties."', example:'className="todo-list"\nstyle={{ color: "var(--accent)" }}' }, { id:'exports', num:6, title:'Exports', icon:'↩', color:'#facc15', desc:'The line that makes a component available to other files.', why:'Every component must be exported to be used elsewhere. The export default pattern means only one thing is exported per file — this is the component that other files import.', example:"export default function TodoList() { ... }" } ]; const quiz = [ { q:'In which file would you find the app\'s dependencies like React and icon libraries?', opts:['App.jsx','package.json','index.html','main.jsx'], correct:1 }, { q:'What does useState([]) create?', opts:['A CSS animation','A state variable initialised as an empty array','A new HTML element','A database connection'], correct:1 }, { q:'If you wanted Bolt to change the accent colour across the entire app, which file would you reference?', opts:['App.jsx','TodoList.jsx','index.css','package.json'], correct:2 }, { q:'What is the purpose of the
in index.html?', opts:['It styles the page background','React mounts the entire app inside it','It stores the todo data','It imports the CSS'], correct:1 } ]; // ══════════════════════════════════════════ // FILE TREE EXPLORER // ══════════════════════════════════════════ let selectedFile = null; let exploredFiles = new Set(); function renderTree() { const el = document.getElementById('file-tree'); el.innerHTML = fileTree.map(f => { const indent = f.depth * 20; const isFolder = f.type === 'folder'; const isSelected = selectedFile === f.id; const explored = exploredFiles.has(f.id); return `
${isFolder ? '' : ''} ${f.name} ${explored && !isFolder ? '' : ''}
`; }).join(''); el.querySelectorAll('[data-id]').forEach(item => { const f = fileTree.find(x => x.id === item.dataset.id); if (f.type === 'file') { item.addEventListener('click', () => { selectedFile = f.id; exploredFiles.add(f.id); renderTree(); renderCodeViewer(f); updateTreeProgress(); }); } }); } function renderCodeViewer(f) { const el = document.getElementById('code-viewer'); el.innerHTML = `
${f.name} ${f.desc || ''}
${f.code.map(line => { const hasAnnotation = line.a && line.a.length > 0; return `
${line.ln}${escHtml(line.code)}
${hasAnnotation ? '
' + line.a + '
' : ''}`; }).join('')}
`; } function escHtml(s) { return s.replace(/&/g,'&').replace(//g,'>'); } function updateTreeProgress() { const files = fileTree.filter(f => f.type === 'file'); const explored = files.filter(f => exploredFiles.has(f.id)).length; document.getElementById('tree-progress').style.width = Math.round((explored / files.length) * 100) + '%'; document.getElementById('tree-progress-text').textContent = explored + ' / ' + files.length + ' explored'; } // ══════════════════════════════════════════ // CODE READING GUIDE // ══════════════════════════════════════════ let activePattern = null; function renderPatterns() { const grid = document.getElementById('patterns-grid'); grid.innerHTML = patterns.map(p => `
${p.icon} ${p.title}

${p.desc}

`).join(''); grid.querySelectorAll('[data-pat]').forEach(card => { card.addEventListener('click', () => { activePattern = activePattern === card.dataset.pat ? null : card.dataset.pat; renderPatterns(); renderPatternDetail(); }); }); } function renderPatternDetail() { const el = document.getElementById('pattern-detail'); if (!activePattern) { el.style.display = 'none'; return; } const p = patterns.find(x => x.id === activePattern); el.style.display = ''; el.innerHTML = `
${p.icon}

${p.title}

${p.why}

${p.example.split('\n').map((line,i) => `
${i+1}${escHtml(line)}
`).join('')}
`; } // ══════════════════════════════════════════ // QUIZ // ══════════════════════════════════════════ let quizState = { current: 0, answered: [], score: 0 }; function renderQuiz() { const el = document.getElementById('quiz-container'); if (quizState.current >= quiz.length) { el.innerHTML = `
${quizState.score} / ${quiz.length}

${quizState.score === quiz.length ? 'Perfect score! You can read Bolt-generated code with confidence.' : 'Review the file tree and patterns above, then try again.'}

`; return; } const q = quiz[quizState.current]; el.innerHTML = `
Question ${quizState.current + 1} of ${quiz.length}

${q.q}

${q.opts.map((opt, i) => `
${opt}
`).join('')}
`; el.querySelectorAll('[data-idx]').forEach(opt => { opt.addEventListener('click', () => { const idx = parseInt(opt.dataset.idx); const correct = idx === q.correct; if (correct) quizState.score++; opt.classList.add(correct ? 'correct' : 'incorrect'); if (!correct) el.querySelectorAll('[data-idx]')[q.correct].classList.add('correct'); setTimeout(() => { quizState.current++; renderQuiz(); }, 1200); }, { once: true }); }); } // ══════════════════════════════════════════ // INIT // ══════════════════════════════════════════ renderTree(); renderPatterns(); renderQuiz(); updateTreeProgress(); const nav = document.getElementById('main-nav'); window.addEventListener('scroll', () => { nav.classList.toggle('nav-scrolled', window.scrollY > 30); }); document.getElementById('mobile-toggle').addEventListener('click', () => { document.getElementById('mobile-menu').classList.toggle('hidden'); });