
Một hộp thư góp ý cho bảy app iOS: một edge function trên Supabase
Endpoint submit-feedback dùng chung cho bảy app indie: validate, rate limit mà không lưu IP, screenshot riêng tư, báo qua Telegram, RLS không có policy.
Bài viết
Những gì mình học được khi tự xây, đưa qua App Review, định giá và quảng bá các app React Native của riêng mình — RevenueCat, AdMob, ASO, landing page và bộ công cụ xung quanh. Viết từ lịch sử commit, không phải từ trí nhớ.
23 bài

Endpoint submit-feedback dùng chung cho bảy app indie: validate, rate limit mà không lưu IP, screenshot riêng tư, báo qua Telegram, RLS không có policy.

Chuyển admin đọc góp ý từ Next.js sang SPA Vite tĩnh: anon key cộng RLS là cổng duy nhất, bẫy email link và PKCE, và một CSP vừa với antd.

RevenueCat đếm app user ID chứ không đếm người, đếm doanh thu gộp chứ không phải tiền về tay. Đọc đúng số của Lockboxy, và chuyển bản debug sang Test Store.

Cách tôi một mình làm bảy app iOS: chung một stack React Native, engine Swift native, Maestro, checklist máy thật và một landing Next.js cho mỗi app.

Talkzy bị App Review từ chối theo guideline 2.3.7 vì screenshot có giá. Khung nào bị dính, mình sửa bộ ảnh ra sao và script nào giờ đang canh phần listing.

Lockboxy đi từ ba lần bị từ chối theo guideline 2.5.1 đến lúc được duyệt: đổi màn hình mặc định, rà lại onboarding, viết lại listing, screenshot, review notes.

Rút một bản nộp đang mang in-app purchase đầu tiên có thể để lại trạng thái Ready for Review ma và lỗi 500. Thứ tự làm đúng, từng bước một.

Cách mình chạy AdMob trong hai app React Native: mỗi vị trí một ad unit, interstitial ở điểm dừng tự nhiên, rewarded, UMP và app-ads.txt.

Pattern paywall với RevenueCat trong app React Native: timeline trial trung thực, exit offer một lần, offer code và hiện gói cho người đã mua.

Bảy app iOS của tôi phát hiện bản mới trên App Store bằng lookup công khai của Apple, mỗi ngày một lần, không làm phiền, mười ngôn ngữ, không server riêng.

Cách mình viết keyword App Store bản địa cho mười locale mà không dùng tool ASO trả phí, cùng một script Python chặn từ thừa hoặc rủi ro trước khi dán vào ASC.

Những gì mình đặt lên bảy landing page tĩnh để Google và các công cụ trả lời bằng AI tìm thấy, trích dẫn được: guide, FAQPage JSON-LD, llms.txt, robots, sitemap.

Vì sao bảy app iOS của mình dùng domain .io.vn mua ở Mắt Bão, ba bản ghi DNS để trỏ về Vercel, và những gì phải kiểm tra trước khi đưa domain vào build.

Hai AI agent dùng chung một checkout và commit của chúng rơi nhầm sang branch của nhau. Reflog cho thấy gì, và bộ quy tắc worktree mình dùng từ đó.

Cách Lockboxy mã hoá trên iPhone: khoá Argon2id từ passcode, khoá dữ liệu được bọc, AES-256-GCM theo chunk, Keychain, backup và những giới hạn thật.

Storefront Next.js trên ECS chạm p95 38s và 50k lỗi 5xx/phút lúc đỉnh. Cache stampede, sticky 404, socket phình vô hạn, và rig k6 chạy cùng region.

Chuyển admin Saramin Vietnam từ Next.js + Prisma sang SPA Vite + antd dùng cookie httpOnly và CSRF, cùng ba bug auth đã qua mọi lượt typecheck.

Cách một nền tảng livestream YouTube 24/7 giữ stream sống khi encoder chết: fencing bằng epoch, failover cẩn thận, kế hoạch KEDA 0 đến 50 pod, upload 10GB.

Nút lưu một chạm cho creator: worker BullMQ gắn tag ở nền có retry, cùng extension Manifest V3 với adapter theo trang và hàng đợi lưu offline.

Một font display cá tính, tracking âm sâu làm dấu của ầ, ữ, ợ, ệ đè lên nhau. Cách sửa: Be Vietnam Pro 800, -0.015em, line-height ~1.16, subset vietnamese.

Một script Node render mọi ảnh bìa và sơ đồ của blog bằng chính Chrome có sẵn trên Mac: token theme từ globals.css, render 2x, sharp nén WebP dưới 200 KB.

Mua Premium của Lockboxy xong, app vẫn hiện paywall. Cách mình dựng màn hình cho khách đã trả tiền: đọc gói riêng, dòng trạng thái trung thực, test.

Search Console cho bảy domain app và một domain cá nhân: domain hay URL-prefix property, bẫy TXT ở Mắt Bão, lúc nộp sitemap, khi nào cần request indexing.