Changelog

1.5.0 — Content, accessibility, performance & test batch

  • SEO: +12 long-tail strategy articles (18→20 posts incl. originals), new /guides hub, blog renderer
  • now supports bold/links/bullets, per-post canonical + OG/Twitter, "Keep reading" block.

  • Accessibility: global :focus-visible ring + reduced-motion; labels/aria on all form inputs; real
  • <form> semantics; role=alert/status on async messages; accessible names on icon buttons; nav/footer/

    consent landmarks labelled.

  • Performance: footer uses client-side next/link; confirmed no <img> and consent-gated scripts.
  • Bug fix: trade calculator coerces NaN/undefined options and asset values to safe numbers.
  • Tests: TS 44→60 (trade calculator, trade finder, rate limiter, magic-token edge cases).
  • Docs: go-live-runbook.md; counsel-review banner on /privacy and /terms.
  • 1.4.0 — Rebrand to Dynasty Cheat Code

  • Renamed product "Dynasty GM" → "Dynasty Cheat Code" across copy, metadata, legal, email, demo.
  • Renamed identifiers: package name, demo file, D1 db name, placeholder fallbacks.
  • Legal contact/company/jurisdiction: Dynasty Cheat Code, dynastycheatcode@gmail.com, State of Ohio.
  • Verified tests, typecheck, Python tests, build, npm audit (0).
  • 1.3.0 — Next 16 security upgrade

  • Upgraded Next.js to 16.2.9; React to 19.2.7.
  • Cleared all npm audit advisories; `npm audit` now reports 0 vulnerabilities.
  • Migrated async Next APIs (cookies/params/searchParams) for the Next 16 build.
  • Verified tests, typecheck, Python engine tests, and production build.
  • Temporary: lint aliases typecheck pending ESLint 9 flat-config migration.
  • 1.2.0 — Stripe/subscription teardown + launch hardening

  • Removed Stripe and subscriptions entirely: `Subscription` model dropped from both Prisma schemas,
  • `stripe` dependency removed, `/api/stripe/*` routes return 410, billing UI and payment SDK stubbed.

    Session/auth no longer reference paid status.

  • Scrubbed all remaining subscription/Stripe language from `/privacy`, `/terms`, `README.md`,
  • `docs/production-launch.md`, and `docs/deployment.md` (now reflect "free, ad-supported, no payments").

  • Added `docs/security.md`: records the Next.js audit decision (stay on patched 14.2.35 with
  • image-optimizer mitigation in `next.config.js`; Next 15/16 major upgrade flagged as a pre-scale,

    build-validated task) and rate-limiter guidance (swap the in-memory limiter for a shared store like

    Upstash before enabling public email at scale).

  • Expanded curated comparisons from 5 to 20 high-intent matchups across RB/WR/QB/TE plus pick-vs-player
  • (hand-picked, not auto-generated). All resolve against the dataset.

  • Verified: tsc 0 errors, 44 TS tests, 37 Python tests.
  • 1.1.0 — SEO content expansion (player pages, comparisons, pick hubs)

  • Player pages upgraded: structured answer blocks near the top (best for contenders / rebuilders /
  • Superflex / market gap / risk), 1QB + Superflex + SF-TE-Prem values, buy/sell/hold with note,

    contender-vs-rebuilder advice, position rank (overall + positional), similar players, and links to

    rankings/calculator/compare/buy-sell-hold/trade-value-chart.

  • Curated comparison system: `/compare/[slug]` for Bijan vs Gibbs, Nabers vs MHJ, Jefferson vs
  • Chase, Daniels vs Caleb, and a 2026 first vs young player — each with a verdict + answer blocks.

    `/compare` now lists featured matchups above the build-your-own tool.

  • Pick-value hubs: `/values/2026-rookie-picks`, `/values/future-first-round-picks`,
  • `/values/early-vs-late-first` with value tables + guidance.

  • Index control: player pages, comparisons, and value hubs added to the sitemap; per-user/dynamic
  • pages (`/account`, `/league/*`) set to noindex and disallowed in robots.

  • New helpers (`answerBlocks`, `positionRank`, `similarPlayers`, comparisons) with tests
  • (44 TS tests). tsc 0 errors; 37 Python tests.

    1.0.0 — Pivot to a free, ad-supported site

  • Removed the subscription model from the product. `/pricing` now redirects to a new **/support**
  • page ("the site is free; ads keep it running; optional tip later"). No plan tiers anywhere.

  • Removed all paid gates: trade finder shows **all** partners (no "Unlock Pro" overlay); saving a
  • league is a **free** convenience (sign-in only, no 402). Dropped `userIsPaid` gating from flows.

  • Nav/home/footer/account de-emphasize payments: no upgrade buttons, no subscription concept.
  • Account = optional sign-in + saved leagues only. Stripe code remains but is dormant/unsurfaced.

  • Home + rankings + player pages messaged as free; added internal links (tools ↔ rankings ↔
  • players). Ads stay consent-gated + env-configured; player pages stay in the sitemap.

  • Legal: Terms billing section rewritten for a free service; sitemap `/pricing` → `/support`.
  • Docs repositioned: product-spec (free ad-supported toolkit), launch-checklist (SEO/AdSense/
  • content), production-launch (Stripe/email/accounts marked optional), README.

  • Preserved: pick valuation, franchise value, coverage/confidence, stud-tax calculator,
  • consent-gated scripts, player metadata/sitemap. tsc 0 errors · 37 TS · 37 Python tests.

    0.16.0 — Pre-launch security & monetization hardening

  • Deps: upgraded Next to 14.2.35 (patched line), dropped the wrangler/miniflare toolchain
  • (Cloudflare-alt via npx), bumped vitest 4 + nodemailer 9 + postcss 8.5; `npm audit` 12 -> 1

    (the lone residual is an anomalous Next image-optimizer advisory, mitigated via remotePatterns).

  • Auth: `AUTH_SECRET` now REQUIRED in production (no dev-fallback secret); added IP+email rate
  • limiting (5 / 15 min) on `/api/auth`. New rateLimit + existing magic tests (37 TS tests).

  • Stripe: checkout now upserts the Subscription row before attaching `stripeCustomerId`.
  • Pro gating: saving leagues is now paywalled server-side (402 + upgrade prompt) — Pro claim is real.
  • Legal: removed draft/placeholder banners; `/privacy` + `/terms` finalized and configurable via
  • `NEXT_PUBLIC_COMPANY_NAME` / `_CONTACT_EMAIL` / `_GOVERNING_LAW` (still pending counsel sign-off).

  • Next image config hardened (single trusted remotePattern, no SVG).
  • 0.15.0 — Review fixes: build blocker, franchise value, consent, ads, player SEO, saved leagues

  • Fixed the production build blocker: `SleeperUser.metadata` typed; `tsc --noEmit` is clean (0 errors).
  • Power rankings now rank by **franchise value (roster + picks)**; classification "total" uses it
  • too, so pick-rich teams rise. New Franchise/Roster columns (TS + Python engines + demo).

  • Analytics + AdSense scripts now load only **after consent** (`ConsentedScripts`), not on page load.
  • AdSlot maps named placements to env slot IDs and renders real units only when client + slot + consent.
  • Player pages get per-player metadata/canonical/OG + `generateStaticParams`; sitemap now includes
  • every `/players/[id]`.

  • Saved leagues are real: `/api/league/save` persists via `importLeague`, a Save button on the
  • dashboard, and the account page lists them. Pricing copy aligned ("on-demand re-analysis").

    0.14.0 — Production Postgres (one command)

  • Hosted-Postgres path without breaking local SQLite dev. `scripts/make-postgres-schema.mjs`
  • derives `prisma/schema.postgres.prisma` from the SQLite `schema.prisma` (only the datasource

    differs + `directUrl`), so the two never drift.

  • One-command prod DB setup: `npm run db:setup:pg` (derive schema -> generate -> db push ->
  • seed). Also `db:push:pg`, `db:migrate:pg` (migration-history path), and `vercel-build`

    (derive + generate Postgres client + next build).

  • `.env.example` documents pooled `DATABASE_URL` + `DIRECT_URL`; `docs/production-launch.md`
  • DB step is now "set DATABASE_URL/DIRECT_URL -> `npm run db:setup:pg`". Seed unchanged (no

    SQLite-specific code).

    0.13.0 — SEO content batch + production launch guide

  • New indexable tool pages: /trade-value-chart (200+ players, all formats, server-rendered),
  • /buy-sell-hold/[position] (QB/RB/WR/TE hubs), /startup-draft strategy landing; refactored

    /buy-sell-hold hub. All with metadata/canonical/OG and internal links; sitemap + footer wired.

  • Five new substantive strategy articles (startup 1QB vs SF, valuing rookie picks, when to
  • rebuild, buying a contender window, finding trade partners) — auto-indexed via the blog reader.

  • `src/lib/data/seo.ts` shared helpers (tradeValueRows, playersByCall) + 2 tests (35 TS total).
  • `docs/production-launch.md`: complete self-serve Vercel + Postgres + Stripe + email + OAuth +
  • AdSense launch walkthrough with env table, build gate, smoke tests, and flagged decisions.

    0.12.0 — Launch blockers: email delivery + legal pages

  • Magic-link email now actually sends: `src/lib/email/mailer.ts` supports Resend (HTTP, no dep)
  • and SMTP (optional nodemailer), behind env vars, with a dev fallback that returns the link.

    Templated HTML+text email. 5 mailer tests (template, provider detection, Resend success/error,

    not-configured). `/api/auth` sends on request; docs + .env.example updated.

  • Privacy Policy and Terms of Service replaced with complete, usable draft copy for a
  • fantasy-sports SaaS (accounts, cookies/analytics, AdSense/ad partners, Stripe, GDPR/CCPA

    rights, retention, contact) — each flagged as needing counsel review before AdSense submission.

  • Verified: 95 files parse, 33 TS tests, 37 Python tests.
  • 0.11.0 — Trade smarts, hardened auth, SEO/monetization

  • Trade calculator: stud-tax (value-concentration) so one elite beats a pile of mediums, plus
  • stud-tax and pick-discount sliders; shows effective vs raw value. Trade finder: "why they say

    yes", lineup impact, and an offer ladder (aggressive / fair / smash accept).

  • Auth: replaced the unverified instant email sign-in with a verified, time-limited HMAC
  • magic-link flow (request -> emailed link -> verify -> session). Google OAuth kept. 4 new tests.

  • SEO/monetization: consent banner, env-gated analytics + AdSense, OG/canonical metadata,
  • /privacy, /terms, and indexable /compare + /buy-sell-hold tool pages; sitemap expanded.

  • 28 TS + 37 Python tests pass.
  • 0.10.0 — Real future picks + coverage confidence (Priority 1)

  • League analyzer now values future rookie picks: default ownership reconciled with Sleeper
  • traded_picks, each pick valued by round + original owner's projected slot, discounted by

    years out. Fixes contender/rebuilder calls that ignored draft capital.

  • Per-team player coverage % + confidence label (High/Medium/Low) and not-yet-valued list,
  • surfaced on the dashboard so thin-coverage teams are flagged. 3 new pick-value tests (22 TS).

    0.9.2 — Soften SF TE Premium TE boost

  • Reduced the TE-premium multiplier so elite TEs rise toward — not above — the elite QB/WR
  • tier, matching ETR's SF/TE-Prem ordering (top-150 Spearman ~0.88). Synced TS port.

    0.9.1 — Format: TE Premium -> SF TE Premium

  • Renamed the TE-premium format to **SF TE Premium** (Superflex + TE-premium), matching
  • ETR's "SF/TE Prem" column: QBs now get the Superflex boost AND elite TEs the TE-premium

    boost in this format. Updated engine, TS port, labels, route (old URL redirects), Sleeper

    format detection, and calibration (SF_TE_PREMIUM vs ETR SF/TE-Prem ~0.88).

    0.9.0 — Tight ETR calibration

  • Reworked the consensus anchor (auction shape + rank-fairness blend) and engine weights so
  • our board closely tracks ETR: Spearman ~0.95 (1QB) / ~0.91 (Superflex) across the top 150.

  • 1QB top-7 now matches ETR exactly; Superflex correctly leads with QBs then elite WR/RB.
  • FantasyCalc now supplies only the 30-day trend (risers/fallers); values stay on one
  • consistent ETR-anchored scale. Differences from ETR are small, intentional model nuances.

    0.8.0 — Calibrated to consensus realism (326-player board)

  • New ~326-player dataset built from ETR public facts (`build_dataset_from_etr.py`); ETR
  • ordering/auction used as a calibration target + market anchor (owner-directed), NOT shipped

    as our values. `scripts/calibrate.py` reports rank correlation.

  • Engine recalibrated: softer age decay, market-anchored blend, tiered Superflex QB multiplier.
  • Spearman vs ETR ~0.79 (1QB) / ~0.83 top-150 (Superflex); top boards now look realistic.

  • Demo runs on the full 326-player board. 37 Python + 18 TS tests pass.
  • 0.7.0 — Validation, trust doc, one-command refresh

  • `backtest.py`: honest validation of buy/sell/hold vs real 30-day market trend. Finds the
  • model is contrarian to momentum (corr -0.17) — expected for a value model; surfaced in the

    demo and documented (not spun as a win). 3 new tests.

  • `docs/trust-and-validation.md`: data provenance (real vs seeded), validation result, limits.
  • One-command refresh: `npm run data:full` (scripts/refresh_all.sh) and `npm run data:demo`.
  • 0.6.0 — 30-day trend + real production feed

  • 30-day market trend (FantasyCalc) surfaced as risers/fallers on the home page and in each
  • player drawer; captured in the snapshot + `ingest_market.py`.

  • `ingest_sleeper_stats.py`: real season PPG/usage from the free Sleeper stats endpoint,
  • joined by Sleeper id; `build_player_inputs.py --sleeper-stats` merge; weekly workflow wired.

    0.5.0 — Real market values (trustworthy buy/sell/hold)

  • `ingest_market.py` pulls free public FantasyCalc dynasty values; joined by Sleeper id
  • and aligned to the engine scale. Buy/sell/hold is now genuine model-vs-market signal

    (e.g. SELL aging RBs the market overpays for, BUY productive young QBs).

  • `build_player_inputs.py --market` merge; weekly workflow + demo now use real market.
  • Demo player drawer shows a Model-vs-Market comparison.
  • 0.4.0 — Product polish + bigger data

  • Expanded to 65 valued players with believable, calibrated buy/sell/hold spreads.
  • New design system (gradient cards, position colors, value bars, pills) applied to the
  • Next app and a fully rebuilt, interactive standalone demo (player radar, compare tool,

    charts, 8-team league analysis, trade finder).

  • `scripts/build_demo.py` regenerates the demo from engine output.
  • 0.3.0 — DB switch + automation

  • `getDb()` helper auto-selects SQLite (local) or Cloudflare D1 (production); all API
  • routes + lib refactored to use it. Clean `npm install` (dropped the next-only build dep).

  • GitHub Actions: CI (Python + TS tests + typecheck) and a weekly value-refresh workflow
  • (nflverse + Sleeper -> engine -> commits values.json).

  • Standalone interactive demo (`dynasty-gm-demo.html`) powered by real engine output.
  • 0.2.0 — Real data, OAuth, Cloudflare

  • nflverse stats ingestion (`ingest_nflverse.py`) -> real PPG/usage; merged by
  • `build_player_inputs.py` for full-league coverage.

  • Google OAuth sign-in (manual flow) reusing the session cookie; email fallback kept.
  • Cloudflare Pages + D1 wiring: `wrangler.toml`, driverAdapters, `src/lib/db/d1.ts`,
  • deploy/migrate scripts, full deployment guide.

    0.1.0 — Initial build

  • Original dynasty value engine (veterans + rookies) in Python, fully tested.
  • Format adjustments: 1QB, Superflex, 2QB, TE-premium, lineup depth.
  • League analyzer: 8 team directions with strengths/weaknesses/recommendations.
  • Trade finder: window-aware partners, targets, sells, packages.
  • Next.js app: rankings, player pages, trade calculator, Sleeper import,
  • league dashboard, trade finder, rookies, rookie draft, pricing, account.

  • Auth (email session) + Stripe checkout/webhook/portal + paid gating.
  • Blog/SEO, waitlist, feedback, changelog, sitemap.