Skip to content

Changelog

Every release that shipped to production, in reverse chronological order. Sourced from CHANGELOG.md in the repo — same file the team writes against.

  1. Unreleased

    In progress

    DevX

    • husky pre-commit runs lint-staged (eslint --fix on staged code) + tsc --noEmit; commit-msg hook nudges Conventional Commits, blocks one-word vague subjects.
    • GitHub issue templates (bug, feature, deal-data correction) + PR template + Dependabot config (weekly npm, monthly Actions/Docker, grouped major-bump bans).
    • CONTRIBUTING.md and CHANGELOG.md (this file).
  2. 2026-07-10

    feat(catalog): US units — lb / quart / fl oz

    Changed

    • Pet food renormalized to cost per lb, motor oil to cost per quart, haircare to cost per fl oz. Remaining category units unchanged (page, diaper, cartridge, ml). cost_per_unit values in the DB recomputed to match.
  3. 2026-07-09

    feat(relaunch): OutletPicks all-category pivot

    Added

    • All-category relaunch: supplements-only catalog replaced by 313 active deals across 8 categories — printer ink, pet food, grooming, baby care, skincare, automotive oil, haircare, fragrance.
    • Cost-per-unit engine: every deal normalized to its category unit and ranked by real cost per unit; daily price-refresh cron keeps the figures current.
    • Price-drop tracking (/this-week) and side-by-side compare tool (/compare).
    • 8 category buying guides on /guides, bylined OutletPicks Editorial.

    Changed

    • Legacy supplement guides noindexed and removed from hubs; supplement-era routes (/nutrients, /best/*, /cheapest/*, /stacks, /tools/*, /glossary, …) redirect or noindex.
  4. 2026-04-29

    perf: caching + N+1 + fonts + edge SWR

    Performance

    • listDeals collapsed N+1 — single LATERAL jsonb_agg round-trip.
    • In-process cached(key, ttl, loader) helper. Applied to countActiveDeals (5 min), /api/health (10 s), HotStrip top-6 query (30 s).
    • /vouchers, /free, /discussions now revalidate = 60 for ISR.
    • Caddy @publicHtml + @feeds + @manifest matchers add edge cache + SWR; @go keeps no-store for click counter.
    • Geist sans + mono get display: 'swap' + explicit fallback stack; adjustFontFallback: true on sans for CLS.
  5. 2026-04-29

    feat(seo/growth): FAQ + Person + Review LD, RSS, x-default, newsletter

    Added

    • FAQPage JSON-LD on /how with 7-question accordion.
    • Person JSON-LD for deal posters; Review JSON-LD for top-5 upvoted comments per deal.
    • RSS feeds: /feed.xml (latest 50) and /feed/nutrient/[slug] per-nutrient.
    • Newsletter signup with double opt-in: newsletter_subscription table, subscribeNewsletterAction, /api/newsletter/{confirm,unsubscribe}.
    • hreflang="x-default" added to sitemap and root layout alternates.
  6. 2026-04-29

    feat(observability): Sentry, request IDs, worker DLQ, health alerter

    Added

    • Sentry SDK (server, edge, client) with optional init via SENTRY_DSN. error.tsx and global-error.tsx capture exceptions.
    • Worker (@sentry/node) reports failed jobs.
    • proxy.ts attaches x-request-id header on every request; /api/health echoes it; loggerForRequest() helper for action-level correlation.
    • Worker dead-letter queue (price-tracker-dlq) parks jobs that exhaust 3 attempts with full payload + error.
    • scripts/health-alert.sh cron-friendly Telegram/Slack alerter with state file dedup; systemd .service + .timer (every minute).
  7. 2026-04-29

    feat(a11y/ux): PWA + skip-link + focus-trap + breadcrumbs + locale + plurals

    Added

    • PWA manifest with theme-color, 3 shortcuts; SVG icon set + ImageResponse-rendered apple-icon.
    • Skip-to-content link in [locale]/layout.
    • prefers-reduced-motion query disables thermo-pulse and shrinks all animations to 0.01ms.
    • useFocusTrap hook applied to mobile drawer + search dialog; restores focus on close.
    • Breadcrumb primitive on nutrient/brand/deal pages.
    • next-intl ICU plural messages (counts.deals, counts.comments, etc.).
    • SearchBar discriminated SearchResult: ok | rate_limited | unavailable.

    Fixed

    • Locale-aware formatPrice everywhere — removed 'en-GB' hardcodes from StackBuilder + ResolvedStack + SearchBar.
  8. 2026-04-29

    feat: wire half-built features — uploads, stacks, profile, GDPR, README

    Added

    • Submit form image upload via MinIO presigned URL with progress bar.
    • /stacks/[id] (public/private) and /stacks/explore gallery.
    • Profile edit UI (/profile/settings): name + email preferences toggles.
    • GDPR JSON data export + permanent account deletion (anonymises comments).
    • One-click unsave on /profile saved cards.
    • Full README rewrite (project intro, stack, scripts, layout, deploy).
  9. 2026-04-29

    chore(quality): Vitest + Playwright e2e, move mock-data, audit any types

    Added

    • Vitest setup with happy-dom, 41 unit tests across 6 files (cost-per-dose, SSRF, affiliate, filters, blur, reputation tiers).
    • Playwright e2e (11 specs × chromium + iPhone 14): hero, locale switcher, search, JSON-LD assertion, auth-redirects, 404.
    • CI extended with vitest + e2e jobs (Postgres + Redis + Meili services, chromium + webkit).

    Changed

    • mock-data.ts moved from src/lib/ to scripts/seed-data.ts — out of the app bundle.
  10. 2026-04-29

    feat: UX polish — sitemap split, blur, verify banner, notifications, compare, rep badges, countdown, optimistic comments

    Added

    • Sitemap split into static / nutrients / brands / deal-paged segments scaling to 100k+ deals; /sitemap-index.xml index.
    • Image blur placeholder (leaf→cream shimmer SVG) on deal cards + hot strip.
    • Email verification banner in [locale]/layout.
    • /notifications aggregated feed (comments, replies, price drops, vote milestones).
    • Category chip filter on homepage (vitamin/mineral/omega/…).
    • /compare?ids=… view with Best-value highlight.
    • 5-tier ReputationBadge (Newcomer → Legend).
    • Live ExpiresCountdown (1s/30s/60s tick depending on remaining time).
    • Optimistic comment posting via useOptimistic.
  11. 2026-04-29

    feat: production-readiness — pagination, skeletons, streaming, deploy, CI

    Added

    • "Load more" pagination via ?show=N URL param (24..240).
    • loading.tsx route segment fallbacks + Skeleton primitives.
    • Suspense around HotStrip and Comments — shell streams while DB queries finish.
    • /api/health endpoint (postgres + redis + meili pings).
    • pino structured logger with redact list; worker + scheduler converted from console.log.
    • scripts/backup-postgres.sh (pg_dump + gzip + S3 SigV4 upload + retention).
    • VPS deploy: Dockerfile + Dockerfile.worker + Caddyfile + systemd units + PM2 ecosystem + deploy README.
    • GitHub Actions CI: typecheck + lint + tests + build with Postgres/Redis/Meili services.
    • DeepL Pro translation refresh script.
  12. 2026-04-29

    feat: wire half-broken UI — saves, votes, stacks, profile, mobile, footer, errors

    Added

    • toggleSavedDealAction + SaveButton client (optimistic).
    • voteOnCommentAction + CommentVoteRow with three-state click.
    • saveStackAction + Stack builder save UI; ?nutrients=… URL preload for shareable stacks.
    • /profile (auth-gated): saved deals, my stacks, recent comments.
    • MobileNav drawer + dedicated mobile search sheet.
    • Footer pages: /about, /how, /guidelines, /privacy, /terms, /affiliate.
    • not-found.tsx per locale, error.tsx per segment, global-error.tsx root fallback.
  13. 2026-04-29

    security: SSRF, open redirect, rate limit, CSP, image host whitelist

    Added

    • assertSafeUrl() blocks file://, javascript:, credentials, localhost, RFC1918, AWS metadata 169.254.169.254, IPv6 loopback, link-local; DNS lookup rejects hosts that resolve to private IPs.
    • /go/[dealId] validates target host against active store domains (cached 5 min).
    • Redis token-bucket rate limiting on vote/comment/report/submit/extract/search/upload.
    • CSP + HSTS + X-Frame-Options + Referrer-Policy + Permissions-Policy + COOP headers.
    • next/image.remotePatterns switched from wildcard ** to explicit list.
  14. 2026-04-29

    feat: Level 3 — SEO, admin, uploads, email, queues, analytics, telegram

    Added

    • robots.txt, sitemap.xml with hreflang × 7 locales, per-page metadata + canonical.
    • Organization, WebSite, Product+Offer, BreadcrumbList JSON-LD.
    • Dynamic OG images (next/og ImageResponse) for home + per-deal.
    • Admin moderation: report + audit_log tables, role-gated /admin.
    • MinIO S3-compat container + presigned-URL upload action.
    • Resend email scaffolding (deal alert + weekly digest).
    • BullMQ price-tracker queue + worker + scheduler + weekly digest scripts.
    • Plausible/Umami self-hosted analytics integration.
    • Telegram bot webhook with /start, /link, /subscribe, /unsubscribe.
  15. 2026-04-29

    feat: Level 2 — affiliate, search, stack builder, real stub pages

    Added

    • Affiliate URL rewriting per store (Amazon, iHerb, Awin, CJ); /go/[dealId] click-tracking redirect.
    • MeiliSearch v1.13 container + sync script + 3 indexes; instant search dropdown with keyboard nav.
    • Stack builder: pick nutrients → cheapest deal per nutrient → daily/monthly cost.
    • Real /vouchers, /free, /discussions pages replacing stubs.
  16. 2026-04-29

    feat: Level 1 functionality — DB, auth, voting, comments, filters, submit

    Added

    • Drizzle ORM + Postgres 16 (15 tables), docker-compose, seed script.
    • Auth.js v5 with DrizzleAdapter, Google OAuth + Resend magic link.
    • Real voting (votes table, transactional temperature recompute).
    • Threaded comments with Zod-validated server action.
    • Filters wired to URL via searchParams; server-side filtering + pagination.
    • Submit deal form with generic OG/JSON-LD URL meta extractor.
  17. 2026-04-29

    feat: scaffold VitaminDB community deals platform

    Added

    • Next.js 16 App Router with Turbopack, output: 'standalone'.
    • next-intl v3 routing across 7 locales (EN/DE/ES/FR/PT/IT/NL).
    • Tailwind v4 design system (leaf/citrus/temperature palette).
    • Deal card grid + row layouts, thermometer pill, sticky header, sidebar filters, hot strip.
    • Mock data: 10 deals, 16 nutrients, 10 brands, 8 stores.
  18. 2026-04-28

    Initial commit