PaceLab
PaceLab (paceslab.com) is een set van vijftien hardlooptools en referentietabellen die we volledig zelf hebben gebouwd, van merk tot rekenkern tot vindbaarheid. Het rekenwerk draait in de browser van de bezoeker: geen account, geen backend, en een ingevoerde tijd of afstand die het tabblad niet uit hoeft.
Bekijk live →
De uitdaging
Tempo uitrekenen is simpele wiskunde, maar de sites die die som aanbieden zijn dat zelden. In deze niche kom je pagina's tegen waar het antwoord onder een advertentieblok ligt, waar je eerst op een knop moet drukken voor een uitkomst, en waar niet staat welke formule eronder zit. De opgave die we onszelf stelden: dezelfde vraag beantwoorden, maar dan direct, controleerbaar en zonder dat de bezoeker er iets voor inlevert.
Onze aanpak
We bouwden een zuivere rekenkern in TypeScript en zetten daar vijftien ingangen op: calculators, een voorspeller, een splitsplanner en pace charts, allemaal gevoed door dezelfde functies. Het merk kreeg een eigen ontwerp zonder CSS-framework, donker en typografisch, waarin het getal de hoofdrol speelt. De site is statisch geprerenderd en rekent client-side, zodat er tijdens het rekenen geen server tussen de invoer en het antwoord zit.
Het resultaat
De site telt vijftien tools verdeeld over vier categorieen: drie calculators, twee plan- en voorspeltools, acht pace charts en twee naslaggidsen. Daaronder liggen 214 vooraf uitgerekende referentierijen en 51 uitgeschreven vraag-en-antwoordparen. De build levert twintig statische pagina's op en geen dynamische route: alles wordt vooraf gerenderd. De rekenkern is een klein, unit-expliciet TypeScript-bestand waarvan de formules ook op de site zelf staan uitgeschreven. De runtime-afhankelijkheden blijven beperkt tot Next.js, React en React DOM.
Resultaat
15 tools, 20 statische pagina's, 0 netwerkverzoeken tijdens het rekenen
Waarom juist deze niche
De som achter hardlooptempo is triviaal: tijd gedeeld door afstand. Precies daarom is het zo'n typische zoekopdracht. Bijna niemand gaat na een training staan puzzelen of 22 minuten over 5 kilometer nu 4:24 per kilometer is, en al helemaal niet of dat 7:05 per mijl betekent. Mensen zoeken het op, willen het antwoord zien en gaan verder. Dat maakt het een niche met veel, zeer specifieke vragen: welk tempo hoort bij een marathon van vier uur, wat betekent 12 kph op de loopband, wat kan ik lopen op de halve als mijn 10K 45 minuten was.
Wat ons opviel is dat de bestaande aanbieders die eenvoud zelden respecteren. Het antwoord staat onder een advertentieblok, je moet eerst op 'bereken' drukken, de pagina laadt traag omdat er een framework en een adnetwerk overheen ligt, en welke formule er onder een voorspelling zit blijft onduidelijk. Voor een vraag die in principe in een tiende seconde beantwoord is, is dat een merkwaardige hoeveelheid wrijving.
PaceLab is onze poging tot het tegenovergestelde. De site heet naar wat hij doet, de slogan 'Find your pace. Nail your race.' zegt de rest, en de belofte is simpel: je typt twee getallen en het derde staat er al. Geen knop, geen account, geen wachttijd. Die belofte is vervolgens de maatstaf geweest voor de technische en visuele keuzes in dit project.
Een rekenkern, vijftien ingangen
Alles begint bij lib/running.ts: een klein bestand met pure functies die expliciet zijn in hun eenheden. De conversies staan er onafgerond in. Een mijl is 1.609344 kilometer, een halve marathon 21.0975 kilometer, en de Riegel-voorspelling gebruikt de gangbare exponent 1.06. Bovenaan het bestand staan referentiewaarden waartegen we de rest ijken: 5:00 min/km is ongeveer 8:03 min/mijl, 10 kph is 6:00 min/km. De kernfunctie is solvePace: geef twee van de drie waarden afstand, tijd en tempo, en je krijgt de derde. Dat is de hele motor achter de pace-calculator. De finishtijdcalculator hoeft maar een kant op en doet die ene vermenigvuldiging zelf, maar haalt zijn afstandstabel, eenheidsconversies en opmaak uit datzelfde bestand; het verschil tussen die twee tools zit in de vraagstelling, niet in de wiskunde.
Daarbovenop ligt lib/tools.ts, een registry van vijftien tools verdeeld over vier categorieen: drie calculators, twee plan- en voorspeltools, acht pace charts en twee naslaggidsen. Voor die vijftien pagina's is de registry de bron voor de naam, de H1, de titel, de metabeschrijving, de kaarttekst en de categorie, en hij voedt het homepagegrid, de sitemap, de kruislinkblokken onderaan de toolpagina's en de ItemList in de gestructureerde data. De header- en footernavigatie in app/layout.tsx staan daarbuiten: dat zijn handgeschreven links. Voor de header is dat een keuze, want die toont bewust een korte selectie in plaats van de hele lijst. Voor de footer, die wel alle vijftien noemt, is het een restje: wie een tool toevoegt, werkt naast de registry ook die opsomming nog even bij.
De charts zijn geen losse datasets maar afgeleiden van diezelfde kern. Een chartpagina geeft alleen een afstand, een begin- en eindtijd en een stapgrootte door aan een component, die daaruit de tabel opbouwt. Zo ontstaan 189 rijen over acht afstanden, van de mijl in stappen van vijftien seconden tot de marathon in stappen van tien minuten, plus 25 rijen in de tempoconversietabel: samen 214 vooraf uitgerekende rijen. Ze komen uit dezelfde functies als de calculators en worden bij de build berekend, dus ze kunnen niet uit elkaar gaan lopen doordat iemand vergeet een handgemaakte tabel bij te werken. Wat je in een tabel leest kan hooguit anders afgerond zijn dan wat de calculator toont; de som eronder is dezelfde.
Een merk dat op een stopwatch lijkt
PaceLab heeft geen template en geen CSS-framework. Het ontwerp staat in een handgeschreven stylesheet die op een handvol custom properties in :root draait, en verder niets. In package.json staan drie runtime-afhankelijkheden: Next.js, React en React DOM. Wat je op het scherm ziet is dus wat we zelf hebben opgeschreven, tot aan de focusring toe.
De visuele keuze is een donkere baan met een enkele signaalkleur. De achtergrond is bijna zwart (#0b0b0d) met een warme gloed bovenin, en het accent is een fel oranje (#ff5a1f) dat spaarzaam wordt ingezet: de uitkomst, het veld waarvoor je op dat moment oplost, de links en de focusring. De koppen zijn Oswald, een smalle uppercase schreefloze met het karakter van een startnummer of een tijdregistratiebord. De lopende tekst is Inter. De getallen in de invoervelden en in de tabellen staan in monospace, zodat cijfers onder elkaar uitlijnen en een tijd als 1:45:00 niet zit te dansen terwijl je typt.
De reden dat dit bij het onderwerp past, is dat hardlopen een sport van aflezen is. Je kijkt naar je horloge, ziet een getal en beslist. Dus is het getal ook hier de held: het uitkomstblok zet het antwoord in Oswald op koptekstformaat, terwijl de rest van het scherm bewust stil blijft. De keuzeknoppen waarmee je aangeeft waarvoor je wilt oplossen zijn minimaal 44 pixels hoog, want dit wordt op een telefoon gebruikt, vaak met een duim, vaak buiten. Het is een interface die je in een oogopslag leest, niet een die je bestudeert.
Alles gebeurt in de browser
De site draait op Next.js 16 met de App Router, React 19 en TypeScript in strict-modus. Er is geen backend, geen database en geen API. Het buildresultaat bevestigt dat: het prerender-manifest telt 26 routes en geen enkele dynamische route. Twintig daarvan zijn echte pagina's, de overige zes zijn de sitemap, robots.txt, het icoon, de OG-afbeelding en de twee foutroutes. Bezoekers krijgen dus statische HTML van het CDN van Vercel.
Acht componenten zijn client-side, en zes daarvan doen het rekenwerk: de pace-calculator, de finishtijdcalculator, de voorspeller, de splitsplanner, de loopbandconverter en de eenheidshelper. Die zes rekenen in een useMemo bij elke toetsaanslag, wat betekent dat er geen verzendknop is en geen ronde naar een server. Het antwoord verandert terwijl je typt. De andere twee client-componenten rekenen niet: dat zijn het contactformulier en de consentbanner. Het contactformulier is ook het enige onderdeel in de bundel dat een netwerkverzoek doet; de zes rekencomponenten doen er geen. Dat is de reden dat we in de voettekst en het privacybeleid schrijven dat je trainingsdata het tabblad niet verlaat: voor die getallen zit er geen ontvanger in de code. Daarnaast staan er twee fetch-aanroepen in scripts/indexnow.mjs, maar dat is een Node-script dat we na een deploy met de hand draaien en dat niet in de bundel terechtkomt.
Onder die eenvoud zit het gebruikelijke detailwerk. In de pace-calculator, de tool waar het meeste getypt wordt, blijft het uitkomstenraster staan als de invoer nog ongeldig is en toont het streepjes, zodat de pagina daar niet verspringt op het moment dat het antwoord verschijnt; de andere vijf rekentools zetten zolang een foutregel op de plek van het raster, dus die winst staat nog op de lijst. De splitsplanner stopt bij 500 kilometer om te voorkomen dat een absurde invoer eindeloos rijen genereert, en herschaalt de segmenttempo's na afloop zodat de laatste cumulatieve tijd op je doeltijd uitkomt en niet een seconde ernaast. Een kaal getal in een tijdveld lezen we als minuten, omdat iemand die '25' typt 25 minuten bedoelt en geen 25 seconden; wie toch seconden wil, typt '0:25'.
Gevonden worden zonder trucs
Omdat de pagina's vooraf gerenderd zijn, staan de teksten, de tabellen en de gestructureerde data in de HTML zelf en hoeft een crawler er geen JavaScript voor uit te voeren. De twintig pagina's zetten elk hun eigen titel, metabeschrijving en canonical; op de vijftien toolpagina's komt die tekst uit de registry, de vier informatiepagina's schrijven hun eigen. De acht pace charts en twee gidsen vormen de longtail-laag: ze bedienen de zeer specifieke vragen, zoals welk tempo hoort bij een marathon van 3:30, waar de generieke calculator geen goed antwoord op is. Over de vijftien toolpagina's samen staan 51 uitgeschreven vraag-en-antwoordparen, waarvan 31 op die charts en gidsen. Elke toolpagina zet zijn FAQ ook als FAQPage in de gestructureerde data, met een BreadcrumbList ernaast; de homepage draagt een WebSite met een ItemList van de vijftien tools.
Een keuze die iets zegt over de houding: er staat bewust geen SoftwareApplication-node in de gestructureerde data. Google's rich result daarvoor vraagt om een aggregateRating of een review, en die hebben we niet. We verzinnen geen sterren, dus laten we de node weg en accepteren dat we dat rich result mislopen. Om dezelfde reden heeft de sitemap een vaste lastModified in plaats van new Date(). Anders meldt elke deploy dat de hele site vernieuwd is terwijl er aan de inhoud niets veranderde. Die datum zetten we met de hand vooruit als er wel iets verandert.
De rest is degelijk uitvoeringswerk. De OG-afbeelding wordt gegenereerd met next/og in de huisstijl, met een helper in lib/site.ts die een bekende valkuil omzeilt: Next vervangt het openGraph-object per routesegment in plaats van het samen te voegen, waardoor een pagina die zelf een OG-titel zet stilletjes de afbeelding uit de layout kwijtraakt. De helper zet type en images er weer bij, zodat dat niet gebeurt. Verder liggen er een robots.ts, een llms.txt voor taalmodellen die de site willen samenvatten, en een IndexNow-script dat na een deploy de sitemap-URL's aanmeldt bij de IndexNow-API, die deelnemende zoekmachines als Bing en Yandex bedient.
Waar het nu staat
De eerste commit is van 3 juli 2026. Sindsdien is de site in een handvol gerichte rondes gegroeid van de kerncalculators naar het volledige assortiment charts en gidsen, met tussendoor een auditronde waarin de OG-afbeelding, de mobiele navigatie, het contrast, de toegankelijkheid, de 404 en de sitemap-lastmod zijn rechtgezet. De laatste ronde, van 14 juli, ging over contentuitbreiding en het opruimen van Ahrefs-bevindingen. Het is een jonge site en we behandelen hem als zodanig: de aandacht gaat nu naar dekking en techniek, niet naar cijfers.
Monetisatie is voorbereid maar staat uit. Er is een advertentieslot en een consentbanner, allebei achter dezelfde vlag: ADS_ENABLED staat op false tenzij een omgevingsvariabele hem expliciet op 'true' zet, en zolang dat niet gebeurt renderen beide componenten niets. Het advertentieslot reserveert straks een vaste hoogte, zodat aanzetten later geen layout shift oplevert. De consentbanner is nadrukkelijk een plaatshouder: in de code staat erbij dat er een gecertificeerd consent-platform voor in de plaats moet voordat er ook maar een advertentiescript laadt. Daarmee doet de site vandaag wat hij belooft: gratis, snel en zonder advertentiecookies. Het moment waarop dat verandert is een bewuste beslissing en geen bijproduct van een integratie.
Voor een opdrachtgever is dit vooral een bewijsstuk. PaceLab is geen conceptontwerp en geen casus die we mochten bedenken, maar een site die we zelf hebben bedacht, gebrand, gebouwd, gepubliceerd en blijven onderhouden. De hele keten zit erin: de strategische keuze voor een niche, een eigen ontwerpsysteem in plaats van een template, een rekenkern die je kunt narekenen, een architectuur die de privacybelofte makkelijk maakt om waar te maken, en de SEO-discipline om dat vindbaar te maken zonder ergens een getal te verzinnen. Wat we voor onszelf bouwen, bouwen we op dezelfde manier voor anderen.
Klaar om jouw merk te laten groeien?
Vertel ons over je project. We denken graag met je mee, vrijblijvend.
Vrijblijvend. Je hoort binnen één werkdag van Jamey.