Skip to content
2BKK

Blog · Performance

Why smarties.co ships six kilobytes of JavaScript

By 2BKK · Published 27 September 2026

smarties.co is a free learning site for children aged five to ten: 76 short games across 11 subjects, parent guides, printable worksheets, a whiteboard mode for teachers, and a full Polish version. The public pages load about six kilobytes of JavaScript. The games run as an installable app that works with no connection. There is no framework anywhere. This post is about why, and what that choice cost.

Two different jobs, two different builds

A site like this has two audiences with opposite needs. Parents and teachers arrive from search, read a page, and decide. Children open one game and play it for two minutes on an iPad, often on a bad connection or none at all.

So the site is split at the URL:

  • The public pages (/, /games/…, /guides/, /worksheets/, /pl/…) are static HTML and CSS with one small script for the menu, the consent question and the language switch. They are cached at the CDN edge and render before any script runs.
  • The game lives under /play/ as a web app with a manifest and a service worker. Once it has been opened, it opens again from the home screen, full screen, without a network.

Neither part needs a component framework. The public pages have no state to manage. The game has state, but it is a few hundred lines per game and a shared runner, and a service worker caches it once.

What "no framework" bought

  • Nothing to hydrate. The page is done when the HTML arrives. There is no moment where the content is visible but the buttons do not work yet.
  • Nothing to upgrade. No dependency tree, no security advisories in packages the site does not use, no build that stops working when a major version ships.
  • A sitemap that is just a list. 345 URLs in English and Polish, each with hreflang pointing at its twin, generated from the same content files that produce the pages.

What it cost

  • Every shared element (header, footer, consent question) is a template, and templates need a build step of some kind. Ours is a script, not a framework, but it is still code somebody maintains.
  • Translations live next to the English text and have to be kept in step by hand. A framework would not have solved that either.
  • Interactive pages with real state are more work without a component model. There is exactly one such page here, the game, and it is worth the work.

Analytics that wait for consent

The site tells parents that nothing about their child leaves the device. A tracking request before consent would make that untrue, so the analytics tag is not loaded at all until a parent says yes. Consent Mode is set to "denied" before any other script runs. The game pages are never measured. When consent is given, the tag still waits until the browser is idle, because loading it the ordinary way moved the performance score from 100 to 85 and the largest paint from about 1.5 seconds to about 4 seconds on the same page.

Where this applies to your site

Most marketing sites are the public half of this story: pages people read and then act on. They rarely need a framework at all, and when they do (a form with logic, a configurator, a booking flow), the interactive part can be one island on an otherwise static page. That is how we build the Next.js sites in our other case studies too: static output for everything that does not change per visitor, and JavaScript only where a click has to do something.

Have a site with the same problems?

We fix what we write about. Send a few lines and we tell you whether we can help.