Skip to content

Release TROME on the App Store

Nine steps take TROME from your free Apple ID to the App Store, and this page walks you through each one, in the order that Apple asks for them. Your own work adds up to about a day, but the whole release takes a few weeks, because most of the time you wait: for Apple, and for some riders to test TROME. A few choices can never be undone: the list below names them before you start, and the step where you meet each one says why.

You need your Mac with the TROME repo, App Store Connect open in a browser, and your iPhone for the identity check and the tests. Each step needs your Apple Account, because you are the Account Holder and nobody else can sign in. What can be prepared without your account is in Have these ready.

The times are rough estimates of your own work, not Apple’s figures.

Step Your time Then you wait for
1. Join the Apple Developer Program 30 minutes Apple’s confirmation email: Apple says to contact them if it has not come 24 hours after you pay
2. Create the app in App Store Connect 20 minutes nothing
3. Sign the release build with your paid team 15 minutes nothing
4. Build, upload and check the first build 1 hour Apple’s email that the build is processed
5. Test with TestFlight: your iPhone first, then a small group 30 minutes, then days of use the beta review of the first external build
6. Fill in the store page 1 to 2 hours nothing
7. Give App Review the notes, the recording and your contact 20 minutes, plus filming nothing
8. Submit, read the status, and release 15 minutes the review (Apple: 90% of submissions in less than 24 hours), then up to 24 hours before the app shows
9. Watch the first days 10 minutes a day nothing

In the order that you meet them:

  1. The App Store ID on a free team. If a free Personal Team signs io.github.valfur03.trome, the free team holds that ID, and your paid account cannot register it until Apple frees it, a week later at best. The risk lasts until your paid team registers the ID (step 2).
  2. Your seller name. As an individual, your legal name is the seller on the App Store, and it becomes the developer name of the app, which you can never edit (step 1).
  3. The Paid Apps Agreement. TROME is free and does not need it, and Apple says that once you accept it, you cannot undo it: never accept it (step 1).
  4. The SKU and the bundle ID. The SKU is fixed once the app record exists, and the bundle ID once the first build is uploaded (step 2).
  5. Made for Kids. Once App Review approves it, it stays for every later version: answer Not Applicable (step 6).
  6. A released version. You cannot go back to an earlier version on the store: you can only send a new one, or remove the app from sale (step 8).

Each step needs some things that can be made without your Apple account. Check that each one is ready before you start the step that needs it, so that you never stop halfway through a form.

  • For steps 2 and 6: the store text, in French and in English: three store titles in order of preference, the subtitle, the promotional text, the description, the keywords, the category, the answers of the age rating questionnaire, and the copyright line. The App Store text of TROME 1.0 holds them all, ready to paste. The name on the home screen stays TROME, whatever store title you get.
  • For step 3: nothing. The repo signs the release build with the team of ios/Config/Signing.xcconfig, a file that git ignores and that you make in step 3, and with no other team.
  • For step 4: the build checks in the repo. The version is 1.0.0 and the build number is the one of the next upload, the app has its icon, its privacy manifest and its answer on encryption, and make check passes.
  • For step 4: the production server. You set its secrets in your own terminal with make server-secrets, which asks for each value at a hidden prompt, then you run make server-deploy, and its /health address answers {"status":"ok"}. Never put a secret in a file or in a message: a file can end up in git, and git keeps it for good.
  • For step 4: the server address and the app token in the release build. The release build reads them from ios/Config/Server.xcconfig, a file that git ignores, never from a file of the repo, and you make it in step 4. Have two values at hand: the host of the production server (for example trome-server.<your subdomain>.workers.dev), and the app token that you set with make server-secrets. Keep a copy of the token in your password manager when you set it: Cloudflare never shows a secret again. The archive fails with no host or no token in that file.
  • For steps 4 and 5: the privacy page and the help page online, with the name and the contact address that they hold: Confidentialité, Privacy, Aide and Help. The app opens the same two pages from its screen, and the build of step 4 must already have these addresses.
  • For step 5: the beta app description and what to test, a few lines for the testers, in French and in English: the store text page holds them.
  • For step 6: the App Privacy answers, written from the privacy page, so that the store and the page say the same thing.
  • For step 6: the screenshots, in French and in English, at the 6.9-inch size of App Store Connect (for example 1260 × 2736 pixels), made by one command in the repo.
  • For steps 5 and 7: the review notes, in English and under 4,000 bytes (in the store text page), and the recording script: you film the recording yourself, on your iPhone, at a real station, with the final build.
  • For step 8: the notes of the version, in two layers. For developers, the commit log, whose messages start with their type (feat, fix, docs), and CHANGELOG.md in the repo, which sums it up for each version. For riders, three or four lines in their own words, in French and in English, written by a person: they go on the site’s What’s new page (Nouveautés, What’s new), and from the second version on, in the What’s New field of the store.
Not checked on an account

Apple’s help, read on 3 October 2026: Program enrollment, Enrolling with the Apple Developer app, Become a member, EU Digital Services Act trader requirements, Sign and update agreements.

You can enrol before the rest is ready: enrolling creates no app and registers no bundle ID. The membership costs 99 USD a year, shown in your own currency when you pay, and its year starts on the day you pay. From that day, you sign with a paid team, which does not have the two limits of the free one: builds that stop after 7 days, and 10 new App IDs a week.

You need an Apple Account with two-factor authentication, your legal first and last name in that account (not a nickname), your own payment card, and a passport, a driving licence or another government photo ID.

  1. On your iPhone, install the Apple Developer app from the App Store, and open it.

  2. Tap the Account tab, and sign in with your Apple Account. If the app asks you to agree to the Apple Developer Agreement, tap Agree.

  3. Tap Enroll Now, read the benefits and requirements, and tap Continue.

  4. Enter your legal first name, last name and phone number. Apple shows this name as the seller of TROME on the App Store, and it becomes the developer name of the app, which you can never edit. An alias or a nickname delays the approval.

  5. Take a picture of your photo ID when the app asks. Apple says that it checks the ID and reads your name and address from it, and does not keep the image. Give a street address: Apple does not accept a P.O. box here.

  6. Choose Individual as the entity type, then read and agree to the Apple Developer Program License Agreement.

  7. Tap Subscribe. In the app, the membership renews every year until you cancel it, and Apple uses the default payment method of your Apple Account: a gift card balance does not work.

  8. Wait for the confirmation email. If it has not come 24 hours after your payment, contact Apple Developer Support with your Enrollment ID.

  9. Sign in to App Store Connect. Under Business, on the Agreements tab, accept the latest agreement if App Store Connect asks for it: you cannot create an app before that. Leave the Paid Apps row alone, and never click View and Agree to Terms on it: TROME is free and does not need it, and Apple says that once you accept it, you cannot undo it.

  10. Still under Business > Agreements, in the Compliance section, click Complete Compliance Requirements next to Digital Services Act, and answer whether you are a trader. If you skip it here, App Store Connect asks the same question when you submit your first app.

Not checked on an account

Apple’s help, read on 3 October 2026: Register an App ID, Delete an App ID, Add a new app, Set your developer name, App information.

First you register the two bundle IDs of TROME to your paid team: one for the app, and one for its Live Activity. Then you create the app record, which is the page of TROME in App Store Connect.

  1. Sign in to your developer account, and open Certificates, Identifiers & Profiles. Click Identifiers in the sidebar, then the + button.

  2. Select App IDs and click Continue, then keep the type App and click Continue.

  3. Enter TROME as the description, select Explicit, and enter io.github.valfur03.trome as the bundle ID. Leave the capabilities as they are: TROME uses none of them. Click Continue, check the ID letter by letter, and click Register.

  4. Do the same for the Live Activity: description TROME Live Activity, bundle ID io.github.valfur03.trome.widget.

  5. If the developer account says that an ID is not available, stop there and do not pick another ID: the repo and the store text use this one. A free team may still hold it. Apple’s help does not say for how long, but an Apple engineer wrote in the developer forums that the IDs of a free team are freed when its credentials expire, after about a week. So try again a week after the last build that a free team signed, and if the ID is still not available, contact Apple Developer Support and ask them to release it to your paid team.

  6. In App Store Connect, open Apps, click the + button at the top left, and choose New App.

  7. Fill in the New App form:

    • Platforms: iOS.
    • Name: the first store title of the store text. If App Store Connect says that the name is taken, try the second title, then the third.
    • Primary Language: French (France), because most riders are French. You add English in step 6, with its text.
    • Bundle ID: choose io.github.valfur03.trome in the list, which shows the IDs that you registered above.
    • SKU: trome-ios, or another code of your choice. Riders never see it, and it may hold letters, digits, hyphens, periods and underscores.
    • User Access: Full Access.

    As an individual, your developer name is your legal name, and the form has no field to change it.

  8. Click Create. The app shows the status Prepare for Submission.

3. Sign the release build with your paid team

Section titled “3. Sign the release build with your paid team”
Not checked on an account

Apple’s help, read on 3 October 2026: Preparing your app for distribution, Team ID. Read on 11 October 2026: Distributing your app for beta testing and releases.

The release build of TROME signs with the team of ios/Config/Signing.xcconfig, your own file, which git ignores, and with no other team. With no team in that file, the release build signs by hand, on purpose: so a free Personal Team that tries to sign it gets an error, and can never register the App Store ID. With your paid team in it, Xcode signs the release build automatically, and makes the certificates and profiles that it needs by itself.

  1. In Xcode, choose Xcode > Settings, click Apple Accounts, and select your account. Your paid team now shows, with your name, next to your Personal Team.

  2. Find your Team ID: in your developer account, click Membership details. It has 10 letters and digits.

  3. Open ios/Config/Local.xcconfig, your own settings file, which git ignores, and replace the value of DEVELOPMENT_TEAM with the Team ID of the paid team. If the file still sets TROME_DEBUG_APP_BUNDLE_ID or TROME_DEBUG_WIDGET_BUNDLE_ID, the IDs of your old Debug builds, delete those lines. Save the file.

  4. Get the latest main, then make the Xcode project again:

    Fenêtre de terminal
    git switch main
    git pull
    make generate

    Its last line shows the IDs of your Debug build, <your prefix>.trome.dev and <your prefix>.trome.dev.widget: they differ from the App Store ID, so your Debug build and the TestFlight build can both be on your iPhone.

  5. Make your signing file from its example, then open it. You do this once: on a later release the file is already there, so check its line and go on to the next step.

    Fenêtre de terminal
    cp -n ios/Config/Signing.example.xcconfig ios/Config/Signing.xcconfig
    open -e ios/Config/Signing.xcconfig

    Put the Team ID of the paid team after TROME_RELEASE_TEAM =, never the ID of your Personal Team, and save the file. If the archive of step 4 shows “TROME” requires a provisioning profile, this value is empty: the release build is still signed by hand.

  6. Click Run in Xcode once, with your iPhone connected, to check that the Debug build still installs. If Xcode says that a Debug ID is not available, your free team still holds it. Set TROME_BUNDLE_ID_PREFIX in ios/Config/Local.xcconfig to a prefix that your free team never used, then run make generate and Run again. Or wait about a week after your last build with the free team, as for the App Store ID, and try again.

make generate makes the Xcode project from ios/project.yml, so a setting that you change in the Signing & Capabilities pane of Xcode is lost the next time it runs.

4. Build, upload and check the first build

Section titled “4. Build, upload and check the first build”
Not checked on an account

Apple’s help, read on 3 October 2026: Distributing your app for beta testing and releases, Upload builds, App build statuses, Overview of export compliance, Describing use of required reason API.

The version that riders see and the build number are in ios/Config/Base.xcconfig: MARKETING_VERSION (1.0.0 for the first release) and CURRENT_PROJECT_VERSION (the build number of the next upload). App Store Connect accepts each build number of a version only once. So right after each upload, you raise CURRENT_PROJECT_VERSION by 1 and commit it (step 11): main always holds the number of the next upload, and the commit that you archive holds the number that it uploads.

  1. Get the latest main, and check that the build is ready:

    Fenêtre de terminal
    git switch main
    git pull
    make check

    Among other checks, it builds the Release app and fails with a message when the app has no privacy manifest, no answer on encryption, or a version that is not three numbers such as 1.0.0. It also fails when the code of the app or of its Live Activity calls an API of Apple’s list of APIs that need a reason, and the privacy manifest gives no reason for it. Then git status --short and git log origin/main.. must print nothing: the tag of step 10 of this list names one commit of main, so the archive must hold no change outside it, and that commit must be on GitHub.

  2. Make your server file from its example, then open it. You do this once: on a later archive the file is already there, so only run the check at the end of this step.

    Fenêtre de terminal
    cp -n ios/Config/Server.example.xcconfig ios/Config/Server.xcconfig
    open -e ios/Config/Server.xcconfig

    Put the host of the production server after TRAIN_SERVER_HOST =: only the host, with no https:// and no path. Put the newest app token of the production server’s list after TRAIN_SERVER_APP_TOKEN =: the one that you set with make server-secrets, or the last one that you added. Save the file. Git ignores this file, and the token goes nowhere else: never into a page, a message or a commit. If you no longer have the token and this is your first upload, make a new one with openssl rand -hex 32 and set it with make server-secret NAME=APP_TOKEN: no installed app holds the old one yet. Make it with -hex: a token with // in it would be cut, because // starts a comment in this file. After your first build is on a phone, never do this to get a token back: a token set alone replaces the server’s list, and cuts off every installed app. Take the token back from the archive of your last upload instead. In the Organizer window of Xcode (Window > Organizer), right-click that archive and choose Show in Finder, then right-click the archive in Finder and choose Show Package Contents. In Products/Applications, choose Show Package Contents on the app, and open Info.plist: the token is the value of TrainServerAppToken. To give the next builds a new token, add it to the server’s list with this one, as Change the app token says. With no archive left, the token is lost, and no step keeps the installed apps working: a new token cuts them off until their riders update.

    Then check the two values with the production server, before each archive:

    Fenêtre de terminal
    make release-server-check

    It asks the server for the trains of one stop, as the app does, and prints one line that shows neither value. A line that starts with OK means that the server accepts them. Any other line says what is wrong and what to do: fix the file, and run the check again. A typo here would ship a build that shows no times at any station, and nothing else shows it before your testers do.

    make check passes without this file, because it builds with stand-in values, so only the archive shows a missing one. The archive then fails with an error that starts with No train server host or No app token for the train server, and names this file. An error that says is not a host name means that TRAIN_SERVER_HOST holds more than the host.

    Last, check that the production server still accepts the app token of each build that riders may hold, not only the newest one:

    Fenêtre de terminal
    make release-tokens-check

    The first time, make ios/Config/BuildTokens.txt first, as The app token of each build says: until then the check stops and tells you so. Its lines are accepted or refused, and that section says what to do with a refused one. Do not archive before every build in the field is accepted.

  3. Run make generate, then open ios/TROME.xcodeproj in Xcode.

  4. In the toolbar, choose the scheme TROME and the destination Any iOS Device (arm64). Then choose Product > Archive. When the archive is built, the Organizer window opens on it.

  5. Click Validate App, and fix each error that it shows before you go on.

  6. Click Distribute App, choose TestFlight & App Store, and click Distribute. Xcode signs the build and uploads it, and with this choice it may also change the build number of the archive.

  7. Wait for Apple’s email that says the build has been processed. Then, in App Store Connect, open TROME > TestFlight, and find the build under Builds > iOS.

  8. Look at its status first:

    • Ready to Submit: the build passed the upload checks, so go on to TestFlight.
    • Missing Compliance: the build does not answer the encryption question by itself. For this build, click Manage and say that TROME uses only the encryption built into iOS (its HTTPS connections): that use is exempt, so Apple needs no export compliance documents. Then open an issue in the repo, so that the next build answers by itself.
    • Invalid Binary: the build failed a check of Apple, and the email says which one.
  9. Read every email that Apple sends about this upload. A message about a missing API declaration (code ITMS-91053) means that the privacy manifest does not give a reason for an API that the app uses: Apple refuses such builds. Fix it in the repo, raise the build number by 1 in the same commit, and upload again: a build that Apple refuses reaches no rider, so it gets no tag and no row.

  10. Write down the build number that App Store Connect shows. Before any new commit, on main, tag the commit that you archived with the version and that number, here 1.0.0 and 3, and push the tag:

    Fenêtre de terminal
    git tag -a builds/1.0.0/3 -m "TROME 1.0.0 (3)"
    git push origin builds/1.0.0/3
  11. In one commit, add the row of the build to the builds that riders may hold, and set CURRENT_PROJECT_VERSION to one more than the build number that App Store Connect shows, for the next upload; push it. That commit will also record the set of promises of the build: what it reads from the server, kept until its row is retired. The repo does not record these sets yet, so for now there is nothing to add. Then add the line of the build to ios/Config/BuildTokens.txt, here 3 = <token>, with the app token of ios/Config/Server.xcconfig that this build holds, and run make release-tokens-check: the line of the new build must say accepted. That file is not in git, so it is not in the commit.

5. Test with TestFlight: your iPhone first, then a small group

Section titled “5. Test with TestFlight: your iPhone first, then a small group”
Not checked on an account

Apple’s help, read on 3 October 2026: TestFlight overview, Add internal testers, Provide test information, Invite external testers, App Review Guidelines, rule 2.2.

You test first on your own iPhone, as an internal tester: this needs no review. Then a small group of riders tests the same build, as external testers: Apple reviews the first build that goes to them, against the same rules as the store, so this review is the free rehearsal of the real one. A TestFlight build works for 90 days.

  1. In App Store Connect, open TROME > TestFlight, and click the + button next to Internal Testing. Name the group, for example Me, select Enable automatic distribution, and click Create.

  2. In the group, click Invite Testers, select yourself, and click Add.

  3. On your iPhone, install TestFlight from the App Store. Open the invitation email on the iPhone, accept it in TestFlight, and tap Install.

  4. Use this build yourself, at real stations, for some days, before you invite anyone. It gets its trains from the production server, as the store build will.

The server shares one daily budget of train data calls between all riders, and today it serves about 40 riders well. So the group stays small until the quota of the PRIM account is raised.

  1. Check that the privacy page and the help page are online, and that the build opens them from the app screen.

  2. Open TestFlight > Test Information (under Additional). Fill in the Beta App Description and the Feedback Email: testers see this address, so use the contact address of the help page. If the page also asks for a privacy policy URL, give the privacy page of the language that you fill in, as in step 6.

  3. Click the + button next to External Testing, name the group, for example First riders, and click Create. App Store Connect needs the internal group of the steps above before it lets you create this one.

  4. In the group, click Add Builds, choose the build, enter what testers should look at in What to Test, and click Submit Review. If App Store Connect asks for a contact and notes for the beta review, give your name, email and phone, and paste the review notes.

  5. Wait for the beta review: App Store Connect emails you when it approves the build. If it rejects it, the build status is Rejected: open App Review in the sidebar to read why, then fix and upload a new build, as in step 8.

  6. In the group, under Testers, click Create Public Link, choose Open to Anyone, click Set Limit under Tester Limit, enter 40, and click Confirm. Or click the + button next to Testers, and invite people by email.

  7. Each day, read the counts of the server, as in step 9. After about two weeks of real use, ask PRIM for a higher quota: on your PRIM account, the page Ma consommation API has a button Augmenter vos quotas. The counts show how many calls a rider really uses, which is the figure that you need.

Not checked on an account

Apple’s help, read on 3 October 2026: Platform version information, App information, Localize app information, Upload app previews and screenshots, Screenshot specifications, Manage app privacy, Set an app age rating, Set a price, Manage availability.

Paste the store text, in French first, then in English: choose the language at the top right of each page. Apple counts the limits in characters, except the keywords, which it counts in bytes, and an accented letter such as é takes two bytes.

  1. Open App Information, and fill in the Name and the Subtitle in French, at most 30 characters each. Then set the Category.

  2. Add English: at the top right, click the primary language, French (France), scroll down to Not Localized, hold the pointer over English (U.S.), and click the + button that appears next to it. Enter the English name and subtitle, and the English privacy address of step 5 below, then click Save at the top right.

  3. Still in App Information, answer Content Rights: TROME shows train data of Île-de-France Mobilités, so say that it shows third-party content and that you have the rights. The licence of the data, the Licence Mobilités, allows its reuse in an app, commercial use included, when the app names the source, which TROME does.

  4. Still in App Information, click Set Up Age Ratings, and give the answers of the store text. Under Age Categories and Override, choose Not Applicable: once App Review approves Made for Kids, it can never be removed.

  5. Open App Privacy, click Edit next to Privacy Policy, and enter the address of the privacy page in each language, the French one for French:

    https://trome.valfur.fr/fr/privacy/
    https://trome.valfur.fr/en/privacy/

    Then click Get Started, and give the App Privacy answers. Check the preview, then click Publish: you confirm that the answers are true, and you must update them if the app changes. They show on the store page once the app is live.

  6. Open the version under iOS App: App Store Connect created it as 1.0. Set its Version Number to 1.0.0, the version of the build, because Apple says that the two should match. Then fill in for each language: the Promotional Text (at most 170 characters), the Description (at most 4,000 characters), the Keywords (at most 100 bytes, with no name of another app or company), the Support URL (the help page of that language, below) and the Copyright (the year and your legal name, without the © sign, which Apple adds):

    https://trome.valfur.fr/fr/support/
    https://trome.valfur.fr/en/support/

    The first version has no What’s New field.

  7. Under Previews and Screenshots, choose the iPhone tab, and drag the screenshots of that language, in their order, into the 6.9-inch well. Apple scales them down for the smaller iPhones.

  8. Open Pricing and Availability, click Add Pricing, choose France as the base country and the free price, and confirm.

  9. In the same page, click Set Up Availability, choose All Countries or Regions, and confirm. China mainland then shows ICP Filing Number Missing: that number is a filing with the Chinese government that TROME does not have, so the app stays unavailable there, and that is expected.

7. Give App Review the notes, the recording and your contact

Section titled “7. Give App Review the notes, the recording and your contact”
Not checked on an account

Apple’s help, read on 3 October 2026: Platform version information, section App Review information, App Review.

App Review is rarely in Paris, so a reviewer cannot see a station arrive. The notes tell them how to see the Live Activity from anywhere, and the recording shows it at a real station. Only App Review sees this part, and you can edit it at any time.

  1. Film the recording on your iPhone, at a real station, with the build that you will submit, as the recording script says.

  2. In the version 1.0.0, scroll to App Review Information. Leave Sign-in required off: TROME has no account.

  3. Fill in the contact: your first name, last name, email address, and phone number in international format, with a plus sign and the country code (for example +33 6 12 34 56 78). Apple uses it only when the reviewer has a question.

  4. Paste the review notes into Notes. The field holds 4,000 bytes at most.

  5. Attach the recording.

  6. Click Save at the top right.

Not checked on an account

Apple’s help, read on 3 October 2026: Choose a build to submit, Select a release option, Submit an app, App and submission statuses, Reply to App Review messages, Manage a submission with unresolved issues, Create a new version.

Choose to release the version yourself: then an approval does not publish TROME, and you pick the day. The store has no tester limit, so release only when the PRIM quota has been raised and the server is ready for everyone.

  1. In the version 1.0.0, scroll to Build, click the + button, choose the build that you tested with TestFlight, and click Done.

  2. In App Store Version Release, select Manually release this version.

  3. Click Save, then Add for Review at the top right. The status becomes Ready for Review.

  4. Click Submit for Review. The status becomes Waiting for Review, then In Review.

  5. Wait for Apple’s email. Apple says that 90% of submissions are reviewed in less than 24 hours.

  6. When the status is Pending Developer Release, check that the PRIM quota has been raised, that the server answers, and that the What’s new page has the 1.0 lines. Then click Release This Version, and Confirm. TROME can take up to 24 hours to show on the App Store. When it shows, write App Store, with no date, in the Where cell of the row of the build in the builds that riders may hold.

Status What it means What you do
Prepare for Submission The app record exists, and you are still filling it in. Finish steps 6 and 7.
Ready for Review Everything is filled in, but nothing is sent yet. Click Submit for Review.
Waiting for Review Apple has your submission, but nobody has opened it yet. Wait. You cannot change the screenshots now.
In Review A reviewer is testing TROME. Wait, and keep the server running.
Rejected App Review refused the build. Read the message, as below.
Metadata Rejected App Review refused a text or a picture of the store page, not the build. Fix the text or the picture, and reply to the message.
Invalid Binary The build does not meet Apple’s current requirements. Upload a new build.
Pending Developer Release Apple approved the version, and it waits for you. Release it on the day of your choice.
Processing for Distribution You released it, and Apple is putting it on the store. Wait up to 24 hours.
Ready for Distribution TROME is on the App Store. Go to step 9.
Developer Rejected You took the version out of the review yourself. Submit it again when it is ready.

A refusal is a message, not a penalty, and each round usually costs a day.

  1. In App Store Connect, click the link at the top of the TROME page that says there are unresolved issues, then Resolve next to the submission.

  2. Read the message: it names the rule of the App Review Guidelines and what the reviewer saw.

  3. If the reviewer misunderstood the app, click Reply to App Review, explain it, and attach a screenshot or a video if it helps.

  4. If only the store page is wrong, fix the text or the picture, and resubmit the same build.

  5. If the build is wrong, fix it in the repo, and upload it as in step 4. Then, in the version, replace the build with the new one, and click Resubmit to App Review.

  6. If you are sure that TROME follows the rules, you can appeal to the App Review Board, once for each refusal, from the App Review page.

A phased release gives a new version to the riders with automatic updates over 7 days, so that a bug reaches fewer of them. Apple offers it only for an update, not for the first version: choose it from version 1.1 on, in the version page, under Phased Release for Automatic Updates.

Not checked on an account

Apple’s help, read on 3 October 2026: View ratings and reviews, View tester feedback, Acquiring crash reports and diagnostic logs. Cloudflare’s docs, read on 3 October 2026: workers.dev.

First, when the store link opens on your iPhone, change the site to the store link: the homes and the README still say that TROME is not on the App Store yet.

For the first week, look at these once a day:

What Where
The reviews of riders App Store Connect, TROME > Ratings and Reviews, by country. You can answer a review in public.
The feedback of testers App Store Connect, TROME > TestFlight, under Feedback: Screenshots and Crashes.
The crashes Xcode, Window > Organizer > Crashes. It shows the crashes of TestFlight testers, and those of App Store riders who share analytics with Apple.
The emails of riders The contact address of the help page.
The train data calls of the day make server-counts URL=<address of the production server>, with your owner token. It shows today and the last 14 days; add FULL=1 for 30 days, hour by hour. Your PRIM account shows the same calls on Ma consommation API.

If the server must stop, for example when it uses too many PRIM calls or answers wrong times, turn off its address. Riders then get no new times until you turn it on again. Never leave it off for good: every build calls this address (Keep the address of the server).

  1. In the Cloudflare dashboard, open Workers & Pages, and select the production Worker.

  2. Open Settings > Domains & Routes, and click Disable next to workers.dev.

  3. To start it again, click Enable in the same place. The next make server-deploy also turns it on again, as Cloudflare’s docs warn.

Every build uploaded to Apple is a row of this table, from its upload on, and keeps its row forever. A server change keeps every build in the field working: the server adds what a new build needs next to what the older ones read, and never swaps it. Why: a rider updates when they choose, so an old build can call the server for years. The table does not yet say what each build reads from the server: until the repo records it, read the code at the tag of the build.

Each build has the git tag builds/<version>/<build> on its commit, which you add at the end of the upload in step 4. A TestFlight build becomes unavailable to testers after 90 days: the table counts them from the upload, and App Store Connect shows the days left on the build, so trust it when the two differ. A build released on the store stays installed and keeps working, so when you release it in step 8, you write App Store, with no date, in the Where cell of its row.

Apple’s help, read on 11 October 2026: TestFlight overview.

Version (build) Uploaded Commit Where, and until when Status
1.0.0 (1) 11 October 2026 ca169af TestFlight, internal testers, until 9 January 2027 In the field
1.0.0 (2) 11 October 2026 9d83a8d TestFlight, until 9 January 2027 In the field

Builds 1 and 2 were tagged after their upload, from the history and the time of each archive. Build 2 was archived with its build number not yet committed, so its tag is on the commit of that number, made just after the archive with no other change. The app files of build 1 are the same in every commit from dcf1d8d to dd59fdd, so its tag holds the right app code whichever of them was checked out.

Every build in the table holds the address of the production server, trome-server.<your subdomain>.workers.dev, for good. So while the table has a build in the field, never do any of these in your Cloudflare account:

  • Rename the subdomain of the account (Workers & Pages, Your subdomain).
  • Rename or delete the production Worker, trome-server.
  • Leave its workers.dev address off.
  • Move production to another account.

Each of them cuts every build in the field from its times, and no message can reach those builds. Keep the address of the server says what each costs and the only way back. A new address is only ever added next to the old one, and the old one stays until every build that holds it is retired.

Each build holds the app token that it was built with, and the server must accept it until the build is retired. The server keeps a list of tokens for this reason: a new token joins the list, and no build that holds an older one loses its times (Change the app token). Keep these tokens in ios/Config/BuildTokens.txt, a file that git ignores, one line per build: its build number, =, and its token. Make the file once from its example, and add a line for each build in the field, from your password manager:

Fenêtre de terminal
cp -n ios/Config/BuildTokens.example.txt ios/Config/BuildTokens.txt
open -e ios/Config/BuildTokens.txt
// The app token of each build that riders may hold.
1 = <the app token of build 1>
2 = <the app token of build 2>

If you no longer have the token of a build, take it from the archive of that build, as step 2 of the upload says for the last one.

Then ask the production server about each build in the field of the table above:

Fenêtre de terminal
make release-tokens-check

It uses the host of ios/Config/Server.xcconfig, sends the token of each build as the app does, and prints no token. Run it before every upload, and after every deploy or change of a secret of the production server. Each line is the name of a build, then what the server did with its token:

  • accepted: the server accepts the token, so the riders of this build see times.
  • refused: the server refuses it, so the riders of this build see Update the app in place of times.
  • not asked: the check stopped before this build, as the last line says.

The last line says how it ended:

  • OK: every build in the field is accepted, and the check is done.
  • Refused: at least one build is refused. Look at its line in ios/Config/BuildTokens.txt first: a typo is the likeliest cause, so fix it and run the check again. If the line matches your password manager, the production list lost that token: set the whole list again, with the token of every build in the field and the newest one, as Add a token says. The new value replaces the whole list, so leave no token out, and run the check again.
  • Not finished: the server has no PRIM calls left this hour, and the builds that say not asked wait: run it again an hour later. The check makes at most one PRIM call per build.
  • Any other line says what is missing or wrong, for example a build with no line in the file, or a host that does not answer: the check stopped, so do what it says and run it again.

A build leaves the field only for one of these reasons, written in its row with the date:

  • No rider can still open it: its TestFlight date has passed, or you expired it in App Store Connect.
  • For a build on the store: you judge that no rider still uses it, from the App Store Connect figures by version, and you write those figures in the reason. They count only the riders who share analytics with Apple, so they show that a build is rare, never that it is gone.

A server change is never a reason: a change that would break a build waits until that build is retired. A new app token is no exception: it joins the server’s list, and a token leaves the list only once every build that holds it is retired (Change the app token). Once a build is retired, a server change may drop what only that build read. The row stays in the table, with the status Retired on <date>: <reason>.

This page was written from Apple’s help, before anyone followed it on a paid account, so your first release is its test. When a step differs from what you see, write down the step, what the page said, what the screen showed, and what you did instead: a screenshot helps. Then open an issue in the repo, titled with the step, for example “Release page, step 4: the Organizer shows another button”. The page is fixed in the same week, and each step that you followed loses its mark Not checked on an account, so that the next release follows tried steps.