DEV Community

Cover image for Building an Educational Math Game with Next.js, Pure SVGs, and JSON-LD
7x Games
7x Games

Posted on

Building an Educational Math Game with Next.js, Pure SVGs, and JSON-LD

Hey DEV community! ๐Ÿ‘‹

I recently added a new educational game to my web arcade, 7x.games, called Fraction Math Master.

Usually, when developers think of building web games, they immediately reach for Canvas, WebGL, or engines like Phaser. But for educational puzzle games, that is often overkill. I wanted to share how I built a highly interactive, fast, and SEO-optimized math game using pure React, Tailwind CSS, and SVGs.

Here is a breakdown of the technical hurdles and how I solved them.

๐Ÿ• 1. Drawing Dynamic "Pizza Slices" with SVG Math
Kids learn fractions best visually. I needed a way to show a circle divided into any number of slices (denominator) with a specific number of them shaded in (numerator).

Instead of loading heavy image assets, I built a FractionCircle React component that generates SVG paths on the fly using basic trigonometry.

By calculating the angle of each slice ((2 * Math.PI) / denominator), I used Math.cos and Math.sin to draw exact SVG arcs.

JavaScript
// Simplified snippet of the SVG math
const cx = size / 2;
const cy = size / 2;
const r = size / 2 - 8;
const sliceAngle = (2 * Math.PI) / den;

const startAngle = -Math.PI / 2 + i * sliceAngle;
const endAngle = startAngle + sliceAngle;

const x1 = cx + r * Math.cos(startAngle);
const y1 = cy + r * Math.sin(startAngle);
const x2 = cx + r * Math.cos(endAngle);
const y2 = cy + r * Math.sin(endAngle);

// Draw the wedge!
const path = M ${cx} ${cy} L ${x1} ${y1} A ${r} ${r} 0 ${largeArc} 1 ${x2} ${y2} Z;
Because it is pure SVG, it scales flawlessly on mobile screens, weighs literally bytes, and allows me to add smooth CSS transform: scale(1.03) pop animations when the user gets an answer correct.

๐Ÿ›‘ 2. Avoiding the "Infinite While Loop" Trap
The game generates dynamic multiple-choice questions (e.g., "Find an equivalent fraction for 2/4").

Initially, I used a while loop to generate random wrong answers. The logic was: Generate a random fraction. If it equals the correct answer, throw it out and loop again. The bug: If the math constraints were too tight (e.g., Easy Mode where the max denominator is 6), the random number generator could run out of unique wrong answers, trapping the browser in an infinite while loop and crashing the tab.

The Fix: I switched to a Deterministic Array Generator.
Instead of "guessing" random numbers, I wrote a helper function that instantly calculates every single possible wrong answer within the difficulty limits, pushes them into a pool, shuffles the pool, and returns the top 3.

JavaScript
// Pre-generate valid wrong answers to avoid infinite loops
function getSafeWrongs(correctN, correctD, count, maxD) {
const correctVal = correctN / correctD;
const pool = [];

for (let d = 2; d <= maxD + 5; d++) {
for (let n = 1; n < d; n++) {
if (n / d !== correctVal) {
pool.push({ num: n, den: d, label: ${n}/${d} });
}
}
}

shuffle(pool);
return pool.slice(0, count); // Guaranteed to never freeze!
}
Zero guessing. Zero chance of an infinite loop.

๐Ÿ” 3. Enterprise SEO in Next.js (JSON-LD)
A web game is useless if no one plays it. To get this game ranking on Google for queries like "Fraction Games Online Free For Kids", standard

tags aren't enough. <p>Using Next.js App Router, I injected Google's native languageโ€”JSON-LD Schema Markupโ€”directly into the layout.js of the game.</p> <p>I used two specific schemas:</p> <p>@type: VideoGame: Explicitly tells Google the genre, the audience (educational), and that it is free to play in a browser.</p> <p>@type: FAQPage: I hardcoded common search queries (e.g., "How do you simplify a fraction?") directly into the schema. This allows Google to pull the game page directly into the "People Also Ask" dropdown boxes on search result pages.</p> <p>JavaScript<br> export default function FractionMathLayout({ children }) {<br> return (<br> <><br> type="application/ld+json"<br> dangerouslySetInnerHTML={{ __html: JSON.stringify(mySchemaObject) }}<br> /><br> {children}<br> &lt;/&gt;<br> )<br> }<br> ๐ŸŽฎ The Result<br> The result is a fast, responsive, and highly interactive educational game that requires zero external assets to run. It has 5 game modes (Identify, Compare, Equivalent, Simplify, Add/Sub) and a combo-streak system.</p> <p>If you want to check out the SVG UI animations or try to get a 10x combo streak, you can play it here: Fraction Math on 7x.games</p> <p>What is your preferred stack for building 2D web games? Do you always reach for Canvas, or do you use React/DOM elements for simpler mechanics? Let me know!</p> </p>

Top comments (0)