The gap we were trying to fill

Most gardening apps split into two camps. Visual layout tools like GrowVeg let you draw your beds; calendar tools like Seed to Spoon track what to sow when. Neither connects the two, and almost none of them care about your actual weather.

The apps that do exist are mostly built around USDA hardiness zones and zip codes. Useful if you're in Iowa. Not if you're growing chard in Gwynedd in February, where what matters is whether last night's soil temperature dropped below 4°C and whether you have rain forecast before you need to water.

That was the brief: a UK-first app that knows your postcode, reads the forecast, and tells you what to do in your garden today - not a generic list from a hardiness zone table.

Why we built on Umbraco

The app runs on Umbraco 17 and .NET 10 as the backend, with a vanilla JS PWA wrapped in Capacitor for the App Store submission. That probably sounds like an odd choice for a gardening app, but it made sense for one reason: the crop library.

Patch ships with 382 crops. Each one has sowing windows, frost hardiness, spacing data, companion planting relationships, and UK-specific growing notes. That data needs to be maintained - adding varieties, correcting errors, updating notes based on what users report. Umbraco gives us a managed CMS for that library at no extra build cost. We already know how to run it, and it means anyone on the team can edit crop data without touching code.

User data - beds, plantings, tasks, harvests, diary entries - lives in seven custom SQL tables via EF Core, completely separate from the Umbraco content layer. Shared crop reference data in Umbraco, personal growing data in SQL. The split meant we could iterate on the user-facing features without touching the crop library, and vice versa.

How we kept scope honest

  • One screen per job

  • Ship the smallest plant database that feels complete

  • Defer anything that needed a backend

We cut everything that wasn't a seed-to-harvest loop. No accounts, no social features, no cloud sync on day one. No drag-and-drop visual garden designer - that's the feature every competitor leads with, and it costs three times what it's worth in build time. Deferred.

The rule was one screen per job. The Today tab shows your tasks for today. The Garden tab shows your beds. The Crops tab lets you browse and search. Nothing earns a screen unless it has a clear job.

The crop database was the other constraint. We wanted it to feel complete on day one - not embarrassingly thin. That meant sourcing data from multiple sources, collating it all, validating it and presenting in a format we could use easily. 168 of the 382 crops shipped with full UK growing data on launch.

The review queue was the only deadline we didn't control, and Apple turned it around in 96 hours - the first time.

Three rejections and a stuck release

The first time, the app came back rejected under Guideline 2.3.2. The IAP promotional images for the Premium subscription were screenshots of the app. Apple's requirement is a clean marketing image. The rejection cascades: one non-compliant image puts the entire IAP product into "Developer Action Needed", which blocks StoreKit from fetching products in the sandbox. Fixed, resubmitted.

The second rejection: missing Terms and Conditions link in the subscription flow. The third: OTP email delivery - Apple's review team are US-based, and our magic link emails hit spam thresholds during review. Added the demo credentials and OTP flow explanation to the review notes. Approved.

Then the auto-release got stuck. App Store Connect showed "1.0 Ready for Distribution" with auto-release set, but the release date kept rolling forward. The "Release This Version" button was absent. The radio buttons to switch to manual release were greyed out. All agreements were active. Bank details, tax forms, compliance - all green. No pending actions anywhere. Contacted Apple Developer Support, and they unstuck it from their end. The app went live without any code change required.

The lesson isn't that Apple's review process is painful - it's that you need to treat the review notes like a user test. The reviewer doesn't know your auth flow, doesn't know magic links, and may be confused by UK-specific content. Write the notes as if you're onboarding someone who has never seen the app.

The bits that catch you

A few things that ate time and aren't obvious:

RevenueCat entitlement IDs are case-sensitive. The entitlement in the dashboard was Premium; the code was checking for premium. The mismatch produces no error - premium just silently doesn't unlock.

Subscription products in "Ready to Submit" status aren't fetchable by StoreKit on real devices. They have to be submitted for review alongside the app before sandbox purchases work. The workaround is a StoreKit Configuration file for local testing, but knowing this before you spend two hours debugging saves a lot of time.

Smidge (our asset bundling library) doesn't support ES6 template literals in its JS minifier. The entire JS bundle gets served unminified. Not a disaster, but not what the docs suggest.

What's next

The iOS app is live at apps.apple.com/gb/app/mypatch/id6761283635. Google Play submission is next. Web payments for users who don't go through the App Store is still to solve.

The crop library is the ongoing work. 168 crops with full data is a reasonable start; getting the remaining 214 to the same quality is a longer project. The data infrastructure is there - it's editorial time now.