Skip to content

Galois

Learn group theory by turning a Rubik's cube. Live: rj8228.github.io/galois · Code: github.com/rj8228/galois

Pitch (30 seconds)

Galois is a free web app that teaches group theory through a 3D Rubik's cube. You turn the cube, notice what happens, and then learn the name for it: identity, order, permutations, commutators, invariants, and finally why every position can be solved in 20 moves or fewer. It has a daily competition, Solve of the Day, with a speed and a fewest-moves track. It's a static PWA on GitHub Pages, tested on phone, tablet and laptop with Playwright.

Why: I taught myself the cube from YouTube at 13. Ten years later I wanted the version that explains the maths. The design rule is "turn first, name it later": every idea starts as something you do on the cube.

Get the framework right

Galois is built with Preact + @preact/signals, not React (the portfolio's skills chip groups it under React). If asked: "Preact: same component and hooks API as React in 3 KB, which matters for a PWA on phones; signals for fine-grained state so a cube turn doesn't re-render the whole tree. My React work is the Prayog terminal and my day job."

Stack and why

Choice Why
TypeScript, Vite Types for the maths (permutations, moves); fast dev server and build
Preact + signals Small bundle for phones; signals update only what reads them
cubing.js 3D cube, notation and puzzle maths, instead of writing a renderer
PWA (vite-plugin-pwa, service worker) Works offline, installable
Vitest + Playwright Unit tests for the maths; E2E on phone, tablet and laptop viewports
Biome Lint + format in one fast tool
GitHub Pages, phases tagged v0.N.0 Every push to main deploys; each phase is a branch → PR → tag

The maths in interview-sized pieces

Idea On the cube Elsewhere in software
Group Moves with "do one then another", an identity (do nothing), and inverses (undo) Undo stacks, Git, CRDTs
Order of a move How many times you repeat it to get back to start (R has order 4; R U has order 105) Cyclic schedules
Permutation Every position is a rearrangement of the pieces Shuffling, sorting networks
Commutator A B A⁻¹ B⁻¹ Changes only a few pieces: the basis of most solving algorithms "Do, change, undo" refactoring
Invariant Some positions are impossible (a single flipped edge) because a parity is always preserved Loop invariants, consistency checks
God's number = 20 Every position can be solved in at most 20 face turns (proved 2010) Graph diameter

Good story: the update that never arrived (service worker)

  • Symptom: after v0.3.0 shipped, the live site kept showing the old "Arrives in Phase 3" page, even after reloads.
  • Cause: v0.3.0 switched the service worker to prompt mode, where the new worker waits until the page tells it to skipWaiting(). But the code that sends that message was in the new app; the browser was still running the old one, which didn't know how. On phones the old tab is rarely closed, so it waited forever.
  • Fix: a new worker takes over by itself as soon as it's installed (PR #4).
  • Lesson: an update mechanism must work with the previous version's code, not just the new one. Same idea as backward-compatible API and schema changes.
How does a service worker update?

The browser checks sw.js for changes (on navigation, at most every 24 h by default). If it changed, it installs the new worker, which then waits until all tabs controlled by the old worker are closed, unless it calls self.skipWaiting(). On activate, clients.claim() makes it control open pages. Cache strategies: cache-first for hashed assets, network-first for index.html.

How do you test a 3D app?

Unit-test the logic (moves, permutations, analysis) with Vitest, independent of rendering. Playwright E2E on three viewports for journeys (turn a face, complete a lesson). Visual checks with screenshots where needed. The renderer (cubing.js) is trusted; my code around it is tested.