Files
cabrits-math/plan.md
2026-07-05 11:12:45 -04:00

34 KiB
Raw Permalink Blame History

Implementation Plan: Term 1 Unit Plan (unit_plan_term_1.pdf) → Cabrits App

1. Context

Cabrits is an interactive mathematics teaching tool for Portsmouth Secondary School Form 1 (age 1112), used live in class by the teacher. Pages contain interactive tools only — no lesson text (the teacher explains verbally). Stack: Next.js 16 (App Router, output: "standalone"), React 19, TypeScript, Tailwind CSS v4 (@theme inline), KaTeX via components/math/math-display.tsx, custom SVG visualizations (no chart libraries), no database/auth — everything is client-side and generated on the fly.

The app currently implements the Term 2 curriculum as Units 14 (Fractions, Decimals, Decimal Operations, Ratio & Proportion) and has already started on Term 1 material as Units 56 (Integers, Number System).

unit_plan_term_1.pdf (8 pages, AY 20252026, Form 1, "NUMBER" unit) specifies these topics. The website is a resource organized by topic — the source document's scheduling is irrelevant and must never appear in the app (no week numbers, no dates, nothing schedule-related in any UI text, slug, title, or description):

Topic Objectives Content
Integers: define, order, compare Define integers & negative numbers; represent on a number line; order integers (ascending/descending); compare integers with < / > Number line, real-world contexts (temperature/thermometer, banking/overdraft, sports goal differences, time). Evaluation: order sets like -8, -10, -4, -3, -6, 5; fill in < or > for pairs like -5 __ 5, 4 __ -16, -6 __ -11
Integers: add & subtract Add & subtract integers, with and without number lines Number-line movement rules; sign rules ("two like signs become +, two unlike signs become "); borrow/owe strategy. Evaluation: 5 + (-3), 8 - (-7), -2 + 9, -9 - (-1), etc.
Integers: multiply & divide Multiply & divide integers Sign rules ( × = + etc.); "Eat! / Do not eat!" story; thermometer word problems (e.g. "In London, temperature is 3 °C, next day it rose by 7 °C…"). Evaluation: 3 × -5, -2 × -9, -12 / 4, -24 / -8, (-2) × (-3) × (-4)
Coordinates Plot coordinates; state coordinates of points Cartesian plane: x-axis (horizontal), y-axis (vertical), origin (0, 0). Evaluation: plot A(-4,-8), B(-3,-9), C(-2,-8), D(-2,0), E(-5,0), F(-6,4), G(-2,5), H(2,4), I(5,0), join alphabetically then I→A to reveal a shape
Identity, inverse & zero facts Basic operations; identity for addition (0) & multiplication (1); inverse under addition (additive inverse, e.g. inverse of 3 is 3 because 3 + (-3) = 0); inverse under multiplication (reciprocal, e.g. inverse of 6 is 1/6 because 6 × 1/6 = 1; inverse of 5 is 1/5); multiplication by zero → 0; division by zero → undefined "Math Wheel" activity. Evaluation: classwork + homework on identities/inverses
Number laws & exponents Commutative, associative, distributive laws; powers/exponents Addition & multiplication are commutative/associative, subtraction & division are not; distributive law (number outside bracket multiplies every number inside). Exponents: 2⁴ = 2×2×2×2 = 16; a¹ = a; a⁰ = 1; product rule 2⁴ × 2³ = 2⁷; quotient rule 6⁵ / 6³ = 6². Evaluation quiz: , , 5⁶ / 5⁴, 7⁰, 4⁴ ×
Number systems (base 10 & base 2) Understand & use the decimal system (base 10); understand & use the binary system (base 2) Base-10 place value chart with powers of 10, expanded form (983275 = 9×10⁵ + 8×10⁴ + 3×10³ + 2×10² + 7×10¹ + 5×10⁰); binary place value with powers of 2; convert binary→denary (111001₂ = 32+16+8+0+0+1 = 57). Evaluation: convert 1011₂, 111₂, 1101₂ to denary

2. Gap Analysis

Already implemented (do NOT rebuild — leave untouched):

PDF topic Existing route Existing explorer
Add/subtract integers /lessons/unit-5-integers/add-subtract components/explorers/integer-add-subtract-explorer.tsx (number-line + sign-rules modes, step-through, inline QuickPractice)
Multiply/divide integers /lessons/unit-5-integers/multiply-divide components/explorers/integer-multiply-divide-explorer.tsx
Binary ↔ denary /lessons/unit-6-number-system/binary components/explorers/binary-converter-explorer.tsx, denary-to-binary-explorer.tsx
(bonus, not in PDF) quaternary /lessons/unit-6-number-system/quaternary quaternary-to-denary-explorer.tsx, denary-to-quaternary-explorer.tsx

Missing (this plan builds these):

  1. Order & compare integers (new topic in existing Unit 5)
  2. Cartesian plane: plot points & read coordinates (new Unit 7)
  3. Identity, inverse, zero facts (new Unit 8, topic 1)
  4. Commutative/associative/distributive laws (Unit 8, topic 2)
  5. Powers & exponents with index laws (Unit 8, topic 3)
  6. Base-10 place value / expanded form (new topic in existing Unit 6)

3. Target Curriculum Structure After Implementation

  • Unit 5 Integers (existing, violet #7c3aed): order-compare (NEW, insert as first topic), add-subtract, multiply-divide
  • Unit 6 Number System (existing, indigo #4f46e5): place-value (NEW, insert as first topic), binary, quaternary
  • Unit 7 Coordinates (NEW, green #16a34a): plot-points, read-coordinates
  • Unit 8 Number Properties (NEW, rose #e11d48): identity-inverse, number-laws, exponents

New routes (7 topic pages + 2 unit overview pages):

/lessons/unit-5-integers/order-compare
/lessons/unit-6-number-system/place-value
/lessons/unit-7-coordinates                    (overview)
/lessons/unit-7-coordinates/plot-points
/lessons/unit-7-coordinates/read-coordinates
/lessons/unit-8-number-properties              (overview)
/lessons/unit-8-number-properties/identity-inverse
/lessons/unit-8-number-properties/number-laws
/lessons/unit-8-number-properties/exponents

No existing route changes. Inserting topics at the front of a unit's topics array only changes the displayed numbering on overview pages (which is index-based), not URLs.

4. Codebase Conventions (READ THESE FILES FIRST as templates)

  1. lib/curriculum.ts — single source of truth. Unit interface has number: 1|2|3|4|5|6 and color: "unit-1"|...|"unit-6" unions that must be extended to include 7 and 8. The sidebar (components/layout/sidebar.tsx), mobile nav (components/layout/mobile-nav.tsx), lessons index (app/lessons/page.tsx), and landing page (app/page.tsx) all iterate curriculum automatically — but each keeps its own hardcoded color-class map keyed by "unit-N" that must gain unit-7/unit-8 entries (Tailwind cannot generate class names dynamically).
  2. Topic page pattern — see app/lessons/unit-5-integers/add-subtract/page.tsx (the most recent convention): a "use client" page containing only <Breadcrumbs>, an <h1>, and one <XyzExplorer /> component. Breadcrumb items: Lessons → Unit N: Title → Short topic label.
  3. Unit overview page pattern — see app/lessons/unit-5-integers/page.tsx: server component, reads curriculum[unitIndex], renders a <Badge variant="unit-N"> header and a sm:grid-cols-2 grid of <Card accent="unit-N" hover> links with numbered chips (bg-unit-N-light text-unit-N-dark).
  4. Explorer pattern — see components/explorers/integer-add-subtract-explorer.tsx (594 lines; the canonical template). Structure:
    • "use client", local Step interface { label: string; math: string; ...visualization payload }
    • A pure buildXyzSteps(...) function that returns Step[] narrating the worked solution
    • Mode-toggle pill buttons (rounded-full border-2 ... with unit color classes)
    • An input <Card> with validated number inputs and a "Go →" button; friendly error messages via a local error state
    • A display <Card> showing step.label, <MathDisplay math={step.math} /> (KaTeX string), and the custom SVG/div visualization that animates with the current step
    • <StepControls> from components/explorers/step-controls.tsx wired via currentStep / totalSteps / isPlaying / onStepForward / onStepBack / onTogglePlay / onReset / canStepForward / canStepBack (note: it expects currentStep + 1 as the 1-based display value)
    • A result <Card> shown when steps complete
    • An inline QuickPractice component (local to the file): random problem generator, number input, Check/Next buttons, running score.correct/score.total chip, Enter-key handling, correct/incorrect feedback using border-correct bg-correct-light / border-incorrect bg-incorrect-light classes
  5. Color systemapp/globals.css defines per-unit CSS vars in :root (--unit-N, --unit-N-light, --unit-N-dark) and mirrors them in the @theme inline block as --color-unit-N* so Tailwind classes like bg-unit-7, text-unit-7-dark, bg-unit-7-light, border-unit-7/40 work. Also available: --correct, --incorrect (+ -light variants), --foreground, --muted, --surface, --border.
  6. Practice hubapp/practice/page.tsx holds TOPIC_GENERATORS (generator functions from lib/problems/generators/*), a unitColors map (currently only units 14), and a filter-pill array (["unit-1","unit-2","unit-3","unit-4"] as const). components/practice/practice-section.tsx renders input UI switched on problem.answer.kind — it already supports "integer" (plain number input), so all new generators should return { kind: "integer", value } answers. MathProblem (in lib/problems/types.ts) requires id, prompt (may contain KaTeX-able text), answer, hints: string[], steps: SolutionStep[] ({ explanation, math? }). Difficulty = 1 | 2 | 3.
  7. Landing page artcomponents/home/topic-art.tsx exports art: Record<string, ReactNode> keyed by "unitSlug/topicSlug", each a small white-on-gradient SVG glyph inside the shared 100×75 viewBox Frame. Every new topic needs an entry or its tile renders without artwork.

5. Implementation Phases

Work in this order; the app must compile after every phase (npx tsc --noEmit and npm run build).

Phase 1 — Shared infrastructure (types, colors, nav maps)

  1. lib/curriculum.ts

    • Extend Unit["number"] union to 1|2|3|4|5|6|7|8 and Unit["color"] union to include "unit-7" | "unit-8".
    • Extend getUnitColor's parameter type and colors record with 7: "unit-7", 8: "unit-8".
    • Insert into unit 5's topics (as the FIRST element):
      {
        slug: "order-compare",
        title: "Order and Compare Integers",
        shortTitle: "Order & Compare",
        description: "Place integers on a number line, order them, and compare with < and >",
      },
      
    • Insert into unit 6's topics (as the FIRST element):
      {
        slug: "place-value",
        title: "Denary Place Value (Base 10)",
        shortTitle: "Place Value",
        description: "Powers of 10 and writing numbers in expanded form",
      },
      
    • Append two new units after unit 6:
      {
        number: 7,
        slug: "unit-7-coordinates",
        title: "Coordinates",
        description: "Plot points and read coordinates on the Cartesian plane",
        color: "unit-7",
        topics: [
          { slug: "plot-points", title: "Plot Points on the Cartesian Plane", shortTitle: "Plot Points", description: "Use x and y coordinates to place points and reveal hidden shapes" },
          { slug: "read-coordinates", title: "State Coordinates of Points", shortTitle: "Read Coordinates", description: "Read off the (x, y) coordinates of points in all four quadrants" },
        ],
      },
      {
        number: 8,
        slug: "unit-8-number-properties",
        title: "Number Properties",
        description: "Identity and inverse, the laws of arithmetic, and powers of numbers",
        color: "unit-8",
        topics: [
          { slug: "identity-inverse", title: "Identity and Inverse", shortTitle: "Identity & Inverse", description: "Identity for addition and multiplication, inverses, and the zero facts" },
          { slug: "number-laws", title: "Commutative, Associative and Distributive Laws", shortTitle: "Number Laws", description: "Which operations can be swapped, regrouped, and expanded" },
          { slug: "exponents", title: "Powers and Exponents", shortTitle: "Exponents", description: "Base and power, expanding powers, and the index laws" },
        ],
      },
      
  2. app/globals.css — add beside the existing --unit-6 definitions in :root:

    --unit-7: #16a34a;
    --unit-7-light: #dcfce7;
    --unit-7-dark: #15803d;
    
    --unit-8: #e11d48;
    --unit-8-light: #ffe4e9;
    --unit-8-dark: #be123c;
    

    and in the @theme inline block (beside --color-unit-6-dark):

    --color-unit-7: var(--unit-7);
    --color-unit-7-light: var(--unit-7-light);
    --color-unit-7-dark: var(--unit-7-dark);
    --color-unit-8: var(--unit-8);
    --color-unit-8-light: var(--unit-8-light);
    --color-unit-8-dark: var(--unit-8-dark);
    
  3. components/ui/badge.tsx — extend BadgeVariant union with "unit-7" | "unit-8" and add to variantStyles:

    "unit-7": "border border-unit-7/20 bg-unit-7-light text-unit-7-dark",
    "unit-8": "border border-unit-8/20 bg-unit-8-light text-unit-8-dark",
    
  4. components/ui/card.tsx — extend the accent prop union and accentStyles with "unit-7": "border-l-4 border-l-unit-7" and the unit-8 equivalent.

  5. components/layout/sidebar.tsx — add unit-7 / unit-8 entries to unitColorMap, following the exact shape of the existing entries (active, dot, heading, hoverBg keys with the unit's color classes).

  6. components/layout/mobile-nav.tsx — same: extend both color maps (there is a text-color map at ~line 10 and a dot/bg map at ~line 19) with unit-7/unit-8 entries.

  7. app/page.tsx (landing) — add to unitStyles:

    "unit-7": {
      tile: "from-[#4ade80] to-[#15803d]",
      unitCard: "border-[#86efac] bg-[#f0fdf4]",
      chip: "bg-[#15803d]",
    },
    "unit-8": {
      tile: "from-[#fb7185] to-[#be123c]",
      unitCard: "border-[#fda4af] bg-[#fff1f2]",
      chip: "bg-[#be123c]",
    },
    

    The topic tiles cycle through the topicTiles gradient array by index, so no per-topic change is needed there.

  8. components/home/topic-art.tsx — add 7 entries to the art record (white SVG glyphs in the 100×75 viewBox, matching the visual weight of existing entries):

    • "unit-5-integers/order-compare": a horizontal number line (line + tick marks) with < glyph, e.g. ticks at intervals with two highlighted dots and a < between two numbers
    • "unit-6-number-system/place-value": three columns of stacked digits over small 10² 10¹ 10⁰ labels (use <text> with fontSize ~810)
    • "unit-7-coordinates/plot-points": a small grid (4 light <line>s each way), two axes drawn heavier, one bright plotted point with small crosshair lines to the axes
    • "unit-7-coordinates/read-coordinates": axes plus a point labelled (3, 2)
    • "unit-8-number-properties/identity-inverse": n + 0 = n style glyph, or two circles balancing on a seesaw with 0 at the pivot
    • "unit-8-number-properties/number-laws": a + b = b + a with a swap arrow (curved <path> with arrowhead)
    • "unit-8-number-properties/exponents": large 2 with superscript 4 and = 16

Checkpoint: npx tsc --noEmit passes; landing page, sidebar, and mobile nav show Units 78 with correct colors; the two new Unit 5/6 topics appear (links 404 until later phases — acceptable mid-work, but all phases must be done before merging).

Phase 2 — Unit 5: Order & Compare Integers

New file: components/explorers/integer-order-compare-explorer.tsx — model on integer-add-subtract-explorer.tsx. Unit color: unit-5 (violet). Three modes via pill toggle:

  1. "Number Line" mode (objective 12: define/represent):

    • Input: one integer from 15 to 15 (reuse the NumberLine rendering approach from the add-subtract explorer: absolute-positioned ticks over a percentage-scaled track, labels every 5 plus highlighted values).
    • Step sequence: (1) show the number line with zero highlighted, label "Zero separates negative numbers (left) from positive numbers (right)"; (2) mark the entered integer with a Start-style pill marker; (3) state its type: \text{-7 is a negative integer — it is 7 steps left of zero} (KaTeX via MathDisplay).
    • Below the line keep the existing convention: ← negative / positive → edge labels.
    • Add a context selector row of small buttons — Thermometer 🌡, Money 💰, Sea level 🌊 — that re-labels the step text (e.g. thermometer: "7 means 7 degrees below zero"; money: "7 means owing $7"; sea level: "7 means 7 m below sea level"). This delivers the PDF's real-world contexts (temperature, banking/overdraft). A vertical thermometer variant is optional polish, not required.
  2. "Order" mode (objective 3):

    • Input: a comma-separated list of 36 integers (validate: integers, within 20…20, at least 3). Direction toggle: Ascending / Descending.
    • Step sequence built by buildOrderSteps(values, direction): (1) show unordered values as chips; (2) place all values as dots on the number line simultaneously; (3) one step per pick — "The smallest is the furthest LEFT on the number line: 10" — moving each chip into the ordered row; (4) final ordered list, \text{Ascending: least} \to \text{greatest}.
    • The visualization: the shared number line with dots, plus a row of value chips that fill in as steps advance (conditionally render based on currentStep, same technique as the existing explorers' step-driven rendering).
  3. "Compare" mode (objective 4):

    • Input: two integers a, b. Steps: (1) plot both on the number line; (2) "Numbers to the RIGHT are always larger" with the right-hand one highlighted; (3) result 5 < 5 rendered with MathDisplay.

Inline QuickPractice (same Card layout/score-chip pattern as the template): alternate two question types randomly —

  • Compare: show a \; \square \; b with two big < / > buttons instead of a number input (immediate check on click). Seed pairs like the PDF's evaluation: (-5, 5), (4, -16), (-6, -11), plus randoms in 20…20.
  • Order: show 4 shuffled integers as clickable chips; student clicks them in ascending order; each click either locks the chip (correct next pick) or flashes incorrect. Score a point when all 4 are placed without a mistake.

New file: app/lessons/unit-5-integers/order-compare/page.tsx — copy the shape of add-subtract/page.tsx; breadcrumbs Lessons → Unit 5: Integers → Order & Compare; <h1>Order and Compare Integers</h1>; render the new explorer.

Phase 3 — Unit 7: Coordinates

New file: app/lessons/unit-7-coordinates/page.tsx — copy app/lessons/unit-5-integers/page.tsx, change curriculum[4]curriculum[6], unit-5unit-7 classes, badge variant unit-7, breadcrumb label Unit 7: Coordinates.

Shared visualization — build a reusable CartesianGrid component (either inside each explorer or as components/visualizations/cartesian-grid.tsx if components/visualizations/ exists — check; if the repo keeps visuals inline in explorers, put it in a shared file under components/explorers/ such as cartesian-grid.tsx). Spec:

  • SVG viewBox="0 0 440 440", responsive (className="h-auto w-full max-w-md"), grid from 10 to +10 both axes (21 lines each way; light stroke="var(--border)" gridlines, heavier axes through the origin in var(--foreground)), axis numeric labels every 2 (skip 0 clutter; label origin 0 once), arrowheads + x / y labels at the axis ends.
  • Props: points: { x: number; y: number; label?: string; color?: string }[], segments: { from: Point; to: Point }[] (polylines drawn so far), optional highlight point with guide lines: a dashed line from the point straight down/up to the x-axis and across to the y-axis (this is the key teaching visual for both plotting and reading), optional onGridClick?: (x, y) => void (attach a click handler on the SVG, invert the coordinate transform, snap to nearest integer intersection).
  • Coordinate transform: sx = 20 + (x + 10) * 20, sy = 20 + (10 - y) * 20.

New file: components/explorers/plot-points-explorer.tsx — unit color unit-7. Two modes:

  1. "Plot a Point": inputs for x and y (10…10). buildPlotSteps(x, y): (1) "Start at the origin (0, 0), where the axes cross"; (2) "Move ALONG the x-axis: 4 to the right" (grid shows a horizontal arrow from origin to (x, 0)); (3) "Then move UP/DOWN parallel to the y-axis: 3 up" (vertical arrow (x,0)→(x,y), dashed guides); (4) "Mark the point (4, 3) — x always comes first!". Each step's payload tells CartesianGrid what arrows/guides/points to draw.
  2. "Shape Reveal" (the PDF's evaluation activity): a select of 34 preset shape datasets, the first being exactly the PDF's: A(-4,-8), B(-3,-9), C(-2,-8), D(-2,0), E(-5,0), F(-6,4), G(-2,5), H(2,4), I(5,0) joined A→B→…→I→A. Add 23 simpler presets (e.g. a square, a star, a house). Step-through: each step plots the next labelled point and draws the segment from the previous one; final step closes the shape (I back to A). StepControls drives it, so the teacher can play it like an animation.

Inline QuickPractice: "Click where (3, 5) is!" — random target coordinates, student clicks the grid (via onGridClick), snap-checked for exact match; correct → green pulse on the point, score increments; incorrect → show the clicked point in red and the target in green with guide lines.

New file: components/explorers/read-coordinates-explorer.tsx — unit color unit-7.

  • Explore mode: a random (or stepped) point is shown; buildReadSteps(x, y): (1) "Drop a line straight DOWN/UP to the x-axis — it lands on 4" (dashed vertical guide); (2) "Go straight ACROSS to the y-axis — it lands on 3" (dashed horizontal guide); (3) "The coordinates are (4, 3): x first, then y". Include a quadrant call-out step ("Both negative → bottom-left quadrant") since the PDF's shape spans all four quadrants.
  • Inline QuickPractice: show a random point on the grid; two number inputs ( __ , __ ); check both; classic error worth catching in feedback: if the student enters (y, x) swapped, say "You swapped them — x comes first!".

New pages: app/lessons/unit-7-coordinates/plot-points/page.tsx and .../read-coordinates/page.tsx following the standard topic-page shape (breadcrumb unit label Unit 7: Coordinates).

Phase 4 — Unit 8: Number Properties

New file: app/lessons/unit-8-number-properties/page.tsx — copy the unit-overview pattern with curriculum[7], unit-8 classes.

New file: components/explorers/identity-inverse-explorer.tsx — unit color unit-8. Mode pills: Identity · Inverse · Zero Facts.

  • Identity: input a number n; toggle Add / Multiply. Steps: n + 0 = n — "Adding 0 leaves the number unchanged: 0 is the identity for addition"; n × 1 = n — "Multiplying by 1 leaves it unchanged: 1 is the identity for multiplication". Visual: a "machine" card — number goes in, +0/×1 badge in the middle, same number comes out (simple flex layout with an animated arrow; framer-motion optional, CSS transitions fine).
  • Inverse: input n (non-zero for multiplication). Steps for addition: "The additive inverse is the number that gets you back to the identity 0" → n + (n) = 0 (e.g. inverse of 3 is 3; inverse of 5 is 5 — flip the sign). Steps for multiplication: "The multiplicative inverse (reciprocal) gets you back to 1" → n × \frac{1}{n} = 1, with the PDF's note that the inverse of 5 is \frac{1}{5} (sign stays in front). Render fractions with KaTeX.
  • Zero Facts: input n. Steps: n × 0 = 0 — "Anything times zero is zero"; n ÷ 0 = \text{undefined} — "You cannot share among zero groups — division by zero is UNDEFINED" (style the word in text-incorrect). Also show 0 ÷ n = 0 for contrast.
  • Inline QuickPractice: random prompts with integer answers — "What is the additive inverse of 8?" (answer 8), "What is 17 × 0?", "What number is the identity for multiplication?"; multiplicative-inverse questions phrased to keep integer answers ("The inverse of 6 under multiplication is 1/□ — what goes in the box?").

New file: components/explorers/number-laws-explorer.tsx — unit color unit-8. Mode pills: Commutative · Associative · Distributive.

  • Commutative: inputs a, b; operation selector (+ × ÷). Steps compute both a ∘ b and b ∘ a side by side and conclude: for + and ×, "Same answer — addition/multiplication IS commutative ✓"; for and ÷, show the two different results and "Different answers — subtraction/division is NOT commutative ✗" (this contrast is explicitly in the PDF's evaluation questions). Visual: two mirrored expression cards with a swap arrow between them; results colored correct/incorrect by match.
  • Associative: inputs a, b, c; operation + or × (plus a "try " demo option that shows the counterexample). Steps: evaluate (a ∘ b) ∘ c bracket-first, then a ∘ (b ∘ c), compare.
  • Distributive: inputs a, b, c. Steps for a × (b + c): (1) show the expression; (2) "The number outside multiplies EVERY number inside" → a×b + a×c with curved arrows from a to each term (SVG or absolutely-positioned spans); (3) evaluate both ways to the same answer.
  • Inline QuickPractice: e.g. "Fill in the blank: 4 × (5 + 2) = 4×5 + 4×□" (integer answer), "Does 9 4 = 4 9? Enter 9 4:" style computations.

New file: components/explorers/exponents-explorer.tsx — unit color unit-8. Mode pills: Expand · Index Laws.

  • Expand: inputs base (212) and power (06), guard result ≤ ~1,000,000. buildExpandSteps(base, exp): (1) 2^4 — "the base is 2, the power (index) is 4: multiply the base by itself 4 times"; (2) 2 × 2 × 2 × 2 shown building up factor by factor across steps with running product; (3) = 16. Special-case steps: power 1 → 3^1 = 3 "any number to the power 1 is itself"; power 0 → 6^0 = 1 "any number to the power 0 is 1".
  • Index Laws: choose Multiply or Divide; inputs base b, powers m, n. Steps for multiply: (1) b^m × b^n; (2) expand both into factor strings side by side; (3) "count the factors: m + n of them" → b^{m+n}; (4) evaluated value. Divide analogously with cancellation visual (strike-through matching factors — render the expansion as individual chips and add line-through opacity-40 to cancelled ones as steps advance) → b^{mn}.
  • Inline QuickPractice: seeded directly from the PDF quiz — , , 5⁶ / 5⁴ (ask for the answer as a power's value, keep numbers small), 7⁰, plus randoms like a^m × a^n = a^? (answer: the exponent, an integer).

New pages: app/lessons/unit-8-number-properties/{identity-inverse,number-laws,exponents}/page.tsx following the standard topic-page shape.

Phase 5 — Unit 6: Denary Place Value

New file: components/explorers/place-value-explorer.tsx — unit color unit-6 (indigo), consistent with the binary explorers it sits beside (read binary-converter-explorer.tsx first and mirror its table/chart styling so the base-10 and base-2 pages feel like siblings).

  • Input: a whole number 1999,999.
  • buildPlaceValueSteps(n): (1) show the number and "each digit has a place value that is a power of 10"; (2) reveal the place-value chart header row: 10^5 = 100000 · 10^4 = 10000 · … · 10^0 = 1 (only as many columns as the number has digits); (3) one step per digit left→right: highlight the column, show 9 × 10^5 = 900000; (4) assemble expanded form 983275 = 9×10^5 + 8×10^4 + 3×10^3 + 2×10^2 + 7×10^1 + 5×10^0 in KaTeX; (5) sum check back to the original number.
  • Visual: an HTML table styled like the PDF's chart (Place Value / Digit / Product rows), current column highlighted with bg-unit-6-light, inside an overflow-x-auto wrapper for mobile.
  • Inline QuickPractice: "In 47,382 — what is the VALUE of the digit 7?" (answer 7000); "Which power of 10 is the hundreds column? Enter the exponent" (answer 2).

New page: app/lessons/unit-6-number-system/place-value/page.tsx (breadcrumb unit label Unit 6: Number System).

Phase 6 — Practice hub generators

New file: lib/problems/generators/integer-problems.ts exporting (all return MathProblem with answer: { kind: "integer", value }, difficulty-scaled ranges, unique id via the same scheme other generators use — check fraction-problems.ts for the id/random helpers and reuse its style):

  • generateIntegerAddSubtract(difficulty) — d1: single op, values 10…10; d2: values 20…20 including double negatives like 8 (7); d3: three-term chains. Steps narrate the sign rules exactly as the explorer does.
  • generateIntegerMultiplyDivide(difficulty) — d1: single product/quotient with small factors (division always exact); d2: larger values; d3: triple products like (2) × (3) × (4) (the PDF homework question). Steps narrate sign-counting ("two negatives → positive").
  • generateTemperatureProblem(difficulty) — word problems modeled on the PDF: "In London, the temperature is 3 °C on Monday. The next day it rose by 7 °C. What was the temperature on Tuesday?" Vary city, start temp, rise/fall.

New file: lib/problems/generators/number-properties-problems.ts exporting:

  • generateIdentityInverse(difficulty) — additive-inverse and zero-fact questions with integer answers.
  • generateExponentEvaluate(difficulty) — d1: squares/cubes of 29 and n^0/n^1; d2: PDF-quiz style (6^3, 2^3 2^1); d3: index-law simplifications where the answer is the resulting exponent ("4^4 × 4^3 = 4^x — find x").
  • generateDistributive(difficulty) — evaluate a × (b + c) numerically.

New file: lib/problems/generators/number-system-problems.ts exporting:

  • generateBinaryToDenary(difficulty) — d1: 34 bits; d2: 56 bits (the PDF's 1011₂, 111₂, 1101₂ range); d3: 78 bits. Steps show the power-of-2 column products and the sum.
  • generateDigitValue(difficulty) — "value of digit d in N" questions for base 10.

Modify app/practice/page.tsx:

  • Import the new generators and append TOPIC_GENERATORS entries for: unit-5 order-compare(skip — comparison answers don't fit integer input; leave its practice inline in the explorer), unit-5 add-subtract (generateIntegerAddSubtract), unit-5 multiply-divide (generateIntegerMultiplyDivide), unit-5 temperature word problems (attach to multiply-divide or add-subtract as a second entry with label "Temperature Problems"), unit-6 place-value (generateDigitValue), unit-6 binary (generateBinaryToDenary), unit-8 all three topics.
  • Extend the TopicGenerator["unitColor"] union to "unit-1" | ... | "unit-8", add unit-5unit-8 entries to the unitColors map (labels: "Integers", "Number System", "Coordinates", "Number Properties" — include unit-7 only if a coordinates generator is added; otherwise omit unit-7 from the filter row), and extend the filter-pill as const array accordingly.

Coordinates practice stays inside the explorers (click-the-grid needs custom input UI that PracticeSection doesn't support — do NOT extend MathAnswer for this; it's out of scope).

Phase 7 — Verification

  1. npx tsc --noEmit — zero errors.
  2. npm run lint — zero errors.
  3. npm run build — succeeds (catches server/client component violations; every page that renders an explorer must be "use client" or import a "use client" explorer, matching the existing pattern).
  4. npm run dev and manually visit every new route (list in §3). For each: breadcrumbs correct, unit color correct, explorer loads, "Go" produces steps, StepControls play/step/reset work, QuickPractice checks answers correctly (test at least one correct and one incorrect answer each).
  5. Specifically verify: the PDF shape-reveal dataset plots correctly and closes I→A; n ÷ 0 shows "undefined" and never computes; 7⁰ = 1; negative coordinates plot in the correct quadrants; ordering -8, -10, -4, -3, -6, 5 ascending yields -10, -8, -6, -4, -3, 5.
  6. /practice: new topics appear, unit filter pills for the new units work, answers validate.
  7. Landing page: Units 78 render with art on every topic tile (no blank tiles — confirms topic-art.tsx keys match unitSlug/topicSlug exactly).
  8. Check mobile layout (narrow viewport): the Cartesian grid and place-value table must scroll or scale, not overflow the page.

6. Acceptance Criteria (map back to the PDF)

  • Order & compare integers: explorer covers number-line placement, real-world contexts, ascending/descending ordering, and </> comparison, including the PDF's evaluation numbers
  • Integer add/subtract and multiply/divide: already live; unchanged and still passing build
  • Coordinates: plot-points + read-coordinates explorers, including the PDF's AI shape activity as a preset
  • Identity & inverse: explorer covers identity 0/1, additive & multiplicative inverse (with the 1/5 sign note), ×0 = 0, ÷0 undefined
  • Number laws: explorer demonstrates all three laws AND the non-commutativity/non-associativity of and ÷
  • Exponents: explorer covers expansion, , a⁰, product & quotient index laws; PDF quiz questions appear in QuickPractice
  • Denary place value: explorer reproduces the PDF's 983275 expanded-form walkthrough for any input
  • Binary system: already live (binary page)
  • No week numbers, dates, or scheduling language anywhere in app UI text, slugs, titles, or descriptions
  • All new topics wired into: curriculum.ts, sidebar, mobile nav, lessons index, landing page (with art), and the practice hub where applicable
  • tsc, lint, and build all clean