Non-root users cannot bind to ports < 1024. Port 8080 is used by
nginxinc/nginx-unprivileged by default.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Switch from nginx:stable-alpine to nginxinc/nginx-unprivileged:stable-alpine.
The unprivileged image runs as nginx user (UID 101) on port 8080, satisfying
the runAsNonRoot: true security context in Kubernetes.
Fixes: https://github.com/cartsnitch/infra/issues/65
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Full Twitter/X and Reddit promotional copy for all 5 shrinkflation
series posts (anchor top-10, dairy, frozen, household, snacks).
Includes 7-tweet thread + Reddit crosspost for Apr 1 anchor, and
single-tweet + thread teaser for Apr 3-11 series posts.
Refs: CAR-202, CAR-170, CAR-199
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Update frontmatter and footer navigation for dairy, frozen food,
household essentials, and snacks posts to match the cereal post series
format. Sets consistent series name "The Shrinkflation Files", correct
part numbers (2–5), and properly linked prev/next nav footers.
Refs: CAR-157, CAR-114
Co-authored-by: Frontend Frankie <frankie@cartsnitch.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* content: add founder story blog post — Why We Built CartSnitch
Replaces the Phase 1 draft with the final founder story from CMO
content-spec (CAR-134). Personal narrative opening, clearer positioning
against coupon/crowdsourced tools, and beta launch CTA.
Refs: CAR-134, CAR-114
Co-Authored-By: Paperclip <noreply@paperclip.ing>
* content: merge founder story with data stats per Penny's review (v1.1)
Restores BLS/USDA statistics, specific shrinkflation examples, and
privacy footer from the original draft. Keeps the founder pasta story,
three-things framework, and cleaner positioning from the CMO content-spec.
Combined version addresses all points raised in Penny's changes-requested review.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
---------
Co-authored-by: Frontend Frankie <frankie@cartsnitch.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
* content: add shrinkflation series post 1 — The Shrinkflation Files: Cereal
Updates cereal blog post with final content-spec v1.0 from CAR-141.
Refined narrative structure: why cereal, unit-price math, CartSnitch
tracking section, five-part series framing.
Part of shrinkflation series (CAR-141, parent CAR-114).
Co-Authored-By: Paperclip <noreply@paperclip.ing>
* content: update cereal shrinkflation post to v1.1 with brand-specific data
Restores brand data table (Cheerios, Frosted Flakes, Lucky Charms, etc. with
exact oz reductions and unit price math), adds three-blind-spots psychology
section, and $80-120/year family impact estimate. Keeps series branding,
CartSnitch product section, and series preview from content-spec draft.
Addresses CEO changes-requested review on PR #29.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
---------
Co-authored-by: Frontend Frankie <frankie@cartsnitch.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
Adds marketing blog post comparing CartSnitch, Flipp, Basket, and Ibotta.
Covers shrinkflation detection, automatic tracking, and store comparison.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Onboarding guides cover the five core user flows: getting started,
connecting store accounts, setting up price alerts, reading the
dashboard, and comparing stores. FAQ addresses common questions
about how CartSnitch works, data privacy, supported stores, and
troubleshooting.
All guides include screenshot placeholders for integration once
staging is available (blocked on CAR-60).
Ref: CAR-114
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Copy 10 marketing content files from the cmo/content-phase1 branch
of cartsnitch/agents into content/marketing/, preserving the
blog/, email/, and social/ subdirectory structure.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Avoids Docker Hub 429 rate limits by pulling node:20-alpine and
nginx:stable-alpine from ghcr.io/cartsnitch/mirror/. GHCR login
now runs on all builds (not just main push) to authenticate pulls.
Ref: cartsnitch/infra#7, CAR-55
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Build stage uses node:20-alpine to install deps and build.
Prod stage uses nginx:stable-alpine to serve static assets.
Includes nginx config with SPA routing, gzip, health endpoint,
and aggressive caching for Vite-hashed assets.
Closes#6
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- AccountLinking: remove unused _fields param from handleConnect
- Coupons: extract Date.now() to pure helper function outside component
to satisfy react-hooks/purity rule
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Manifest referenced icon files that didn't exist, causing PWA install to fail.
Generates placeholder brand-blue icons for all three required sizes.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Must-fix:
- Exclude JWT token from Zustand persist (partialize) to prevent
localStorage XSS exfiltration — token now lives in memory only
- Wire all pages through TanStack Query hooks (usePurchases, useProduct,
useProducts, usePriceHistory, useCoupons, usePriceAlerts) with proper
loading skeletons and error states
- Add mock interceptor in api.ts (VITE_MOCK_API=true) so mock data flows
through the same fetch path — single flag to switch to live API
Should-fix:
- Wire theme toggle to DOM (dark class on <html>)
- Fix AccountLinking form inputs (controlled with value/onChange)
- Remove unused err in catch blocks (Login, Register)
- Bump remaining min-h-10 touch targets to min-h-12 (48px)
Build: 128KB initial JS, Recharts 498KB lazy chunk. 5/5 tests pass.
Co-Authored-By: Paperclip <noreply@paperclip.ing>