GlamUp Girls — Mobile Dress-Up Game (Flutter + Flame, TR/EN/AR)
Kendi ürünüm — bağımsız yayın
(73 ratings) 8480 views
A dress-up game live on Google Play with 11 models, 918 wardrobe pieces and four pet packs: a Flutter + Flame client, server-side purchase verification on Firebase Cloud Functions, three languages, and Arabic right-to-left layout defects closed by measurement rather than guesswork. Started in April 2026, in production on Play since 20 August 2026; PEGI 3, built under the family-policy rules.
Build value: $60,000 Potential value: $750,000
GlamUp Girls — Mobile Dress-Up Game
GlamUp Girls is a dress-up game: pick a model, do her makeup, choose hair and clothes, walk the runway. Eleven models, 918 wardrobe pieces, four pet packs, weekly and monthly contests. It speaks Turkish, English and Arabic, with voice lines in each. First commit on 7 April 2026; production release on Google Play on 20 August 2026. Rated PEGI 3, listed under Casual, and bound by Play's family policy.
I would rather explain how it was built than what it does. In a casual game the visible part, the art and the animation, is the small part. The time goes into the content pipeline, the scoring math, verifying purchases on the server, and the rules that come with a children's category. Every number below was measured in the repository, not estimated.
What Is in the Game
- 👗 11 models, each split into 15 categories, 918 wardrobe pieces in total
- 🐾 4 pet packs (cat, dog, pony, unicorn), 193 pieces
- 🌟 Runway score: 4 categories in free style, 5 in contest mode, normalized to 0-100
- 🏆 Weekly and monthly contests, a rare-item collection
- 🌍 TR / EN / AR interface, right-to-left layout for Arabic, voice lines in every language
- 🛡️ A parental gate on purchase entry points; child-directed ad treatment with a G content rating
The Work
The client is Flutter + Flame: 398 Dart files and 155,283 lines under lib/. Business logic sits in 81 service classes and screen state in the 10 classes under lib/store. Persistence is local-first on SharedPreferences scoped to the user id, with cloud sync kept in a separate layer so that offline play never depends on it. The server side is Firebase Cloud Functions: 15 callable functions, a 2,770-line index.js and a separate 629-line module for purchase verification.
Key Outcomes
✅ 14,081 normalized webp sprites across 23 asset packs; color-variant counts enter the code from a 1,134-entry table generated by scanning the assets, never typed by hand
✅ Purchases are never trusted from the client: StoreKit 2 JWS signatures on iOS, the Play Developer API on Android, verified on the server; a receipt cannot be replayed
✅ All 43 screens pass an overflow test at 13 device widths between 320 and 1024 dp
✅ 3,883 test cases in 424 test files, plus 27 emulator test files on the Firestore/Functions side
✅ The Arabic punctuation drift was closed by measurement (36.1 px), and a 261-line guard test keeps it closed
Content Pipeline
The wardrobe is modeled as 11 models × 15 categories; behind the 918 piece definitions sit 23 asset packs and 14,081 normalized webp sprites. Color variants took the most time. I used to type the counts by hand. Whenever a pack gained a piece the table went stale and the game showed the wrong variant count. Now an asset scan produces 1,134 (pack, prefix) entries and embeds them straight into the code. The table cannot go stale, because there is no hand-kept table any more.
Outfit Scoring
Scoring lives in its own 15-file module, 1,583 lines, six of them analyzers. A free-style look earns up to 25 points in each of four categories; contest mode adds Theme Fit and normalizes five categories at 20 points each to a 0-100 scale. A five-tier rarity multiplier sits on top, from Common ×1.00 to Legendary ×1.25. These are constants in the code, not notes in a comment, so a design change touches one place.
Three Languages and Right-to-Left
Interface text lives in 51 ARB files across 17 namespaces: 6,342 key lines in English, 6,333 in Turkish, 6,567 in Arabic. Twenty-seven separate i18n tests check parity between the files and catch English leaking into the Arabic screens.
The real lesson was on the Arabic side. When Latin text such as a username lands inside an Arabic sentence, the exclamation mark and the full stop drift to the wrong side. I measured it with TextPainter instead of eyeballing it: unisolated, the exclamation mark rendered at x=0.0; wrapped in Unicode FSI/PDI isolates it rendered at x=36.1. Once the difference was a number, the fix was small. To keep it from coming back, a 261-line source guard test counts the EdgeInsets.only, fromLTRB, Positioned and TextAlign usages that silently draw on the wrong side in RTL, and excludes the symmetric ones.
Voice: 30 lines per language, 22 for the guided tour and 8 reactions. Turkish and English come from edge-tts (tr-TR-EmelNeural, en-US-AvaNeural), Arabic from Azure Speech (ar-EG-SalmaNeural). Each language is pinned to a single voice, so the character does not change voice from screen to screen.
Server Side and Purchases
Purchase verification happens on the server, not in the client. iOS uses the StoreKit 2 JWS signature, Android the Play Developer API. A verified transaction is written under verified_purchases/{transactionId} with an atomic create, so the same receipt is valid neither twice nor on another account. Errors fall into three classes: a genuinely invalid receipt and a configuration error are blocked; a transient network error or a 5xx fails open. That last choice is debatable. I preferred a short window of leniency over locking out a child who has already paid because of a server hiccup.
Children's Category and Compliance
In-app purchase entry points sit behind a parental verification dialog that cannot be dismissed by tapping outside it: an addition question with both terms drawn at random from 12 to 19 (answers 24 to 38), a new question 600 ms after a wrong answer, and a passed check cached for 15 minutes.
There is no such gate on the ad side, and I want to say so plainly, because my first draft claimed otherwise and the code proved me wrong. Ads are constrained by child-directed treatment and a G content rating; before the SDK initializes, the Google UMP consent flow runs with an 8-second timeout.
Test Surface
3,883 cases in 424 test files, with 27 emulator test files on the Firestore and Cloud Functions side. On top of those, 11 regression guards named *_guard_test.dart: six scan the source on disk and lock a code pattern in CI, five assert on behavior. The overflow matrix runs 43 screens at 13 device widths, and a separate coverage test compares the screen register against the *_screen.dart files on disk, so a new screen that is missing from the register turns CI red.
Current build value, $60,000: core production, three languages with RTL engineering, Arabic voice, children's-category compliance and the server side. Potential value, $750,000: the size it could reach with a full team and a marketing budget, not a revenue claim. Both come from a market survey done in August 2026, in which figures taken from vendor pages were corrected by adversarial verification.
Technical Challenges
- Hand-kept color-variant counts going stale; solved by generating the table from an asset scan
- Latin text inside Arabic sentences shifting punctuation; measurement plus FSI/PDI isolation
- Replaying a purchase receipt, or using it on another account; closed with an atomic create
- Keeping the purchase gate and the ad consent as two separate mechanisms in a children's category
- Forgetting to add a new screen to the overflow matrix; the coverage test catches it in CI
Why It Mattered
From the outside a casual dress-up game is a small job. From the inside it is five problems that have to be managed at once: content production, scoring math, payment security, three languages, and child compliance. In this project I closed all five by measuring and locking each one with a test; the result is visible in the store, in the purchase flow, and on the Arabic screen.
By the Numbers
| Area | Value |
|---|---|
| Codebase | 398 Dart files, 155,283 lines, 81 services |
| Wardrobe | 11 models × 15 categories, 918 pieces + 193 pet pieces |
| Sprite pool | 23 packs, 14,081 webp, 1,134 variant entries |
| Localization | 51 ARB files, 17 namespaces, 3 languages, 30 voice lines per language |
| Tests | 424 files, 3,883 cases, 27 emulator tests, 11 guards |
| Server | 15 callable functions, server-side purchase verification |
Closing
The build on Play carries every line on this page. The observation I am left with: in a dress-up game the most expensive mistake is not in the art, it is in keeping a table by hand.
https://play.google.com/store/apps/details?id=com.glamupgirls.app