diff --git a/CLAUDE.md b/CLAUDE.md index 24b5fb3..18f4afb 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -86,6 +86,10 @@ All uploads are presigned/direct-to-storage — media bytes never pass through t Gated by path secret (see `proxy.ts` above) *and* by role at the tRPC layer: `src/trpc/routers/admin.ts`'s `assertAdmin()` allows either `ADMIN_OWNER_ID` (env-configured super-admin bootstrap) or an `AdminRole` row (`SUPER_ADMIN` / `MODERATOR`). Actions are written to `ModerationLog`. Pages live under `src/app/p/[secret]/{users,moderators,posts,reports,ads,referrals,…}`. +### Download redirect `/app` + +`src/app/app/route.ts` (public in `proxy.ts`) is the target for flyers/QR codes: Android → Play Store with sanitized `utm_*` passed as Play `referrer`, iOS → `APP_STORE_URL` in `src/lib/app-links.ts` once set (still `null` until the iOS release; until then the web start page), everything else → web start page; `?ref=` → `/r/`. Logic is pure in `src/lib/app-redirect.ts`; clicks are counted per day/source/platform in Redis (`appredirect:` hashes, `src/lib/app-redirect-stats.ts`) and shown in the admin referral overview. Redis on the NAS is the `pawfeed-redis` container (not `glitchtip-redis`), password in `docker/.env` `REDIS_PASSWORD`. + ### New-pet welcome & founding members `pets.create` fires `welcomeNewPet()` (`src/lib/new-pet-welcome.ts`) in the background — it must never block pet creation. It (1) sets `Pet.isFoundingMember` via one guarded SQL update for the first 250 pets by `createdAt` (never revoked; badge = Sprout icon next to the name, web + mobile), (2) lets the curator pet "PawFeed Team" (`ensureTeamPet` in `src/lib/team-pet.ts`) follow the new pet, and (3) sends a welcome DM via `sendTeamMessage`. (2) and (3) are switchable and the DE/EN text (mandatory `{name}` placeholder) is editable in the admin panel under "Begrüßung" (`/p/[secret]/curator`, `CuratorSettings` id = 1, `curator-admin.ts`). Replies to the welcome DM land in the admin "Messages" team inbox.