Git history, but for websites.
Webrewind pulls a site's snapshots from the Wayback Machine, deduplicates unchanged captures, and stitches them into a scroll-driven timeline with AI-written captions and a looping GIF reel.
- Query the Wayback CDX API for captures in a given year range.
- Dedupe consecutive snapshots by HTML digest — no ten copies of the same page.
- Capture each unique snapshot in parallel with headless Chrome.
- Store frames and an encoded GIF in MinIO/S3.
- Caption each frame on demand with Gemma 3n (NVIDIA).
- Stream progress over SSE; render a vertical timeline in React.
- Client — React 18, TypeScript, Vite, Tailwind, Radix, Framer Motion
- Server — Node, Express, Puppeteer,
gif-encoder-2, axios - Storage — MinIO (S3-compatible)
- AI — NVIDIA Gemma 3n (
google/gemma-3n-e4b-it) - Monorepo — Turborepo + Yarn workspaces
webrewind/
├── apps/
│ ├── client/ # Vite + React (@webrewind/client)
│ └── server/ # Express + Puppeteer (@webrewind/server)
├── turbo.json
└── package.json
git clone https://github.com/iamspathan/webrewind.git
cd webrewind
yarn install
yarn devClient on http://localhost:5173, server on http://localhost:3200.
You need MinIO reachable on :9000 with a public webrewind bucket. The simplest path is docker compose up -d if a compose file ships with your checkout; otherwise point MINIO_ENDPOINT at your own instance.
Copy .env.example to .env in each app.
Server — the essentials:
| Variable | Purpose |
|---|---|
PORT |
server port (default 3200) |
MINIO_ENDPOINT |
S3 endpoint the server writes to |
MINIO_PUBLIC_URL |
S3 endpoint the browser reads from |
MINIO_BUCKET |
bucket name (default webrewind) |
MINIO_ACCESS_KEY / MINIO_SECRET_KEY |
credentials |
NVIDIA_API_KEY |
enables AI captions (optional) |
CAPTURE_CONCURRENCY |
parallel Puppeteer pages (default 4) |
Client:
| Variable | Purpose |
|---|---|
VITE_API_BASE_URL |
API base (empty in dev — Vite proxy) |
VITE_API_PROXY_TARGET |
dev proxy target (default http://localhost:3200) |
yarn dev # run client + server (turbo)
yarn build # build everything
yarn lint # lint everything
yarn workspace @webrewind/client dev # client only
yarn workspace @webrewind/server dev # server onlyPOST /screenshots— start a capture job; returns{ jobId, streamUrl }GET /screenshots/events/:jobId— SSE progress streamDELETE /screenshots/:jobId— cancel a jobPOST /summaries— caption a single frameGET /health·GET /metrics·GET /docs— ops
Full OpenAPI at /docs.
PRs and issues welcome. Open one and we'll take a look.
MIT.
