Week 1 — HTML, CSS & React UI foundations
Learn HTML document structure and CSS layout (box model, positioning, Flexbox/Grid), then build React foundations — then ship a Tic-Tac-Toe mini-project.
- 1. HTML document structureOpen
Document outline, semantic landmarks, headings, lists, links, and basic form controls so you can read markup before JSX.
- 2. CSS box model & normal flowOpen
Content, padding, border, margin, box-sizing, block vs inline vs inline-block, and margin collapse in normal flow.
- 3. CSS positioning & stackingOpen
Position modes, containing blocks, offsets, stacking, and when absolute is the wrong tool for page layout.
- 4. Flexbox & Grid alignmentOpen
Flex direction, wrapping, justify-content, align-items, gap; Grid tracks and simple alignment; choosing flex vs grid.
- 5. What is React?Open
Declarative UI, component trees, and one-way data flow.
- 6. Your first componentOpen
Function components, component composition, and capitalized component names.
- 7. Importing and exporting componentsOpen
Named exports, default exports, and module boundaries.
- 8. Writing JSXOpen
Single roots, fragments, attributes, and self-closing elements.
- 9. JavaScript in JSX with curly bracesOpen
Expressions vs statements, dynamic attributes, and nullish fallbacks.
- 10. Passing props to a componentOpen
One-way data flow, prop naming, and children.
- 11. Conditional renderingOpen
Ternary, &&, early return, and empty states.
- 12. Rendering listsOpen
map, key placement, and why array indexes can break dynamic lists.
- 13. Keeping components pureOpen
Pure rendering, local mutation, and predictable re-renders.
- 14. Responding to eventsOpen
Learn the common React DOM handlers with examples, then the mistakes that cause the most bugs.
- 15. SPA routing: React Router & route guardsOpen
Learn how React apps route with react-router-dom (BrowserRouter, Routes, Link, navigate, params), how public vs private routes work, then how this monorepo uses Next App Router instead for the product shell.
- 16. State: a component’s memoryOpen
useState, setters, and local state ownership.
- 17. Render and commitOpen
Triggering updates, rendering, reconciliation, and commit work.
- 18. State as a snapshotOpen
Snapshot semantics, closures, and scheduled renders.
- 19. Queueing state updatesOpen
Batching, functional updaters, and replace versus update operations.
- 20. Updating objects in stateOpen
Immutability, spread syntax, and nested updates.
- 21. Updating arrays in stateOpen
Adding, removing, replacing, and sorting immutable arrays.
End-of-week mini-project · practice only
Tic-Tac-Toe
Build a playable Tic-Tac-Toe game with React components, immutable state, time-travel history, and a small React Router shell.
Definition
A single-page React game that applies every Week 1 foundation — semantic HTML/CSS layout, components and props, conditional rendering, keyed lists, purity, events, immutable state, and SPA routing — with no Redux, Query, or Next.
In simpler words
Two players take turns on a 3×3 board. You own all the UI and game state in React, add a history you can jump back to, and wrap it in a couple of routes. No Nest yet.
Concepts covered this week
- HTML document structure
- A semantic shell: a <main> game region, a status <output>, and a <nav> for the menu/history routes.
- CSS box model & normal flow
- Padding/border/margin size the squares and gaps so the 3×3 grid stays square.
- CSS positioning & stacking
- A win/draw banner overlays the board with absolute positioning and z-index.
- Flexbox & Grid alignment
- CSS Grid lays out the board; Flexbox centers the status bar and controls.
- What is React & your first component
- Start from one <Game> component, then split into Square/Board/StatusBar.
- Importing & exporting components
- Each component lives in its own file and is imported where it is used.
- Writing JSX & JavaScript in JSX
- Render nine squares and interpolate the status string with curly braces.
- Passing props
- Board hands each Square its value and an onClick handler.
- Conditional rendering
- Show “X’s turn”, “O wins”, or “Draw” from derived game state.
- Rendering lists with keys
- The move-history list maps moves to buttons with stable keys.
- Keeping components pure
- Square renders only from props — no mutation or side effects during render.
- Responding to events
- Handlers are passed down and run on click, never called during render.
- SPA routing: React Router & guards
- Routes for a menu, /game, and /game/:id history; a guard blocks history when no game was played.
- State: memory, render/commit, snapshot & queueing
- useState holds the squares and current player; each click re-renders from a fresh snapshot.
- Updating objects & arrays in state
- Copy the board array (slice) and push to history without mutating the previous turn.
Deliverables
- Square / Board / Game / StatusBar components in their own files with props down and events up
- useState for the squares array and current player; winner/draw/next-player derived from state (no DOM reads)
- An immutable move history with “jump to move” time-travel rendered from a keyed list
- A small React Router shell: menu → /game → /game/:id history, with a guard on the history route
- A responsive board built with CSS Grid/Flexbox and an overlay result banner
Build guide
- Build the static boardLay out nine Squares with CSS Grid and semantic HTML before adding any state.
- Lift game stateMove the squares array and current player into <Game> with useState; pass value + onClick down to each Square.
- Derive the statusCompute winner/draw/next-player from the board with a pure helper and show it via conditional rendering.
- Update immutablyOn click, copy the array with slice, set the cell, and ignore clicks on filled cells or after a win.
- Add move historyStore each board snapshot in a history array and render a keyed “jump to move” list that time-travels state.
- Wrap it in routesAdd React Router: a menu route, /game, and /game/:id history; guard the history route so it redirects when no game exists.
- Polish the UIStyle the grid, add an overlay banner for win/draw, and make the empty board look different from a finished game.
Acceptance checklist
- [ ] Board renders 9 squares from a state array (not nine separate states)
- [ ] Clicking a square updates immutable state (no board[i] = 'X' mutation)
- [ ] Winner / draw / next player shown with conditional rendering
- [ ] Handlers are passed, not called during render
- [ ] Move history uses stable keys and can time-travel
- [ ] React Router shell works; the history route is guarded
- [ ] Empty board ≠ finished game (distinct UI)Stretch goals
- Add an unbeatable AI opponent (minimax) as the O player.
- Persist the current game to localStorage and restore it on reload.
- Add a scoreboard route that tallies wins across games.
Tips
- Follow react.dev’s Tic-Tac-Toe tutorial first, then rebuild from memory without copy-paste.
- HTML/CSS foundations still apply: semantic structure, box model, and Grid for the board.
- Keep it local-only — no Nest or Redux yet; state lives in React.
- Add the Router shell last so the game works before navigation does.