Skip to content

Changelog

Changelog

Curated highlights of recent releases. For complete API versions and the breaking-change policy, see the API versioning & LTS policy.

Detailed changes for individual endpoints: OpenAPI spec and interactive API reference.


2026-04 · Per-code dashboard analytics

  • Dashboard: The Analytics button in the QR code list now opens the statistics page for the selected QR code at /dashboard/codes/{id}.
  • Routing: The /dashboard/codes alias still redirects to /dashboard, but it no longer catches detail routes such as /dashboard/codes/{id}.
  • API: The detail page loads the QR code directly via GET /v1/codes/:id, so it no longer depends on list pagination limits.
  • Tests: Regression tests cover the alias redirect and direct code loading.

2026-04 · Dashboard delete dialog for QR codes

  • Dashboard: The trash button in the QR code list now opens a custom React dialog instead of a native browser popup.
  • Feedback: After deletion, a toast reports success or failure.
  • Tests: packages/dashboard/tests/dashboard.test.ts prevents regressions back to confirm() in the QR code delete flow.
  • Dashboard: Short codes in the QR code list are now directly clickable external redirect links. The external-link icon next to e.g. wu3qaa opens https://qr3.app/{shortCode} in a new tab.
  • i18n: Added German and English tooltip copy.
  • Tests: packages/dashboard/tests/dashboard.test.ts protects the link href, new-tab behavior, noopener noreferrer, and icon against regressions.

2026-04 · Redirect Worker route for dynamic QR codes

  • Fix: Dynamic QR codes at https://qr3.app/{shortCode} are handled by the Redirect Worker again. The production route now uses qr3.app/* because Cloudflare Worker routes do not support :code path parameters.
  • Hardening: Non-matching paths pass through to the landing origin, so regular pages like /en/pricing are not blocked by the Redirect Worker.
  • Tests: packages/redirect/tests/unit/redirect.test.ts covers the wildcard route, short-code handling, and origin pass-through.

2026-04 · Workspace-wide DPP scan overview (Q3.4.2)

  • New: GET /v1/workspace/stats/dpp?days=30 — aggregates all dpp_scans for the API key’s workspace (active_dpps, scans_by_day, top_dpps with product name/category).
  • Dashboard: Home card (/dashboard) with a 30-day bar chart + top lists — shown alongside QR code cards.
  • Public: Marketing short link GET /dpp/dpp_<id> (single path segment) for live demos, alongside /dpp/{gtin}/{serial}.

2026-04 · DPP scan analytics (Q3.4.1)

  • New: GET /v1/dpp/:id/stats?days=30 — aggregated scans of the public GS1 resolver per DPP. Fields: total_scans, period_scans, scans_by_day, top_countries, top_devices, top_representations.
  • New: dpp_scans table (migration 0011) — separate from scans (redirect worker). IP addresses are hashed with a daily rotating salt; raw IPs never reach D1.
  • Dashboard: mini-chart card (SVG, no chart library) on /dashboard/dpp/:dppId with 30-day bars + top-3 breakdowns. Empty-state while a DPP is live but has no scans yet.

2026-04 · Live EU compliance simulator (Q3.3.7)

  • New: POST /v1/dpp/:id/validate-update — simulates partial updates stateless (status, market list, …) without persistence. The response contains eu_compliance + preview.changed_fields.
  • Dashboard: simulator card on the DPP detail page (/dashboard/dpp/:dppId) — chips for DE/AT/FR/IT/ES/NL + custom, status dropdown, Preview EU impact / Save changes / Reset. Non-blocking via Remix useFetcher.
  • Hardening: extracted simulator helpers (readUpdatePatchFromForm, marketCountriesKey) + 18 new unit tests; bugfix: lone non-ISO input no longer clears the market list.

2026-04 · Live EU compliance preview in the create form (Q3.3.6)

  • Changed: POST /v1/dpp/validate now also returns eu_compliance — the same validator as GET /v1/dpp/:id/eu-compliance, stateless before save.
  • Dashboard: preview under the existing validation panel + new save-guard banner above the submit buttons when errors/warnings remain (i18n pluralization DE/EN).

2026-04 · EU validator + textile UI (Q3.3.4 + Q3.3.5)

  • New: EU compliance validator with 5 textile rules (TEXTILE_AGEC_REQUIRED, TEXTILE_MICROPLASTICS_CONSISTENCY, TEXTILE_SVHC_THRESHOLD, TEXTILE_GREENWASHING, TEXTILE_ESPR_READY).
  • New: GET /v1/dpp/:id/eu-compliance with compliant / espr_ready / issues[] / summary.
  • Dashboard: EU compliance section on the DPP detail page (summary tiles, grouped issue cards, ESPR-ready badge in the header).

2026-04 · Textile DPP schema (Q3.3.1–Q3.3.3)

  • New: textile category with AGEC mandatory chain (weaving/knitting → dyeing/printing → assembly), per-fiber origin_country + recycled_pct, svhc_substances[], ESPR opt-in (PEF, lifetime, recyclability).
  • New: base field market_countries: string[] (ISO 3166-1 alpha-2) across all DPP categories — drives FR-specific AGEC rules and the French consumer mandatory notice.
  • New: consumer HTML template with AGEC microplastics warning box, 3-step origin chain (flag pills), SVHC list, durability and recyclability sections.
  • Migration: 0010_dpp_market_countries (D1).

2026-04 · DPP bulk import (Q3.2.1–Q3.2.5)

  • New: POST /v1/dpp/import accepts CSV and XLSX (Worker-compatible via SheetJS xlsx, ~283 KB gzip bundle).
  • Scaled: plan-based limit (Free 100 → Enterprise 10k) + chunked db.batch() of 100 + 5 MB body limit.
  • New: error report as CSV in the errors_csv field of the 201 response; GET /v1/dpp/import/templates/:category?format=csv|xlsx returns ready-made templates for battery and textile.
  • Dashboard: drag-and-drop upload at /dashboard/dpp/import with template proxy and inline CSV download.

Non-breaking — LTS additions

All of the above are additive:

  • Existing POST /v1/dpp/validate clients can ignore the new eu_compliance field without changes.
  • Existing battery flows are unchanged.
  • market_countries is optional and defaults to [].

See API versioning for the breaking-change policy.