README still said "no EAS Build has been run yet" — the app has since
gone through several production builds and is now live on Google Play
(closed testing). Also documents the new eas update / EAS Update
workflow for shipping JS-only fixes without a new store review,
closing out Gitea #35's last remaining task item.
- explore.getTrending posts are now interleaved into the chronological
Feed at semi-random intervals (src/lib/interleave-trending.ts),
marked with a small "Trending" badge on PostCard — a lightweight
stand-in for web's separate Explore "Trending" tab, which mobile
wasn't going to get as its own screen. No backend change: reuses the
existing explore.getTrending procedure as-is.
- update app icon / splash / favicon / Android adaptive-icon assets
(user-provided)
- README: correct the now-stale Dark Mode "not yet converted" list
(Explore/Notifications/pet profile/health were converted in the
found.md batch) and document the report/date-format/pinch-zoom/
legal-links fixes
- i18next + react-i18next + expo-localization: device-locale detection,
an MMKV-persisted DE/EN/Automatisch override (mirrors web's cookie-only
locale, no backend field needed), and a language switcher on the Pets
tab next to the theme toggle
- every screen and shared component converted from hardcoded German
strings to translation keys; de.json/en.json kept in exact key-parity
(218 keys each, verified programmatically)
- backend: src/trpc/init.ts now accepts an x-locale header as a fallback
locale source (cookie still wins, web unaffected) since mobile has no
cookie jar to set NEXT_LOCALE in; mobile's tRPC client sends the
current language on every request
- fixes a latent bug: species/breed pickers were hardcoded to locale
"de" while every other pet query resolved names via ctx.locale's
default (English, since mobile never sent a locale cookie) — both now
use the same current-language value
- expo-localization is a new native module (config plugin) and needs a
native rebuild to actually link; deviceLocale() falls back to English
instead of crashing when it isn't linked yet, so the app stays usable
before that rebuild happens
Needs a NAS deploy (src/trpc/init.ts is shared backend code) before the
x-locale fallback and the species/breed locale fix take effect for mobile.
- 5-step onboarding (guidelines, upload consent, spider opt-in, pet
creation, avatar) that gates first launch until a pet exists
- Add/delete pet flows on the Pets tab, with a shared OptionPicker
(ScrollView-based, not FlatList, to avoid nested-VirtualizedList
warnings inside onboarding's outer ScrollView)
- App-wide light/dark/auto theme via ThemeContext, synced with the
existing owner.getThemePreference/setThemePreference backend
procedures; core navigation chrome, Feed, Pets tab, and shared
primitives (Button, TextField, Card, PetAvatar, PostCard, StoryTray)
converted to the makeStyles(colors) pattern
- found.md fixes: safe-area insets on image/story viewers so controls
clear the status bar, auto-mark-all-read on the notifications tab,
and an Explore species/breed filter
sign-in.tsx only ever covered login (per its own comment "sign-up screens
are follow-up work"). Adds the other half: email/password sign-up using
Clerk's Futures API (signUp.password() -> verifications.sendEmailCode()/
verifyEmailCode() -> finalize()), mirroring sign-in.tsx's two-step
credentials/verify shape. No invite-code step, since INVITE_REQUIRED is
globally off on the backend since launch.
Verified live on the Android emulator: real Clerk validation surfaces
correctly (breached-password rejection), and a valid submission correctly
sends a verification email and transitions to the code-entry step.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Push notifications went from "wired but not deliverable" to fully working
end-to-end this session. Records the three separate one-time setup pieces
(EAS project id, FCM credentials baked at prebuild time, and the FCM V1
vs. Legacy service-account-key slot mixup that produced a confusing
"Unable to retrieve the FCM server key" error) so a future session doesn't
have to rediscover them.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Health: consent gate (Art. 9 DSGVO) plus weight/vet-visit/vaccine log
sections, gated behind health.getConsentStatus like the web app.
Milestones: view a pet's milestone posts and create the 5 user-initiated
types with an optional photo. Messaging: chat detail/compose screen
(messages/[conversationId].tsx) polling while focused, reachable from the
conversations list and from a pet profile's new "Nachricht" entry point.
Push: usePushNotifications requests permission and registers the Expo
push token with owner.registerPushToken; real delivery still needs an EAS
project id (`eas init`), tracked in the README.
All four verified live on a real Android emulator: health CRUD (add/list/
delete a weight log), Health/Milestones/Nachricht entry points gated
correctly by own-pet vs. other-pet, and full chat history loading via an
existing conversation.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Story tray/creation/viewer with PawRing seen/unseen indicator, expo-video
playback for VIDEO posts (replacing the static placeholder), and a
pets/people/hashtags search screen reachable from the Explore tab header.
Extracts FollowButton from the pet-profile screen since search results
need the same follow/unfollow toggle.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Moves the mobile app from a connectivity scaffold to a real Phase 1 app:
- Migrate off Expo Go onto a local custom dev client (expo-dev-client,
built via expo prebuild + expo run:android against the local Android
SDK — no EAS account needed). Needed because react-native-mmkv requires
native code Expo Go doesn't ship.
- Persisted, MMKV-backed TanStack Query cache (PersistQueryClientProvider)
plus expo-image, so a relaunch renders the last-known feed/pets/
notifications instantly instead of a blank screen while refetching.
- ActivePetContext: every pet-scoped procedure requires an explicit petId
server-side (no server-side "current pet"), ported from web's
ActivePetContext, MMKV-backed instead of localStorage.
- Bottom Tabs (Feed/Explore/Notifications/Pets) mirroring the web app's
actual mobile nav, with Messages as a header button rather than a tab
(matches web). Feed, PostCard, PawButton reactions, pet discovery grid,
notifications list, and a conversations list are all wired to the real
backend and verified against the live database.
- Design tokens/components extended with PostCard/PawButton/PetAvatar/
PetIdentityBadges, all styled from the existing src/theme/tokens.ts.
- Fixed a react/react-dom version mismatch surfaced along the way, and
handle Clerk's needs_client_trust (Device Trust) sign-in status with an
email-code step.
Verified end-to-end in the Android emulator against pawfeed.org: feed
scrolls and paginates with real posts/images, paw reactions toggle
optimistically and persist, pet switching updates every screen, and
notifications/explore show live data.
Connectivity + auth scaffold only: Expo Router, Clerk session auth via
expo-secure-store, and a type-only tRPC AppRouter import from the web
app's router — no backend changes needed. See mobile/README.md.