- Replace all runs-on: runners-cartsnitch with ubuntu-latest - Remove SARIF upload steps (no Gitea Security tab) - Replace GitHub App token with secrets.GITEA_TOKEN in deploy-dev and deploy-uat Co-Authored-By: Paperclip <noreply@paperclip.ing>
CartSnitch
Grocery price intelligence — know what you're paying, every time.
CartSnitch is a self-hosted grocery price intelligence platform that connects to your store loyalty accounts, tracks prices across retailers, monitors shrinkflation, and helps you find the best deals.
Project Overview
CartSnitch solves the problem of grocery price opacity. Most shoppers don't know if they're getting a good deal, whether prices have spiked since their last visit, or if the "sale" is actually a worse price than a competitor. CartSnitch makes prices transparent.
Core features:
- Connect Meijer, Kroger, Target loyalty accounts
- View purchase history across all stores in one timeline
- Track per-item price charts across stores over time
- Receive shrinkflation and price increase alerts
- Browse active coupons and deals
- Generate optimized shopping lists with store-split plans
- Public price transparency dashboards
Architecture
CartSnitch is a polyglot microservices platform. The monorepo contains the frontend PWA and core services.
┌─────────────────────────────────────────────────────────────────┐
│ CartSnitch PWA │
│ (React, mobile-first PWA) │
└──────────┬────────────────────┬────────────────────┬───────────┘
│ │ │
▼ ▼ ▼
┌──────────────────┐ ┌─────────────────┐ ┌─────────────────────┐
│ Auth Service │ │ API Gateway │ │ ReceiptWitness │
│ (Better-Auth) │ │ (Python/FastAPI)│ │ (Python/Scrapers) │
│ Session mgmt │ │ REST + proxy │ │ Purchase ingestion │
└────────┬─────────┘ └────────┬────────┘ └──────────┬──────────┘
│ │ │
└──────────────────────┼────────────────────────┘
▼
┌────────────────────────┐
│ CloudNativePG (PGSQL) │
│ Shared database │
└────────────────────────┘
Services in This Repo
| Directory | Service | Description |
|---|---|---|
/ (root) |
Frontend | React PWA, mobile-first |
auth/ |
Auth | Better-Auth service — session management, email/password, OAuth |
api/ |
API Gateway | Frontend-facing REST API, Python/FastAPI |
common/ |
Common | Shared Python models, Pydantic schemas, Alembic migrations |
receiptwitness/ |
ReceiptWitness | Purchase data ingestion via retailer scrapers |
Other CartSnitch Repos
| Repo | Service |
|---|---|
cartsnitch/stickershock |
Price increase detection & CPI comparison |
cartsnitch/shrinkray |
Shrinkflation monitoring |
cartsnitch/clipartist |
Coupon/deal watching |
cartsnitch/infra |
Kubernetes manifests, Flux kustomizations |
Tech Stack
Frontend
- React 18+ with TypeScript
- Vite — build tool
- Tailwind CSS v4 — mobile-first responsive design
- Workbox — service worker, offline caching, PWA manifest
- Recharts — price trend visualizations
- TanStack Query — data fetching and caching
- React Router v7 — client-side routing
- Zustand — lightweight state management
Backend Services
- Better-Auth — authentication (session management, email/password, OAuth)
- Node.js (API Gateway)
- Python/FastAPI (API Gateway, ReceiptWitness)
- PostgreSQL via CloudNativePG
- DragonflyDB for caching
Infrastructure
- Kubernetes (k3s-compatible)
- Flux CD — GitOps deployment
- GitHub Actions — CI/CD
- CalVer (
YYYY.MM.DD[.N]) — image tagging - Bitnami Sealed Secrets — secret management
- Authentik — OIDC/OAuth2 provider
Getting Started
Prerequisites
- Node.js 20+
- npm or pnpm
- PostgreSQL (local or containerized)
- Docker (for running services locally)
Local Development
-
Clone the repo
git clone https://github.com/cartsnitch/cartsnitch.git cd cartsnitch -
Install dependencies
npm install -
Set up environment variables
cp .env.example .env # Edit .env with your local settings -
Start the frontend dev server
npm run devThe PWA will be available at
http://localhost:5173. -
Run tests
npm test -
Build for production
npm run build
Running Backend Services Locally
The frontend PWA communicates with three backend services. For full local development, you'll need to run each service:
# Auth service (Better-Auth)
cd auth
npm install
npm run dev
# API Gateway (separate repo: cartsnitch/api)
# See api/README.md
# ReceiptWitness (separate repo: cartsnitch/receiptwitness)
# See receiptwitness/README.md
Environment Variables
| Variable | Description | Default |
|---|---|---|
VITE_API_URL |
API Gateway base URL | http://localhost:3000 |
VITE_AUTH_URL |
Auth service base URL | http://localhost:3001 |
Contributing
We welcome contributions. Please follow the workflow below.
Branching Strategy
- Branch from
dev - Use prefix:
feature/,fix/,docs/,chore/ - Examples:
feature/shopping-list-optimization,fix/price-chart-zoom
Commit Convention
We use Conventional Commits:
feat: add shopping list export
fix: correct price chart date formatting
docs: update API documentation
chore: update dependencies
Pull Request Workflow
- Open a PR against
dev - CI must pass (lint, type check, tests, e2e)
- QA reviews and approves
- CTO merges to
dev - Dev deploys automatically
- CTO promotes
dev → uat - UAT and security review
- CEO merges
uat → main - Production deploys automatically
Never push directly to main, dev, or uat.
Code Standards
- ESLint for linting
- TypeScript strict mode
- Mobile-first responsive design
- Accessibility (WCAG 2.1 AA)
Testing
Unit Tests
npm test
E2E Tests (Playwright)
npm run test:e2e
Tests run headless by default. For headed mode:
npm run test:e2e:headed
Lighthouse CI
Performance audits run automatically in CI. To run locally:
npm run build
npm run preview
# In another terminal:
npx lighthouse http://localhost:4173 --output=html --output-path=./report/lighthouse.html
CI/CD Pipeline
All branches (main, dev, uat) run through GitHub Actions on every push.
Pipeline Stages
| Job | Trigger | Purpose |
|---|---|---|
lint |
Every push | ESLint + TypeScript type check |
test |
Every push | Unit tests via Vitest |
audit |
Every push | Security vulnerability scan |
e2e |
Every push | Playwright end-to-end tests |
lighthouse |
After test | Performance budget check |
build-and-push |
On push to main/dev/uat | Build and push Docker images to GHCR |
deploy-dev |
On push to dev or main | Update cartsnitch/infra → auto-deploy to dev |
deploy-uat |
On push to uat or main | Update cartsnitch/infra → auto-deploy to uat |
Image Tagging
- Production (
main): CalVer tag (YYYY.MM.DD[.N]) +latest - Development (
dev): SHA tag (sha-<short-sha>)
Deployment Environments
| Environment | Namespace | URL | Trigger |
|---|---|---|---|
| Dev | cartsnitch-dev |
cartsnitch.dev.farh.net |
Push to dev branch |
| UAT | cartsnitch-uat |
cartsnitch.uat.farh.net |
Push to uat branch |
| Production | cartsnitch |
cartsnitch.farh.net |
Push to main branch |
Deployment
Infrastructure
The infrastructure repository (cartsnitch/infra) contains Kubernetes manifests and Flux Kustomize overlays.
Flux GitOps Flow
- CI builds and pushes a new Docker image
- CI opens a PR to
cartsnitch/infraupdating the image tag - On merge, Flux reconciles the manifests and rolls out the new image
Forcing a Rollout
To force pods to pick up a new :latest image:
kubectl rollout restart deployment/<name> -n <namespace>
Secrets
Secrets are managed via Bitnami Sealed Secrets. No plain Kubernetes secrets are used.
Related Projects
- StickerShock — Price increase detection
- ShrinkRay — Shrinkflation monitoring
- ClipArtist — Coupon/deal optimization
- Infra — Kubernetes infrastructure
License
MIT © 2025 CartSnitch