← All projects

PrijsVink: Dutch supermarket price comparison

A full-stack product for searching and comparing supermarket prices across major Dutch retailers, built to stay simple and cheap to run.

What it does

PrijsVink collects product and price information from major Dutch supermarkets and lets you search and compare them in one place. Behind the search box: retailer data ingestion, product normalization, promotion handling, a Rust API and a public web application.

Architecture

PrijsVink architecture: a Python scraper updates SQLite, Docker packages the database with the Rust API, the private image is pushed to GitHub Container Registry and deployed to Render, and the React frontend on GitHub Pages calls the API over HTTPS.
Data flows one way: scrape, snapshot, package, deploy.
  • Python scrapers collect product information and prices.
  • SQLite stores products and prices.
  • Rust (Axum) serves the API, opening the database read-only.
  • React frontend on GitHub Pages.

Key decisions

Ship the database inside the image. The production API only reads, so a SQLite snapshot is packaged into the same Docker image as the API. No database server, no persistent disk, and every deployment is one predictable artifact. The trade-off: publishing new data means building and deploying a new image.

Keep the image private. The API exposes prices publicly, but the full database file shouldn't be a downloadable artifact, so the image lives in a private GitHub Container Registry and Render pulls it with credentials.

Accept free-tier trade-offs, knowingly. Render's free tier spins services down after inactivity, so the first request can be a cold start, and deploys are triggered manually. Fine for a side project; the upgrade path is clear when it matters.

Search

Search originally used repeated substring matching. Replacing it with SQLite's FTS5 full-text index reduced search latency by roughly 10× in current tests.

What's next

Automating image builds and deploys with GitHub Actions, and reducing the image size. The full deployment story, including a SQLite connection bug and how it was fixed, is in the blog post.

Visit PrijsVink ↗ GitHub ↗ ← Back to projects