# Kasy App

Flutter app with Firebase backend — generated by kasy.

---

## Documentation

Full Kasy documentation lives at **[kasy.dev/docs](https://kasy.dev/docs)** — install, features, customization, publishing and troubleshooting, step by step.

This project also ships local guides (they work offline):

| Guide | Content |
|-------|---------|
| [docs/auth-setup.md](docs/auth-setup.md) | Enable Google, Apple and Facebook login |
| [docs/revenuecat-setup.md](docs/revenuecat-setup.md) | Enable subscriptions (RevenueCat) from test to production |
| [docs/ad_mobs.md](docs/ad_mobs.md) | Ads (AdMob) and verified rewards |
| [docs/ios-release.md](docs/ios-release.md) | Publish to iOS on Mac (`kasy ios`) |
| [docs/codemagic-release.md](docs/codemagic-release.md) | Publish without a Mac (`kasy codemagic`) |
| [docs/figma-workflow.md](docs/figma-workflow.md) | Figma → Flutter workflow for AI assistants |
| [docs/figma-guia.md](docs/figma-guia.md) | Step-by-step Figma guide (rebrand and screens) |
| [design/README.md](design/README.md) | Figma design system (Community + duplicate link) |

---

## Getting started

```sh
kasy run             # recommended — reads .env and picks the right keys
kasy run --ios       # iOS simulator
kasy run --android   # Android emulator
kasy run --web       # web at localhost:5555
```

Alternatives: `make run` or `flutter run` work too, but without the `kasy run` extras (automatic RevenueCat key selection, log at `.kasy/run.log`, update notice).

**Physical device via cable**
- iOS: connect iPhone → trust this computer → Xcode → Window → Devices → pair
- Android: Settings → Developer options → enable USB debugging

**Backend deploy** (when ready):

```sh
kasy deploy
```

---

## Keys and credentials

This project uses two types of credentials. Understanding the difference avoids confusion when configuring.

### App keys (stay in the project)

They live in the **`.env`** file at the project root (each key has an explanatory comment). `kasy run` reads the `.env` and injects the values into the build via `--dart-define`; Flutter reads them with `String.fromEnvironment()`. **Never go to the server.**

| Variable | Module | How to get |
|----------|--------|------------|
| `RC_TEST_KEY` | RevenueCat | RevenueCat dashboard → Apps → Test Store → key (`test_…`). **One key for both iOS+Android.** Auto-used on simulator/emulator. |
| `RC_IOS_PROD_KEY` | RevenueCat | RevenueCat dashboard → Apps → App Store → key (`appl_…`). Auto-used on physical iPhone (Sandbox and Production). |
| `RC_ANDROID_PROD_KEY` | RevenueCat | RevenueCat dashboard → Apps → Google Play → key (`goog_…`). Auto-used on physical Android. |
| `RC_WEB_API_KEY` | RevenueCat Web | RevenueCat dashboard → Apps → Web Billing → **production** key (`rcb_…`, not `rcb_sb_`) for release builds |
| `SENTRY_DSN` | Sentry | Sentry dashboard → Project → DSN |
| `MIXPANEL_TOKEN` | Mixpanel | Mixpanel dashboard → Settings → Token |

To update a key, edit the `.env` and run `kasy run` again.

### RevenueCat: `kasy run` picks the right key automatically

The CLI detects whether you're running on **simulator/emulator** or **physical device** and injects the right key:

| Where you run | Key used |
|---|---|
| iOS Simulator / Android Emulator | `RC_TEST_KEY` (test_) |
| Physical iPhone | `RC_IOS_PROD_KEY` (appl_) — falls back to `RC_TEST_KEY` if missing |
| Physical Android | `RC_ANDROID_PROD_KEY` (goog_) — falls back to `RC_TEST_KEY` if missing |

Force manually: `kasy run --rc=test` or `kasy run --rc=prod`. `--rc=auto` (default) applies the rule above.

- **Why the split?** Simulators can't run real in-app purchases against `appl_`/`goog_` — only RevenueCat Test Store works there. On physical devices, `appl_`/`goog_` covers both Sandbox and Production (the SDK detects the environment).
- **TestFlight and release:** use the production keys. **NEVER ship `test_` to the store** — the RevenueCat SDK crashes the app on release.
- **VS Code (F5 without kasy run):** `launch.json` defaults to `RC_TEST_KEY` (or production if test_ is missing). To switch manually, run via `kasy run`.

---

### Server secrets (stay in GCP Secret Manager)

Used by **Cloud Functions** at runtime. **Never in the app code.**

| Secret | Used by | How to get |
|--------|---------|------------|
| `REVENUECAT_WEBHOOK_KEY` | Subscription webhook | Dashboard RevenueCat → Webhooks → Authorization header |
| `META_ACCESS_TOKEN` | Meta Conversions API | Meta Business Manager → System Users → Token |
| `META_DATASET_ID` | Meta Conversions API | Meta Business Manager → Events Manager → Dataset ID |

To configure or update each secret:

```sh
firebase functions:secrets:set REVENUECAT_WEBHOOK_KEY --project=YOUR_PROJECT_ID
firebase functions:secrets:set META_ACCESS_TOKEN --project=YOUR_PROJECT_ID
firebase functions:secrets:set META_DATASET_ID --project=YOUR_PROJECT_ID
```

> Each command asks for the value interactively. The value **does not appear** in the terminal.

To see existing secrets:

```sh
gcloud secrets list --project=YOUR_PROJECT_ID
```

---

## Internationalization (i18n)

The app supports **3 languages**: English (`en`), Portuguese (`pt`), and Spanish (`es`).

### How the language is chosen

```
App opens
  ├─ Has language saved by user? → use saved
  └─ No → read device/browser language
            ├─ Is en, pt or es? → use that language
            └─ None of these → use default language (base_locale)
```

### Change default language (fallback)

When the user's device is in an unsupported language (e.g. Japanese, French), the app uses the **default language**. Default is English. To change to Portuguese:

**`slang.yaml`**
```yaml
base_locale: pt   # change here: en | pt | es
```

Then run:
```sh
dart run slang
```

### Add or edit translations

Files are in `lib/i18n/`:
- `en.i18n.json` — English
- `pt.i18n.json` — Portuguese
- `es.i18n.json` — Spanish

After editing any `.i18n.json`, always run `dart run slang` to regenerate `translations.g.dart`.

### Language selector

The user can change the language in **Settings → Language**. The choice is saved on the device and restored on next app open.

---

## RevenueCat webhook

The webhook receives purchase events (new subscription, renewal, cancellation) from RevenueCat.

**In RevenueCat dashboard:** Webhooks → add function URL → Authorization header = value of `REVENUECAT_WEBHOOK_KEY`.

---

## Deploy

```sh
# Full deploy (Functions + Firestore rules + Storage rules)
firebase deploy --only functions,firestore:rules,storage --project=YOUR_PROJECT_ID

# Functions only
firebase deploy --only functions --project=YOUR_PROJECT_ID
```

---

## Publish to iOS (App Store)

Full guide: [docs/ios-release.md](docs/ios-release.md)

```bash
kasy ios configure   # once — Apple credentials
kasy ios release     # build IPA and upload to App Store Connect
```

No Mac: [docs/codemagic-release.md](docs/codemagic-release.md)

---

## Security

`.gitignore` already excludes: `firebase_key.json`, `.env`, `.env.*`, `*.pem`, `*.keystore`, `.kasy/apple.env`, `.kasy/codemagic.env`, `.kasy/*.log`.

Never commit credentials to the repository.
