gote

A card-based learning game for iPhone and Android, built with Expo (React Native). It pulls your iNaturalist observations and quizzes you on the species you’ve seen.

Game modes

Plus a Lexicon (browse/search every species you’ve observed, filter by how well you know them, tap through to a detail page) and a Statistics page (lifetime accuracy, most-missed and best-known species).

How it works

  1. Enter an iNaturalist username in Settings (no password — it uses your public observations via the iNaturalist v2 API).
  2. Observations are downloaded once and cached locally; later launches sync only what changed.
  3. Common names can be shown in any of iNaturalist’s languages (the app UI stays in English).

Running it on your phone

Most of the app runs in the Expo Go app:

  1. Install Expo Go (App Store / Play Store).
  2. Start the dev server from this folder:
    npm start
    
  3. Scan the QR code — iPhone via the Camera app, Android from inside Expo Go. (Phone and computer must be on the same Wi-Fi; otherwise npx expo start --tunnel.)

For a standalone build on a device, this is a CNG project — run npx expo prebuild then npx expo run:ios (or run:android).

Tests

Pure logic (gestures, cache/sync, quiz, lexicon) is unit-tested:

npm test

Project layout

App.js                       # screen state machine + data orchestration
index.js                     # Expo entry point
src/
  api.js                     # iNaturalist v2 API client + helpers
  storage.js                 # AsyncStorage: username, stats, prefs, obs cache
  cache.js                   # local photo-cache size / clear (expo-file-system)
  prefetch.js                # preloads upcoming card images
  quiz.js                    # multiple-choice distractor logic (pure, tested)
  lexicon.js                 # Lexicon filtering/status logic (pure, tested)
  gestures.js                # gesture decision helpers (pure, tested)
  theme.js                   # colors + monotone icon mapping
  components/                # Icon, ScreenHeader, PhotoViewer
  screens/                   # Menu, Study, PickImage, Custom, Settings,
                             #   Results, Stats, Lexicon, Detail
  hooks/                     # (none currently)
scripts/                     # node test runners (npm test)
assets/                      # app icon + splash (placeholder green)

Notes & next steps

Crash reporting

Errors are reported via Sentry — but only when a DSN is configured. Set it in app.jsonexpo.extra.sentryDsn (or the SENTRY_DSN env var). With no DSN, Sentry is a no-op, so it stays silent in Expo Go and local dev. Reporting is crash/error-only (no performance tracing, no PII).

The @sentry/react-native config plugin is intentionally not enabled yet — it adds a build step that uploads source maps to Sentry, which fails without a Sentry org + auth token. Re-add "@sentry/react-native" to expo.plugins once you’ve set up the account and a SENTRY_AUTH_TOKEN (so crash stack traces map back to source). Until then, errors are still captured; their traces just point at the minified bundle.

License

Copyright (C) 2026 turbolya.

Licensed under the GNU Affero General Public License v3.0 — see LICENSE. You may use, modify, and share this code, but any derivative work or networked service built from it must also be released in full under the AGPL-3.0. It may not be incorporated into closed-source or proprietary software.

One additional permission applies, in LICENSE-EXCEPTION: the app may be distributed through the Apple App Store, Google Play and comparable platforms despite the store terms that would otherwise conflict with the AGPL-3.0 (device limits, store-signed binaries). It covers distribution only — every copyleft obligation above stays in force.

Contributions are accepted under the AGPL-3.0 plus that permission, so it keeps covering the whole work as the codebase grows — see CONTRIBUTING.md.