●MAX — Rork Max generates native Swift for iPhone, iPad, Apple Watch, Apple TV, and Vision Pro, with 2-click App Store publishing and no Xcode required●STACK — Standard Rork builds cross-platform mobile apps with React Native (Expo); choosing between the two by use case is the key decision●FOCUS — Unlike web-first tools such as Bolt or Lovable, Rork specializes in native iOS and Android app generation●BUGS — A hands-on review reports Rork resolved about 70% of bugs without manual help, with the remaining 30% needing edits in the exported codebase●FUNDING — Rork raised $2.8M from a16z (Andreessen Horowitz)●PRICING — It is free to start, with paid plans from $25/month, so you can try before committing●MAX — Rork Max generates native Swift for iPhone, iPad, Apple Watch, Apple TV, and Vision Pro, with 2-click App Store publishing and no Xcode required●STACK — Standard Rork builds cross-platform mobile apps with React Native (Expo); choosing between the two by use case is the key decision●FOCUS — Unlike web-first tools such as Bolt or Lovable, Rork specializes in native iOS and Android app generation●BUGS — A hands-on review reports Rork resolved about 70% of bugs without manual help, with the remaining 30% needing edits in the exported codebase●FUNDING — Rork raised $2.8M from a16z (Andreessen Horowitz)●PRICING — It is free to start, with paid plans from $25/month, so you can try before committing
Adding an Apple Wallet Stamp Card to a Rork Max App — Signing and Updates
You want a shop stamp card in Apple Wallet. When you issue a PassKit pass from a Swift app generated by Rork Max, the hard parts are not design — they are signing and remote updates. Here are the implementation essentials.
It began when someone asked me to replace a paper stamp card with one in Apple Wallet. Simply showing an image of the card face is easy. But that way, stamps added per visit are not reflected, and the user ends up opening the app to check anyway. The point of putting it in Wallet is that it appears on the lock screen and the balance or stamp count stays current automatically.
Issuing a PassKit pass from a native Swift app generated by Rork Max taught me that the hard parts are not design — they are "signing" and "remote updates." Clear those two, or a Wallet pass is no better than a still image. Even as an indie developer who has shipped plenty of apps, this was a fresh stumble for me. Here are the essentials I confirmed.
A pkpass Is a Signed ZIP
An Apple Wallet pass (.pkpass) is a ZIP archive of several files, signed together. Its contents fall into roughly three parts.
First is pass.json: the pass type (store card, coupon, boarding pass, etc.), the fields to display, colors, and the barcode. Second is the images (icon.png, logo.png, and so on). Third is manifest.json and signature — the heart of signing.
manifest.json is a list of SHA-1 hashes for each file. signature is a PKCS#7 binary signing that manifest with your Pass Type ID certificate. In other words, tamper with even one file and the hash no longer matches, so Wallet rejects the pass. That is why "just swap the image" does not work.
webServiceURL and authenticationToken are the entry point for the remote updates described below. The signing itself happens on the server (or at build time). You must not bundle the private key in the app, so generating and signing the pass should be the backend's responsibility.
✦
Thank you for reading this far.
Continue Reading
What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.
WHAT YOU'LL LEARN
✦Understand the structure of a pkpass (pass.json, manifest, signature) and where signing actually matters
✦Learn the PKAddPassesViewController code to add a pass to Wallet from your app
✦Reproduce the push-update flow that bumps the stamp count on each visit, and the server-side web service requirements
Secure payment via Stripe · Cancel anytime
✦
Unlock This Article
Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.
Once you receive the signed .pkpass from the server, the app just uses PassKit to present the add-to-Wallet screen. This is a few dozen lines of Swift.
PKPass(data:) throws if the signature is broken. This is where I first got stuck — the cause was a mismatch between the image filenames in the server's manifest and the images actually placed in the ZIP. A hash mismatch only ever surfaces as "invalid pass," so isolating the cause takes time. The manifest and ZIP contents must match exactly, down to filename and bytes.
You can check whether it is already added with PKPassLibrary:
let library = PKPassLibrary()let alreadyAdded = library.containsPass(pass)
Trigger Per-Visit Updates with Push
Here is the heart of it. When you add a stamp, you want to update the Wallet card face without the user doing anything. PassKit's Web Service makes this happen. The flow:
When the user adds the pass to Wallet, the device sends a "register this pass" request to webServiceURL. The server stores the device's push token linked to the pass serial number. When a stamp increases, the server sends an empty, pass-specific push via APNs. No notification is shown; it is a signal for Wallet to fetch the latest .pkpass from webServiceURL in the background.
The server should implement four main endpoints: device registration (POST .../registrations/...), unregistration (DELETE), returning the list of updated serial numbers (GET .../passes/...), and returning the latest pass (GET .../passes/{type}/{serial}). On receiving a push, Wallet first asks the list endpoint "which passes changed," then fetches the individual pass.
The nice thing about this design is that updates arrive even when the app is not running. In practice, the number of times users opened the app dropped, yet the return-visit rate held up. I believe seeing the stamps on the lock screen acts as a quiet reminder.
What to Check First
Once PassKit is in, send a test empty push from the server to a real device and watch whether the Wallet card face updates on its own. Many articles cover up to adding a pass; pushing through to the update is what first makes a stamp card a "living card face." Beyond matching signature hashes and push updates lies the value of replacing the paper card — that is how it feels to me.
Share
Thank You for Reading
Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.