# R&D: a fastlane importer and a RevenueCat adapter Two questions for after desktop D3. Facts come from the official docs linked in each section; the recommendations are ours. ## 1. `storebound import fastlane` **What fastlane keeps on disk** - **deliver (App Store)**, under `fastlane/metadata/` ([docs.fastlane.tools/actions/deliver](https://docs.fastlane.tools/actions/deliver/)): - One folder per language: `name.txt`, `subtitle.txt`, `description.txt`, `keywords.txt`, `promotional_text.txt`, `release_notes.txt`, `support_url.txt`, `marketing_url.txt`, `privacy_url.txt`. - Non-localized files at the root: `copyright.txt`, `primary_category.txt`, `secondary_category.txt` and the sub-category files. - `review_information/`: `first_name.txt`, `last_name.txt`, `phone_number.txt`, `email_address.txt`, `demo_user.txt`, `demo_password.txt`, `notes.txt`. - A `default/` folder that fills any language without its own files. - Screenshots and app previews in one folder per language. The device comes from the image size or the file name. - **supply (Google Play)**, under `fastlane/metadata/android//` ([docs.fastlane.tools/actions/supply](https://docs.fastlane.tools/actions/supply/)): - `title.txt`, `short_description.txt`, `full_description.txt`, `video.txt`. - `changelogs/.txt` and `changelogs/default.txt`. - `images/`: `icon`, `featureGraphic`, `promoGraphic`, `tvBanner`, plus `phoneScreenshots/`, `sevenInchScreenshots/` and `tenInchScreenshots/`. - **Appfile / Deliverfile / Fastfile** are Ruby: - `app_identifier`, `apple_id`, `team_id` / `itc_team_id`, `json_key_file`, `package_name`. - Deliverfile options such as `languages`, `submit_for_review`, `automatic_release`, `phased_release`, `price_tier`, `app_rating_config_path`. **What an importer would do.** It would only read, it would never run Ruby, and it would write with `--dry` first. 1. **Store ids.** Parse the simple `key("value")` / `key "value"` lines of `Appfile` and `Deliverfile` with a strict regex. That gives `apple.bundleId`, `play.packageName` and the languages. Ruby logic (conditionals, `ENV[...]`, lanes) is reported as "set it in storebound.config.ts", never guessed. 2. **Languages.** Join the deliver locales and the supply locales into storebound `languages[]` (`apple`, `play` codes). 3. **Listing text.** - Write `store/appstore.md` and `store/listing.md` from the `.txt` files, mapping `default/` into every language that lacks a file. - The newest `changelogs/.txt` becomes `whatsNew`. - Check lengths against the store limits (`storebound check`). 4. **Art.** Copy or link the screenshot folders into the renders layout (per language and size), or list them as `shots.frames` when they look like raw captures. The supply icon and feature graphic go to the configured paths. 5. **Secrets and personal data.** - `json_key_file` and `review_information/*` (contact, demo user and password) go to `.storebound/credentials.json`, which is gitignored, and never to the config (AGENTS.md rules 4 and 9). - The importer prints that it moved them, masked. 6. **Not imported, with a note:** - Submission and release flags (`submit_for_review`, `automatic_release`). storebound never submits. - `price_tier`. Prices live in the products / CSV flow. - The age rating config (answered with the owner in `store-declarations`). - Fastfile lanes. **Worth it? Yes.** fastlane is the most common existing setup, and its metadata folder maps almost one to one onto storebound's listing files. A read-only importer gives a migration path that keeps the store text, the screenshots and the credentials layout in a few seconds, and a dry run shows exactly what lands where. **Effort:** about 2 to 3 days with tests on fixture folders: an Appfile / Deliverfile line parser, the two metadata walkers, a dry-run report, and the `.storebound/` hand-off. Ship it as `storebound import fastlane [--dir fastlane] [--dry]`, then as an "Import from fastlane" choice in the desktop first-run guide. ## 2. A RevenueCat adapter **What the API offers.** RevenueCat REST API v2 lives at `https://api.revenuecat.com/v2`. It uses Bearer v2 secret keys with per-endpoint permissions, set in the project settings ([revenuecat.com/docs/api-v2](https://www.revenuecat.com/docs/api-v2)). It covers: - Apps. - Products: `/projects/{project_id}/products`. - Entitlements, with `.../entitlements/{entitlement_id}/actions/attach_products`. - Offerings and Packages. So the RevenueCat catalog can be created and kept in sync by API. **What storebound already replaces.** The store-side catalog: one product and subscription list in the config, created and priced on both stores (`play products / subscriptions`, `apple iap / subscriptions`, the regional price CSV), with cross-store parity (`catalog diff`). Teams that use RevenueCat only as a way to "set up the products" don't need it for that. **What storebound cannot replace.** - Runtime receipt and purchase-token validation. - Entitlement state per user, server notifications (App Store Server Notifications, Play RTDN). - Renewals, grace periods, refunds, customer history, paywall experiments and charts. - The client SDKs. All of that runs on a server, against live users. It is outside a release tool, and storebound should not try. **What an optional adapter could do:** `storebound revenuecat sync [--dry]`. - Key: `REVENUECAT_API_KEY` (v2 secret) and project id, from the environment or `.storebound/` only. - Source of truth: the storebound catalog. For every config product or subscription id and each store: 1. Create the RevenueCat product (store identifier, app id, type). 2. Create the entitlements named in a new optional config field (`products[].entitlements: ['pro']`) and attach the products. 3. Optionally create one default offering whose packages map to the subscriptions (`$rc_monthly` / `$rc_annual` by period). - Idempotent: match by store identifier. A dry-run diff comes first, as with every storebound write. Nothing is deleted. - Read-only parity: show "missing in RevenueCat" in `catalog diff` and in the desktop Catalog tab. **Recommendation.** Build the fastlane importer first: it is the migration path and the bigger win. Make RevenueCat a small, optional adapter later, scoped to catalog sync (products, entitlements, a default offering) plus parity in `catalog diff`. Market it as "keep RevenueCat in step with the stores", not as a replacement: - storebound owns the store-side catalog and the release. - RevenueCat (or the app's own server) owns runtime entitlements. Do not add webhooks, customers or any runtime data, so storebound stays a local tool with no server and no user data.