Inspiration

We are Flamingo Co., Ltd., based in Korea. Plenty of people have one recipe their friends keep asking for. Putting it on a shelf means working out unit cost, a retail price, packaging, allergens and labeling rules, then finding a factory that will quote a small run. We wanted a phone app that drafts all of it and ends with a real quote request.

What it does

You start as a guest, with no sign-up. Choose "No recipe yet" or "I have a recipe", pick Packaged or Menu, a category and a container, then describe the idea in a chat with text, photos or a short video.

In a few minutes you get a product plan: cost per unit, a suggested retail price and margin, a price check against similar products on sale, every ingredient priced with alternatives you can toggle, process steps, shelf life, allergens, compliance notes for the Korean Food Code or FDA/USDA, and up to three AI photos, including one packaged in the container you picked. A guest sees cost, price, margin and the price check; a free account (no card) opens the rest. You can then edit the plan by chatting with AI.

When you are ready, "Get a quote" turns the plan into a co-packer spec sheet. Our team sends it to factories in Korea and posts their offers in the app, usually within 2 to 5 business days. You compare unit price, minimum order, lead time and fees, then pick a factory. Quotes are non-binding.

How it makes money

Two revenue lines around one moment: getting your product made.

  1. Subscriptions pay for planning: Basic at $9.99 a month or $79.99 a year, Pro at $29.99 a month or $239.99 a year. Yearly plans start with a 3-day free trial.
  2. Consumable quote credits pay for the factory step: $19.99 per request, $15.99 on Basic, and one included every month on Pro.

Free gives 2 complete plans. Details are in our HAMM answer.

How we use RevenueCat

We sell auto-renewing plans and consumable quote credits on two stores, and our backend is a Cloudflare Worker. The Worker needs one trusted answer to two questions: what plan is this user on, and which quote purchases are still unused? RevenueCat answers both. Here is the setup, in the order a purchase travels.

1. Catalog: one project, three stores

  • Apps: App Store (bundle getrecipecat.app, StoreKit 2 in-app purchase key, App Store server notifications sent to RevenueCat), Google Play (package app.getrecipecat, service account) and the RevenueCat Test Store.
  • Entitlements: basic and pro, each with 6 products (monthly and yearly on each of the three stores).
  • Offering: default ("RecipeCat plans"), the current offering, with 4 packages: basic_monthly $9.99, basic_yearly $79.99, pro_monthly $29.99, pro_yearly $239.99. On Play they arrive as basic_monthly:monthly, basic_yearly:yearly, pro_monthly:monthly and pro_yearly:yearly.
  • Trial: a 3-day free trial on basic_yearly and pro_yearly in both stores. Monthly plans have none.
  • Consumables, with no entitlement: quote_credit $19.99 and quote_credit_basic $15.99.
  • The ids live in one shared package that the app, the server and our REST API v2 setup script all import. The script creates the entitlements, the offering and its packages for the App Store and the Test Store. We set up Play by hand.

2. Purchase flow in the app (react-native-purchases 10.9)

  • After sign-in the app calls Purchases.logIn with the Clerk user id, so the app, our server and RevenueCat share one id.
  • The paywall reads getOfferings() and picks the 4 packages by product id, comparing only the part before the colon so Play ids match. Quote prices come from getProducts(). No price is written in our code, and "Save 33%" is computed from the store prices.
  • Where it opens: once after a signed-in Free user's first result, then at a locked photo, the AI edit limit, saving a copy, compare, a photo reshoot, the product limit, the Home badge and Account > Plan. Each has its own headline and recommended plan.
  • Trial: iOS tells us if you qualify (checkTrialOrIntroductoryPriceEligibility), and a Free user's button reads "3 days free, then $79.99/year · cancel anytime". Android does not report eligibility, so the Play purchase sheet decides.
  • Plan changes: on Play the app passes the current subscription with CHARGE_FULL_PRICE for upgrades and DEFERRED for downgrades, so Play never opens a second subscription. On iOS both plans share one subscription group.
  • Restore calls restorePurchases() and checks the store's purchase records, not entitlements, because a promotional Pro would always look "restored". Then it says what it found.

3. Server trust

  • Right after a purchase, a restore and each sign-in, the app calls our POST /me/plan/sync. The Worker makes one call, GET /v1/subscribers/{id} with the secret key, and reads the pro or basic entitlement, whether the period is a trial, and non_subscriptions. We wrote no StoreKit or Play receipt code.
  • Each non_subscriptions transaction becomes one quote credit keyed by its RevenueCat transaction id and inserted only once, so a repeated sync never counts it twice. A quote claims one credit with a conditional update, and if saving the quote fails, the credit is released. With no credit left, the API returns 402 with the product to sell: quote_credit, or quote_credit_basic for Basic members.
  • Pro gets one included credit per monthly window, valid 90 days, and never during a trial.
  • Without the RevenueCat secret, the API returns 503 instead of giving anything away.
  • Our webhook handler checks a shared secret and re-reads the subscriber on any event, instead of tracking event types. If a paid period ends and no event arrives, the plan falls to Free after 24 hours of grace.

4. Operations

  • Test Store first. Our development builds ran the paywall, the consumables and the server checks on the Test Store before any App Store product existed. A guard refuses a test_ key in a production build.
  • Promotional entitlements give Pro and Basic to App Review, to judges and to support. The paywall recognizes rc_promo_ product ids and still lets those users subscribe. RevenueCat reports a promotional grant as a normal period, so Pro's monthly quote credit works there too.
  • Deleting an account also deletes its RevenueCat subscriber.
  • 16 automated tests cover promotional grants, Play base plan ids, the restore check, plan sync and monthly windows.

5. Not used yet, and next

  • We built our own paywall because each entry point needs its own headline and default plan, and the table shows live quote prices. We have not used RevenueCat Paywalls, Experiments, Customer Center or Virtual Currencies yet.
  • Quote credits live in our own ledger because each one is tied to one factory request and released if the quote fails to save. Virtual Currencies is on our list to evaluate.
  • Next: Experiments on paywall copy, trial length and the Basic quote discount; RevenueCat Paywalls for the same table, so we can change it without an app release; Customer Center, since the app has no manage-subscription screen today.
  • With $0 revenue so far, RevenueCat's charts have nothing to show yet.

Awards we're entering and why

  • HAMM Award. Two revenue lines on one RevenueCat project: plans for planning and consumable quote credits for the factory step, verified on our server and offered where a maker hits a limit. No revenue yet, and we say so.
  • RevenueCat Design Award. Swap chips that re-price a plan on the phone with no AI call, a product photo made inside the container you picked, and a red progress screen that follows the server's real stages.
  • RevenueCat Peace Prize. A small maker sees cost, price, allergens and a non-binding factory quote before spending on inventory. Design intent only; no impact data yet.

How we built it

  • Mobile: Expo SDK 57, React Native 0.86, Reanimated 4, NativeWind, react-native-purchases 10.9, OneSignal SDK 5, Clerk email-code sign-in.
  • API: Hono on Cloudflare Workers with D1 (Drizzle), R2, KV, Queues and Workflows.
  • AI through OpenRouter: Claude Sonnet 5 writes and judges plans, Gemini 3.1 Flash Image makes photos, Perplexity Sonar Pro finds real product prices.
  • Every plan is checked by up to 12 automated checks and an AI judge, with up to 3 attempts.
  • pnpm and Turborepo, with zod schemas shared by the app, the API and the RevenueCat setup script. PostHog and Sentry.

Challenges we ran into

  • Believable AI numbers. Models write plausible recipes and shaky arithmetic. Our checks recompute cost and margin in code and, when we know enough real products on sale, require the retail price to sit inside their range. If all 3 attempts fail, we keep the best one and flag it in our admin.
  • Store edge cases: double subscriptions on Play, base plan ids, trial eligibility that only iOS reports, and promotional Pro on review accounts.
  • Four languages, two markets. Korean users get the Korean Food Code and won; everyone else gets FDA/USDA rules and dollars.

What we learned

  • Entitlements are not purchases. With promotional grants, a restore check based on entitlements always says "restored".
  • A consumable needs a ledger. Linking each credit to one quote, and releasing it on failure, keeps a failed request from costing a second payment.

What's next

  • The RevenueCat steps above: Experiments, RevenueCat Paywalls and Customer Center.
  • Submit the Pro 10-product pack (generation_pack_10, already handled on the server) as a store product.
  • Multi-step OneSignal flows for unopened results and makers who go quiet.

Honest status

  • Update, October 7, 2026: RecipeCat 1.0 is now live on Google Play: https://play.google.com/store/apps/details?id=app.getrecipecat . Google published it on October 6, 10:20 PM PT (October 7, 2:20 PM KST), after the October 1 deadline; the first review for our new developer account took about 7.5 days. The App Store version is still waiting for review and will be released automatically at https://apps.apple.com/us/app/id6815311551 when Apple approves it. At the deadline itself, neither store had published RecipeCat yet.
  • Our demo video is a screen recording of TestFlight build 1.0 (6) on an iPhone 12, the build we submitted to the App Store. The Pro plan restored in it was bought in the App Store sandbox. Its narration is a synthetic voice, and waiting is sped up and labeled.
  • Our video and screenshots are from the iPhone build. On Android we have not yet completed a Play purchase end to end.
  • Community posts shown are from our team's test accounts.
  • No paying customers and $0 revenue so far.
  • Our team handles factory quotes with factories in Korea, so manufacturing starts there. For US users, the main value today is costing and pricing.
  • US costs are estimated from Korean ingredient prices. Every number is an AI estimate to confirm with a supplier; the spec sheet we send to factories is marked as an AI draft.

Built With

  • claude
  • clerk
  • cloudflare-d1
  • cloudflare-r2
  • cloudflare-workers
  • cloudflare-workflows
  • drizzle
  • eas
  • expo.io
  • gemini
  • hono
  • nativewind
  • onesignal
  • openrouter
  • perplexity
  • pnpm
  • posthog
  • react-native
  • reanimated
  • revenuecat
  • sentry
  • turborepo
  • typescript
  • zod
Share this project:

Updates

Submission history