cd /news/artificial-intelligence/i-shipped-my-first-ios-app-in-30-day… · home topics artificial-intelligence article
[ARTICLE · art-26417] src=dev.to ↗ pub= topic=artificial-intelligence verified=true sentiment=· neutral

I shipped my first iOS app in 30 days for $300. Here's the build log.

A developer built and shipped Chista, an iOS app that auto-imports and classifies screenshots using AI, in 30 days for about $300. The app uses a SwiftUI frontend with a Python backend on FastAPI, Supabase for database and auth, and OpenAI GPT-4o for categorization. The developer documented a critical bug in Apple's in-app purchase verification library where an empty root_certificates list causes all JWS verifications to fail, requiring manual inclusion of Apple's root CA certificates.

read4 min publishedJun 13, 2026

I take a lot of screenshots. The article I'll read later. The recipe I'll cook on Sunday. The movie name from someone's Instagram story. A job post, a product, a tender.

Most of them die in my camera roll.

So I built ** Chista** — an iOS app that auto-imports every screenshot, classifies it with AI (Article, Product, Event, Reference, Media), and surfaces a one-tap action:

It shipped on the App Store thirty days after I started, for about $300 in total cost. The interesting part wasn't the app. It was what the build revealed.

Chista is a native iOS app + Python backend.

PHPhotoLibraryChangeObserver

, scoped to PHAssetMediaSubtype.photoScreenshot

(so it literally can't see your other photos).CategorizationResult

JSON: category, subtype, title, suggested action, extracted data (price, deadline, URL, etc.).That's the whole thing. The "magic moment" is just: you screenshot something, switch to Chista a few seconds later, it's already sorted with a contextual action button.

Layer Tool Why
iOS app Swift 5.10, SwiftUI, StoreKit 2 iOS 17+, modern surface
Backend FastAPI on Railway One-file ergonomics, fast cold starts
Database + Auth Supabase Postgres + JWT auth out of the box
AI OpenAI GPT-4o (Pro), gpt-4o-mini (Free) Tier-routed at categorization time
Push APNs via aioapns Direct, no Firebase middleman
Subscriptions StoreKit 2 + app-store-server-library
Server-side JWS verification
Affiliate routing Custom matrix in Supabase tables Amazon Associates wired, more pending
Hosting (web) Cloudflare Pages Free, fast, never goes down

No frameworks I wouldn't reach for again.

Line item Cost
Apple Developer Account $99/yr
Domain (chista.app) $10/yr
OpenAI API credits
$100 (one-off prepaid)
Cloudflare (web + DNS) free
Railway (backend)
$5/mo trial credit, then hobby tier
Supabase free tier
Everything else mostly free tiers

Total to ship v1: about $300.

Apple App Review's reviewer kept hitting INVALID_CERTIFICATE

when validating in-app purchase JWS payloads on our backend. We chased it through four library versions:

app-store-server-library==1.8.0  → INVALID_CERTIFICATE
app-store-server-library==1.9.0  → INVALID_CERTIFICATE
app-store-server-library==2.0.0  → INVALID_CERTIFICATE
app-store-server-library==3.1.2  → INVALID_CERTIFICATE

I enabled online cert checks. I bundled app_apple_id

. I made the verifier environment switch independently from APNs. Nothing worked.

The actual problem: the library has a constructor like this:

SignedDataVerifier(
    root_certificates=[],   # ← THIS
    enable_online_checks=True,
    environment=Environment.SANDBOX,
    bundle_id="com.chista.app",
    app_apple_id=6771318695,
)

I assumed root_certificates=[]

meant "use Apple's bundled roots." It doesn't. The library ships with zero root CAs. An empty list means "trust nothing." Every Apple-signed JWS fails because the cert chain has no trust anchor.

The fix: download Apple's Root CA G2 and G3 directly from apple.com/certificateauthority, check them into the repo, and pass the bytes:

cert_dir = Path(__file__).parent.parent / "data" / "apple_certs"
root_certs = [
    (cert_dir / "AppleRootCA-G3.cer").read_bytes(),
    (cert_dir / "AppleRootCA-G2.cer").read_bytes(),
]

SignedDataVerifier(
    root_certificates=root_certs,
    enable_online_checks=True,
    environment=env,
    bundle_id=bundle_id,
    app_apple_id=app_apple_id,
)

One line of additional config, ~2KB committed to the repo, problem solved.

If you're integrating Apple's library and hitting this: the empty default is the bug, not your environment. The official docs imply bundled roots; the code does not.

I built Chista with heavy AI assistance — drafting Swift views, generating prompt templates, debugging gnarly things like the cert chain above. It would be dishonest to tell this story without saying so.

What that actually changed:

That last point is where I think the whole industry is heading.

A decade ago, the hard part was writing software.

Today, the hard part is deciding what should exist.

The cost of creation is collapsing. The time from idea to first version is shrinking. The number of people who can build is exploding. None of this is news on dev.to — but watching it happen in real time on my own project felt different than reading about it.

Software is starting to behave like content. The bottleneck is moving from can you build this to should this exist, and is it actually better than what's already there.

That's a great problem to have.

AMAZON_ASSOCIATES_US=...

style env vars for affiliate keys. Six countries in, I moved them all to a affiliate_keys

Postgres table. Should have done it on day one.Chista is on the App Store. Free tier covers 30 screenshots/month. Pro is $4.99/mo with a 14-day trial.

I'd love to hear what's in your camera roll graveyard.

This post mirrors a version on chista.app. The canonical link is set so dev.to credits the source domain for SEO.

── more in #artificial-intelligence 4 stories · sorted by recency
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/i-shipped-my-first-i…] indexed:0 read:4min 2026-06-13 ·