Project Setup and TypeScript Configuration
All six previous modules built toward this. You have the complete TypeScript toolkit. Module 07 assembles it into a working app — starting from an empty folder.
What you are building
Section titled “What you are building”AceIt is a browser-based trivia quiz that runs entirely in the browser:
- Fetch live questions from the Open Trivia DB API — thousands of questions, dozens of categories
- Choose difficulty (Easy, Medium, Hard, or Any) and question count before each round
- Answer one question at a time — correct answers turn green, wrong answers turn red
- See your final score and compare it to your personal best
- Persist high scores to
localStorageso they survive page reloads
No server. No framework. Five TypeScript source files, one stylesheet, and one HTML file.
Create the project folder
Section titled “Create the project folder”aceit/ index.html favicon.svg style.css tsconfig.json package.json types.ts api.ts quiz.ts ui.ts main.ts dist/ ← compiled output (gitignored)If you created the aceit/ folder in Module 01 and have been building files through exercises, you already have partial versions of some of these. This module replaces each with its final, complete form — treat what you have as a working draft.
The favicon
Section titled “The favicon”Create favicon.svg — a simple SVG icon that appears in the browser tab:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"> <rect width="32" height="32" rx="6" fill="#2d3a8c"/> <text x="16" y="23" font-family="system-ui, sans-serif" font-size="18" font-weight="700" fill="white" text-anchor="middle">A</text></svg>The index.html links it with <link rel="icon" type="image/svg+xml" href="favicon.svg" />.
Install TypeScript
Section titled “Install TypeScript”npm init -ynpm install --save-dev typescriptAdd build scripts to package.json:
{ "scripts": { "build": "tsc", "watch": "tsc --watch", "serve": "npx serve ." }, "devDependencies": { "typescript": "^6.0.3" }}tsconfig.json
Section titled “tsconfig.json”{ "compilerOptions": { "target": "ES2020", "module": "ES2020", "moduleResolution": "bundler", "outDir": "./dist", "strict": true, "lib": ["ES2020", "DOM"], "noEmitOnError": true }, "include": ["./*.ts"], "exclude": ["dist"]}Every option here was covered in Module 01. strict: true enables all type checks. lib: ["ES2020", "DOM"] makes fetch, document, and localStorage available to the type checker. noEmitOnError keeps dist/ clean.
The HTML shell
Section titled “The HTML shell”Write index.html now — this is the complete structure. You will not change it during the build:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>AceIt</title> <link rel="icon" type="image/svg+xml" href="favicon.svg" /> <link rel="stylesheet" href="style.css" /></head><body> <header> <h1>AceIt</h1> </header>
<main> <section id="start-screen" class="screen card"> <h2>Ready to test your knowledge?</h2> <div class="field"> <label for="difficulty">Difficulty</label> <select id="difficulty"> <option value="any">Any</option> <option value="easy">Easy</option> <option value="medium">Medium</option> <option value="hard">Hard</option> </select> </div> <div class="field"> <label for="amount">Questions</label> <select id="amount"> <option value="5">5</option> <option value="10" selected>10</option> <option value="15">15</option> <option value="20">20</option> </select> </div> <button id="start-btn" class="btn-primary">Start Quiz</button> <p id="start-high-score" class="high-score-display" hidden></p> </section>
<section id="loading-screen" class="screen card" hidden> <p class="loading">Fetching questions…</p> </section>
<section id="question-screen" class="screen card" hidden> <div class="question-header"> <span id="progress" class="progress-text"></span> <span id="category" class="badge"></span> </div> <p id="question-text" class="question-text"></p> <div id="answers" class="answers-grid"></div> <button id="next-btn" class="btn-primary" hidden>Next</button> </section>
<section id="result-screen" class="screen card" hidden> <h2>Quiz Complete!</h2> <p id="final-score" class="final-score"></p> <span id="new-high-badge" class="badge badge--highlight" hidden>New High Score!</span> <p id="high-score-result" class="high-score-display" hidden></p> <button id="play-again-btn" class="btn-primary">Play Again</button> </section> </main>
<script type="module" src="dist/main.js"></script></body></html>The four <section> elements are the four screens. Each has class="screen" and is shown or hidden by ui.ts. The entry point is dist/main.js — the compiled output of main.ts.
Stub the TypeScript files
Section titled “Stub the TypeScript files”Create each .ts file with a minimal stub export so the compiler resolves all imports:
// types.ts — placeholderexport type Difficulty = 'easy' | 'medium' | 'hard';
// api.ts — placeholderexport async function fetchQuestions() { return []; }
// quiz.ts — placeholderexport class QuizEngine { constructor(public questions: never[]) {} }
// ui.ts — placeholderexport function showScreen(_id: string): void {}
// main.ts — entry point, no exports neededconsole.log('AceIt loading…');Confirm the build
Section titled “Confirm the build”npm run buildYou should see five .js files appear in dist/. No errors. Then start the dev server:
npm run serveOpen the URL in Chrome. Open DevTools → Console — you should see AceIt loading…. Open DevTools → Network — confirm each .js file loads as a module.
.gitignore
Section titled “.gitignore”dist/node_modules/package-lock.jsonExercise
Section titled “Exercise”- Create the
aceit/folder with all files listed above. - Install TypeScript and add the build scripts.
- Write
tsconfig.jsonandindex.htmlexactly as shown. - Create
favicon.svgwith the SVG above. - Add stub exports to each
.tsfile. - Run
npm run build— confirm no errors and five.jsfiles indist/. - Run
npm run serve— confirmAceIt loading…appears in the console and the “A” favicon appears in the browser tab.
- Scaffold first — confirm the build and module system work before writing app logic.
tsconfig.jsonis identical to what you configured in Module 01 — every option has a reason.- The HTML shell is complete and will not change during the build.
- Stub exports prevent module-not-found errors while files are empty.
type="module"on the script tag enables ES modules and loadsdist/main.jsas the entry point.