
One feedback inbox for seven iOS apps: a Supabase edge function
A shared submit-feedback endpoint for seven indie apps: validation, rate limits without storing IPs, private screenshots, Telegram alerts, RLS with no policies.
Writing
What I learned building, reviewing, pricing and marketing my own React Native apps — App Review, RevenueCat, AdMob, ASO, landing pages and the tooling around them. Written from the commit history, not from memory.
23 posts

A shared submit-feedback endpoint for seven indie apps: validation, rate limits without storing IPs, private screenshots, Telegram alerts, RLS with no policies.

Moving a feedback admin from Next.js to a static Vite SPA: the anon key plus RLS as the only gate, email-link and PKCE traps, and a CSP that fits antd.

RevenueCat counts app user IDs, not people, and gross revenue, not proceeds. Reading Lockboxy's numbers honestly, and moving debug builds to the Test Store.

How I build seven indie iOS apps alone: one React Native stack, native Swift engines, Maestro flows, device checklists and a Next.js landing per app.

Talkzy was rejected under guideline 2.3.7 for pricing in its screenshots. What was flagged, how I fixed the set, and the check that now guards the listing.

How Lockboxy got from three guideline 2.5.1 rejections to approval: a new default screen, swept onboarding, a rewritten listing and plain review notes.

Removing a submission that carries an app's first in-app purchase can leave a phantom Ready for Review state and 500 errors. The order that works, step by step.

How I run AdMob in two React Native apps: an ad unit per placement, interstitials only at natural breaks, rewarded trials, UMP consent and app-ads.txt.

Paywall patterns from my React Native apps on RevenueCat: an honest trial timeline, a one-time exit offer, offer codes, and showing buyers their plan.

How my seven iOS apps spot a newer App Store version with Apple's public lookup, once a day, without nagging, in ten languages and with no server of my own.

How I wrote native App Store keywords for ten locales with no paid ASO tool, and a small Python check that rejects wasted or risky words before I paste them.

What I put on seven static app landing pages so Google and AI answer engines can find and quote them: guides, FAQPage JSON-LD, llms.txt, robots and sitemaps.

Why my seven iOS apps use .io.vn domains from Mắt Bão, the three DNS records that point them at Vercel, and what to check before a domain ships in a build.

Two AI agents shared one checkout and their commits landed on each other's branches. What the reflog showed, and the worktree rules I follow now.

How Lockboxy encrypts on the iPhone: an Argon2id key from the passcode, a wrapped data key, chunked AES-256-GCM, Keychain storage, backups and honest limits.

A Next.js storefront on ECS hit p95 38s and 50k/min 5xx at peak. The cache stampede, sticky 404s and socket growth behind it, and the in-region k6 rig.

Moving Saramin Vietnam's admin from Next.js and Prisma to a Vite + antd SPA on httpOnly cookies and CSRF, and three auth bugs that passed every typecheck.

How a 24/7 YouTube livestream platform keeps a stream alive when its encoder dies: epoch fencing, careful failover, a KEDA plan for 0 to 50 pods, 10GB uploads.

A one-click save for creators: a BullMQ worker that tags in the background with retries, and a Manifest V3 extension with page adapters and an offline queue.

A characterful display font with tight tracking made ầ, ữ, ợ and ệ collide. The fix: Be Vietnam Pro 800, -0.015em, line-height ~1.16, the vietnamese subset.

One Node script renders every cover and diagram on my blog with the Chrome already on my Mac: theme tokens from the site's CSS, a 2x render, WebP under 200 KB.

After buying Lockboxy Premium, the app still showed the paywall. How I built the paying customer's view: a membership read, honest status lines, tests.

Search Console for seven app domains and a personal one: domain vs URL-prefix properties, a Mắt Bão TXT trap, sitemap timing, when to request indexing.