03 / WORK / CASE STUDY
Naily — AI Nail Commerce App
A Flutter commerce app — on-device AI nail sizing, AR try-on and custom press-ons. I took over all development and maintenance in November 2025.
- TYPE
- MOBILE APP
- SCOPE
- Pre-launch · takeover since 2025.11
- STACK
- FLUTTER · ONNX · FIREBASE · ECPAY
- LINKS
- Internal project (private)
01 / PROBLEM
Press-on nails are highly customized; customers can rarely judge their own nail sizes, so online orders often bounce back over fit. This app replaces in-store measuring with the phone camera and on-device AI, folding design → sizing → AR try-on → checkout → payment and logistics into one flow.
02 / CONSTRAINTS
- Inherited a multi-author codebase built by the original team (198 commits before the handover), with no transition period.
- AI inference must run on-device within phone-level compute — at handover, AR try-on ran at 1 FPS.
- Payments and personal data are involved: tokens live in secure storage only, logs must not capture full request bodies, iOS requires ATT consent. The app is in pre-launch readiness (P0–P2 audit fixes).
03 / ARCHITECTURE
A modular Flutter app: feature-first layering (config / models / services / screens) with declarative GoRouter navigation — 82 screens, 72 services, 44 models across 533 Dart files (~129k lines), talking to 123 backend API endpoints.
On-device AI is split into six single-purpose AR/CV packages running four ONNX models (YOLO11 nail detection/segmentation, hand landmarks), with an iOS platform channel to native CoreML. Commerce integrates ECPay payments/logistics/e-invoicing and four social logins; Firebase covers push, Crashlytics and analytics; CI runs three pipelines — staged CI, nightly full E2E, and tag-triggered signed releases.
04 / RESPONSIBILITIES
Took over in November 2025; the foundation and commerce flows were built by the original team. Since then all development, maintenance and releases are mine (121 commits, 85% of the period): FCM and tracking integration, the custom press-on feature, a points system, the AR rewrite, the iOS CoreML native layer, security hardening and CI/CD. The backend API is a separate service outside this repo.
05 / CHALLENGES → SOLUTIONS
CHALLENGE
At handover, AR try-on ran at 1 FPS, with the design overlay flickering and drifting during detection.
SOLUTION
Retired three generations of old implementations and rewrote it as five single-purpose packages (detection, rendering, classic CV, mask recolor, manual studio), moving iOS detection to native CoreML, plus cross-frame hysteresis to kill flicker. FPS went from 1 to realtime; the core detection page shrank from 3,051 to 1,356 lines.
CHALLENGE
Core screens were multi-thousand-line monsters — order detail at 5,256 lines, checkout at 3,416 — where every change rippled everywhere.
SOLUTION
Set an 800-line-per-file cap and split by UI region and logic: order detail went 5,256 → 230 lines (logic extracted); the cart/checkout/subscription trio went 6,800 → 1,200 lines plus standalone widgets.
CHALLENGE
Expired tokens logged users out mid-session, and pre-launch security hardening was thin.
SOLUTION
Added 401 intercept-and-refresh across seven services (seamless renewal), and hardened for launch with native-layer obfuscation, Dart obfuscation, certificate pinning and root/jailbreak detection.
06 / SYSTEM FACTS
82
screens
~129k
lines of Dart
121
commits since takeover
64
test files (unit + e2e)
07 / LESSONS
The first step in a takeover is not refactoring — it is writing the conventions down. Once rules are explicit, every change makes the system more consistent instead of more divergent.
Trust git, not prose: this project's CHANGELOG was reconstructed after the fact and its dates don't match the commits. Records worth keeping should be generated with tags, not backfilled.
NEXT
Naily Storefront & Canvas Product Customizer