---
slug: /tiny-replay/
url: https://zajdband.com/tiny-replay/
markdownUrl: https://zajdband.com/tiny-replay/index.md
title: Your run, ride or hike, as a tiny illustrated replay
description: >-
  I made an app that turns a run, a ride or a hike into an illustrated replay on the real map.
  Instead of telling you what it does, four details you can play with: the camera, the colour of the
  sky, the music and the video.
published: '2026-09-23T15:00:00.000Z'
updated: '2026-09-23T15:00:00.000Z'
language: en
category: Web
tags:
  - tiny-replay
  - canvas
  - web-audio
  - webcodecs
wordCount: 980
readingMinutes: 5
license: https://creativecommons.org/licenses/by/4.0/
draft: false
---

[Tiny Replay](https://tinyreplay.zajd.band) takes a run, a bike ride or a hike and turns it into a tiny illustrated replay on the real map. You can race friends or yourself on another day, and download an image or a video.

I made it last night, and the excuse was trying out **Opus 5.5**. I wanted to see how far it would get in one sitting with something that was not a CRUD: maps, canvas, audio, video. It got pretty far.

<div class="tr-player"><iframe src="https://tinyreplay.zajd.band/?demo=rio&amp;embed" title="Tiny Replay playing its Madrid Río demo: six runs along the same stretch of river" width="640" height="480" loading="lazy" allow="autoplay; fullscreen" style="aspect-ratio: 4 / 3; background: #f7e6da; border: 0; border-radius: 20px; display: block; height: auto; width: 100%;"></iframe></div>

<p class="tr-open"><a href="https://tinyreplay.zajd.band/?demo=rio">Open it in Tiny Replay ↗</a>, with the music, styles and saving.</p>

I am not going to say much more about what it does: [try it](https://tinyreplay.zajd.band) with a demo, it is faster. I will tell you about four details I like, and each one can be played with below. Almost all of them use the app's code as is.

## A camera that does not get dizzy

The first thing you do to make a camera follow something is move it a little piece of the way every frame. It works, but it starts with a jolt: the top speed is the first frame, and that feels like a yank. Tiny Replay's is a critically damped spring, the same trick as Unity's `SmoothDamp`: it speeds up, arrives and slows down, without overshooting.

<div data-toy="camera"><p><em>Interactive: two cameras follow a runner who jumps around the map, one with the yank and one with the spring. Needs JavaScript.</em></p></div>

Look at the line at the bottom: the grey one is a spike, the pink one is a hill. The zoom works the same way, but the spring runs on the logarithm of the zoom, so zooming in to double and out to half feel the same.

## The map has the colour of the sky

With the style on *Auto*, the app works out how high the sun was at the place and time you ran, halfway through the activity. If civil dusk had already passed, the map is at night; if the sun was low, it is golden hour. It is a ten-line NOAA formula and nobody is going to notice, but a run at sunset looks like a sunset.

<div data-toy="sky"><p><em>Interactive: a small map that changes colour with the time of the run in Madrid, on June 21. Needs JavaScript.</em></p></div>

## Music with nothing to license

I wanted the videos to have music and I did not want to think about licenses. So the music is not a file: it is a tiny drum machine (kick, snare, cymbals) and a few instruments made of oscillators and noise, playing patterns written by hand on a grid of sixteenth notes. Seven styles, from jazz with swing to reggaeton with its dembow.

<div data-toy="music"><p><em>Interactive: seven styles of music synthesised in the browser, with a grid showing what plays on each step. Needs JavaScript.</em></p></div>

The ugly part: on an iPhone with the silent switch on, Web Audio makes no sound. A video does. So on iOS the app asks for the "playback" audio session and, on older versions, loops half a second of silence in an `<audio>` built by hand, byte by byte, so the phone believes it is playing a video.

## A 29 second video in 5

The usual way to get a video out of a canvas is recording it with `MediaRecorder`, which is real time: a 29 second video takes 29 seconds. Tiny Replay encodes every frame with WebCodecs as soon as it is drawn, renders the music separately with an `OfflineAudioContext` (faster than real time) and packs both into an MP4. The same 29 second clip, with music, takes about 5 seconds.

<div data-toy="export"><p><em>Interactive: two bars filling up, one in 29 seconds and one in 5. Needs JavaScript.</em></p></div>

## An app you can share to

Tiny Replay is a web page, but you can install it, and the point is not the icon on the home screen. It is getting the activity in and the video out without hunting for files. On Android the installed app shows up in the share sheet: share a GPX or FIT file from wherever it is, and the replay opens. Share a Strava or Garmin link instead, and it opens on a helper that takes you to the file. On the way out, once the image or video is ready, a Share button sends it straight to another app, wherever the browser can share files.

The service worker does only that: it receives what is shared. It does not cache the app, so a new version is never hidden behind an old one.

## And other little details

- **The file does not leave your browser.** There is no server. The only things requested from outside are the map around the route, from OpenStreetMap (which is kept in IndexedDB), and the visits to Google Analytics.
- **It opens before the map.** The replay starts as soon as the file is read, on a blank map, and the map fades in when it arrives.
- **Asking two servers at once.** If the map server has not answered in 6 seconds, another one is asked too, and the first to answer wins. Nobody waits for a slow server to time out before trying the next one.

## Things to explore next

- **Customising the characters.** Today everyone is the same little character in a different colour.
- **Landmarks.** OpenStreetMap knows which buildings are landmarks, so if you run past one, the map could point it out.
- **Exporting highlights.** A short video with just the best moments of a long activity, instead of the whole route.

## Closing

I started it last night with Claude Code and Opus 5.5, just to try the model, and by the morning I had all of this. It is about 3,000 lines of JavaScript in modules, no framework and no build: an `index.html` and a `js/` folder.

If you run, [upload your last run](https://tinyreplay.zajd.band). If not, open one of the demos and tell me which music style you liked best.

<script type="module" src="/tiny-replay/toys.js"></script>
