Platform Stats after Wave 19
Wave 19 Retrospective
Wave 19 explored the physics of the universe at its largest scales and smallest times. Spotlight #38 traced inflationary cosmology through the CMB acoustic peaks to dark matter N-body simulations and the emerging DESI BAO constraints. Learning #29 built general relativity from the geodesic equation up to Kerr black holes, gravitational waves, and the information paradox. Spotlight #39 took a deep dive into physical chemistry — Eyring TST, Marcus electron transfer, DFT, and femtosecond wavepacket spectroscopy.
Cosmology & Dark Matter: CMB, Inflation, N-Body Simulations & Large-Scale Structure
General Relativity & Curved Spacetime: From the Equivalence Principle to Black Holes
Physical Chemistry & Reaction Dynamics: Transition States, Marcus Theory, Spectroscopy and Femtochemistry
Full Offline-First PWA
The Wave 18 service worker pre-cached all 75 category index pages but not the 345 individual simulation pages. Wave 19 extends the precache list to every simulation root HTML, giving visitors the full simulation library offline after their first visit. The total precache footprint is approximately 12 MB of HTML, CSS, and JS (excluding WebGL textures and Three.js, which are too large to cache unconditionally).
Service Worker v19 — Precache Strategy
// sw.js key changes in v19 // 1. Build-time manifest from directory listing (Node script) const SIM_PRECACHE = [ '/acid-base/', '/adc-dac/', '/aerofoil/', ... (345 entries) ].map(path => ({ url: path, revision: BUILD_HASH })); // 2. Quota-aware cache installation async function installWithQuotaCheck(cacheName, urls) { const estimate = await navigator.storage.estimate(); const availableMB = (estimate.quota - estimate.usage) / 1e6; if (availableMB < 50) { console.warn('[SW] Low storage, skipping sim precache'); return; } const cache = await caches.open(cacheName); // Batch in groups of 20 to avoid overwhelming fetch pipeline for (let i = 0; i < urls.length; i += 20) { await cache.addAll(urls.slice(i, i + 20)); } } // 3. CacheFirst for simulation pages (long cache lifetime) registerRoute( ({ url }) => SIMS.some(s => url.pathname.startsWith(s)), new CacheFirst({ cacheName: 'sims-v19', plugins: [ new ExpirationPlugin({ maxEntries: 400, maxAgeSeconds: 60 * 60 * 24 * 30 }), new CacheableResponsePlugin({ statuses: [200] }) ]}) ); // 4. NetworkFirst for blog posts (always fresh when online) registerRoute( ({ url }) => url.pathname.startsWith('/blog/'), new NetworkFirst({ cacheName: 'blog-v19', networkTimeoutSeconds: 3, plugins: [ new ExpirationPlugin({ maxAgeSeconds: 86400 }) ] }) ); // 5. Offline fallback setCatchHandler(async ({ request }) => { if (request.destination === 'document') return caches.match('/offline.html'); return Response.error(); });
An in-page install prompt is now triggered after a user’s 3rd
simulation visit using the beforeinstallprompt event. The
UI shows a dismissible banner with estimated session count and offline
capability pitch. Early data (simulated): 6% install rate on mobile,
2% on desktop.
Search Result Highlighting
The fuzzy search introduced in Wave 18 returns ranked simulation
results but displayed them without any visual indication of
where the query matched. Wave 19 adds term highlighting:
matched words and partial n-grams are wrapped in
<mark> elements with an amber background, and
F3/Shift+F3 keyboard shortcuts cycle through highlights in the result
list.
Custom DOM-Range Highlighter (no library)
// highlight.js — ~60 lines, no external dependency function escapeRe(s) { return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); } export function highlightTerms(container, terms) { // Walk all text nodes under container const iter = document.createNodeIterator(container, NodeFilter.SHOW_TEXT); const nodes = []; let n; while ((n = iter.nextNode())) nodes.push(n); const pattern = new RegExp( `(${terms.map(escapeRe).join('|')})`, 'gi' ); nodes.forEach(textNode => { const text = textNode.nodeValue; if (!pattern.test(text)) return; pattern.lastIndex = 0; const frag = document.createDocumentFragment(); let last = 0, match; while ((match = pattern.exec(text)) !== null) { if (match.index > last) frag.appendChild(document.createTextNode(text.slice(last, match.index))); const mark = document.createElement('mark'); mark.textContent = match[0]; mark.style.cssText = 'background:#fbbf24;color:#000;border-radius:2px;padding:0 1px'; frag.appendChild(mark); last = pattern.lastIndex; } if (last < text.length) frag.appendChild(document.createTextNode(text.slice(last))); textNode.parentNode.replaceChild(frag, textNode); }); } // Keyboard navigation through marks let markIdx = -1; document.addEventListener('keydown', e => { const isF3 = e.key === 'F3' || (e.ctrlKey && e.key === 'g'); if (!isF3) return; e.preventDefault(); const marks = [...document.querySelectorAll('#results mark')]; if (!marks.length) return; markIdx = (markIdx + (e.shiftKey ? -1 : 1) + marks.length) % marks.length; marks[markIdx].scrollIntoView({ behavior: 'smooth', block: 'center' }); marks.forEach((m, i) => m.style.outline = i === markIdx ? '2px solid #ff7043' : ''); });
The highlighter is applied to simulation title, category, and description fields within each result card, using the tokenised query terms from the fuzzy-search engine. Trigram matches below 0.6 cosine similarity are excluded from highlighting to avoid highlighting near-random character coincidences.
JSON-LD Structured Data Audit
Google’s Rich Results Test found 47 simulations missing required
schema properties. Wave 19 adds three missing fields to every
simulation’s JSON-LD block:
educationalLevel (secondary/undergraduate/graduate),
teaches (array of learning objectives from the simulation
description), and learningResourceType (always
"simulation" per schema.org vocabulary).
JSON-LD Enrichment Template (per simulation)
- "@type": "WebApplication", - "name": "Acid-Base Equilibrium", - "description": "Interactive acid-base simulation..." + "@type": ["WebApplication", "LearningResource"], + "name": "Acid-Base Equilibrium", + "description": "Interactive acid-base simulation...", + "educationalLevel": "undergraduate", + "teaches": [ + "pH calculation", + "Henderson-Hasselbalch equation", + "buffer chemistry", + "titration curves" + ], + "learningResourceType": "simulation", + "interactivityType": "active", + "isAccessibleForFree": true
A Node.js audit script reads all 345 index.html files,
extracts existing JSON-LD, validates against the schema.org
vocabulary, and generates a patch manifest. Post-deployment validation
via Google’s Search Console batch URL inspector shows 0 errors
and 302 eligible for rich results (43 simulations have no significant
educational structured data candidates and use
WebApplication only).
Wave 19 Engineering Checklist
- ✓SW v19 precaches all 345 simulation root HTML pages with quota guard
- ✓Batch install loop (20 at a time) prevents Service Worker install timeout
- ✓In-page PWA install prompt shown after 3rd simulation (mobile-first)
- ✓Custom DOM-range search highlighter (no mark.js dependency, 60 lines)
- ✓F3/Shift+F3 keyboard cycling through highlighted search terms
- ✓JSON-LD audit script: 345 files checked, 302 enriched with educationalLevel/teaches/learningResourceType
- ✓Google Rich Results Test: 0 errors post-deploy, 302 eligible for rich snippets
- ✓Lighthouse PWA score: 100 (up from 96 pre-Wave 19 )
- ⚠OG image / video thumbnail generation for 50+ simulations — deferred to Wave 20
Wave 20 Preview
Immunology & Infectious Disease
Innate vs adaptive immunity, T-cell receptor diversity, vaccine mechanisms, herd immunity R₀, and epidemic SIR/SEIR modelling.
Statistical Field Theory
Path integrals, partition functions, Ising model renormalisation group, universality classes, and connections between QFT and statistical mechanics.
Geophysics & Seismology
Plate tectonics, seismic P/S wave propagation, normal mode oscillations of the Earth, geoid and gravity anomalies, and mantle convection.
Video Thumbnails & OG Images
Automated Playwright-based screenshot pipeline for 50+ simulation OG images, social share previews, and video thumbnail generation for the blog feed.
Wave 20 marks an important milestone: Learning #30 will be the 30th post in the longest-running educational series on the platform. Statistical field theory sits at the intersection of condensed matter physics, quantum gravity, and machine learning (Boltzmann machines, diffusion models) — connecting half a dozen other spotlight topics in a single framework.