Document /r and /sticker short-link redirects in README

Neither route was mentioned anywhere despite predating this session (/r)
or being added this session (/sticker) — every other route/collection
this size gets its own section.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01G5mssdCBir9kyXTmqBjV3h
This commit is contained in:
Marco
2026-08-28 13:21:48 +00:00
parent 31e4f907f2
commit 33f3adb92c
+30
View File
@@ -1903,6 +1903,36 @@ one; a second `google-maps` row would collide on that name. To actually
use it: `<GoogleMapsEmbed src="<Google Maps embed URL>" title="..." />`
anywhere.
## Short links & QR redirects
`app/r/[code]/route.ts` and `app/sticker/[code]/route.ts` are static
short-link routes (e.g. printed on a flyer or a physical sticker's QR
code) that resolve a `code` against Payload's `redirects` collection and
307-redirect (`redirect()`, deliberately not `permanentRedirect()` — the
target can change at any time and this must never be client-cached) to
that doc's `targetPath`. Both routes call the same
`resolveAndTrackRedirect(code, urlPrefix)` in `app/lib/payload.ts`, which
also fire-and-forget PATCHes `clickCount`/`lastClickedAt` on every hit
(tracking failure only logs — never worth stranding a visitor over).
- **`/r/[code]`** is the default scheme for all new short links —
`einfach-produktiv.com/r/aktion-sommer`.
- **`/sticker/[code]`** exists only because a batch of physical stickers
was already printed as `einfach-produktiv.com/sticker/<code>` (`echt`,
`geheimnis`, `fokus`) before `/r/[code]` existed and can't be
reprinted — same collection, same lookup, just a second fixed prefix.
- The Redirects doc's `urlPrefix` field (`/r` or `/sticker`) isn't just an
admin label — `resolveAndTrackRedirect` filters on it too, so a code is
only reachable under whichever prefix its doc is actually set to.
Changing `urlPrefix` in Payload immediately changes which route serves
that code.
- Defense in depth: `targetPath` must start with `/` and not `//` (open-
redirect guard, same check `app/api/preview/route.ts` does), enforced
both in Payload's own field validation and again in each route.ts before
calling `redirect()`.
- A deactivated (`active: false`) doc — or no matching doc at all —
renders a plain 404 (`notFound()`), not a redirect to some fallback.
## Product image gallery
`ProductGallery.tsx` — main image + thumbnail strip, swappable on click OR