A family wish list app with an Aladdin / Arabian Nights theme. Each family member has their own wish list for birthdays and gifts. Accounts are managed in-app with parent/child types β parent accounts are PIN-protected so kids can't peek at what's being bought for them.
Built with vanilla HTML/CSS/JS wrapped in Capacitor for Android. Designed and built with AJ (age 9).
- π§ Each family member has their own wish list
- β Rate how badly you want each wish (1β5 stars)
- π° Add price and a link to the item
- β Mark wishes as "Got It!" when received
- π Parent accounts are PIN-protected β kids can't log in as parents
- ποΈ Secretly mark items as "being bought" β visible to other family members but hidden from the wish owner (no spoilers!)
- π± Native Android app β all data stored on-device, no server needed
- βοΈ Add/remove accounts in-app β no config files to edit
- π΅ Savings tracking β parents record cash gifts (birthday money, gift cards etc.) for each child; children see their total balance and a breakdown of where it came from
- π Grant wishes with savings β when a parent grants a wish, they can choose to deduct the cost from the child's savings (FIFO β oldest gifts spent first); if savings fall short, the parent is warned of the gap and asked to confirm they'll cover the difference
- π·οΈ Can-afford badge β wishes the child has enough savings to buy are highlighted
- βοΈ Edit wishes β tap any wish card to edit its name, link, price, or star rating (the wish owner or any parent can edit)
- π Granted wish history β granted wishes are hidden by default and revealed with a toggle; each one can be tapped to see when it was granted and exactly which savings contributions paid for it
The repo contains two separate versions:
| Version | Files | Storage | Use Case |
|---|---|---|---|
| Android app | www/ |
IndexedDB (on-device) | The real app β no internet needed |
| Web/Express app | index.html + server.js |
CSV file on disk | Local development / testing only |
The Android app in www/ is the primary version. It is entirely self-contained β no server, no internet connection, no account required.
www/
index.html β Full SPA: all UI, routing, and business logic in one file
db.js β IndexedDB wrapper (accounts, wishes, settings, savings stores)
pin.js β PIN hashing (Web Crypto SHA-256) + lockout logic
Capacitor bundles these files as static assets inside the Android APK and renders them in a native WebView. The JavaScript in www/ calls Capacitor plugin APIs for native features (haptic feedback, status bar, splash screen).
All data lives in an IndexedDB database called wishmaster_db (schema version 2) with four object stores:
- accounts β family members (name, emoji, colour, type
child|parent, hashed PIN) - wishes β wish items (owner account key, name, link, price, star rating 1β5, status
active|got_it,being_bought_by,grantedAt,savingsAllocations) - settings β app title, first-run flag
- savings β cash gift contributions per child (owner key, original amount, remaining amount, optional note, date added)
Each savings contribution tracks how much of the original gift amount remains unspent (remainingAmount). When a parent grants a wish and chooses to deduct from savings, contributions are spent oldest first (FIFO). The portions used are recorded on the wish as savingsAllocations so the full payment history is preserved even if a contribution is later deleted.
- App opens β User select screen (tap your avatar)
- Child accounts β straight into the app
- Parent accounts β PIN entry (4 digits, SHA-256 hashed, 3 attempts before 30s lockout)
- Main app β bottom tab bar shows every family member's list
- Children see their available savings balance at the top of their list; tapping it shows a breakdown of each gift
- Parents see a "π° Manage" button on each child's list to add or remove cash contributions
- "Cast a Wish" FAB β modal to add a new wish to the current user's list; tapping any active wish card opens the same modal pre-filled for editing
- Other users can claim "I'm buying this!" β hidden from the wish owner; parents also get a "Grant Wish!" button to mark a wish as received
- When a parent grants a child's wish and the child has savings, a dialog asks whether to deduct from savings; if savings don't fully cover the price, a warning shows the shortfall and asks the parent to confirm they'll cover the rest
- Granted wishes are collapsed by default; the toggle reveals them newest-first; tapping one shows the grant date and a savings breakdown
wishmaster/
www/ β Android app (self-contained, no server)
index.html β Full SPA (HTML + CSS + JS)
db.js β IndexedDB storage layer
pin.js β PIN hashing + lockout logic
android/ β Capacitor-generated Android project
app/build.gradle β App config: package ID, SDK versions, signing config
variables.gradle β SDK versions (min 26, target 36)
assets/
icon.png β App icon source (used by Capacitor assets tool)
server.js β Express server (for local web development only)
index.html β Web version entry point (requires server.js)
config.json β Web version config (family members, port)
capacitor.config.json β Capacitor config (appId, webDir, plugins)
package.json β npm scripts and dependencies
The Android app runs fine in a desktop browser for rapid development:
npm install
cd www && npx serve .
# Open http://localhost:3000
Open Chrome DevTools β Application β IndexedDB β wishmaster_db to inspect stored data.
- First launch (empty DB) β redirects to account management with welcome title
- Add child account β login works without PIN
- Add parent account with PIN β login prompts for PIN
- Correct PIN β access granted
- Wrong PIN Γ 3 β 30-second lockout with countdown timer
- After lockout expires β can try again
- Add wish with all fields (name, link, price, stars) β saves correctly
- Tap an active wish card β edit modal opens pre-filled; update saves correctly
- "I'm buying this!" shows to other users but hides from the wish owner
- Parent sees "Grant Wish!" button on a child's active wishes
- Grant wish with sufficient savings β deduction dialog β savings deducted FIFO β wish moved to granted
- Grant wish with insufficient savings β warning shows shortfall β confirm covers rest β partial deduction recorded
- Grant wish choosing "No, keep savings" β wish granted, savings unchanged
- Grant wish with no price set β dialog offers to deduct full savings balance
- Granted wishes hidden by default; toggle reveals them newest-first
- Tap a granted wish β detail modal shows grant date and savings breakdown
- Savings balance bar shows correct total; tap opens breakdown modal
- Can-afford badge appears on wish when savings β₯ price; disappears when savings drop below price
- Parent adds savings contribution β balance updates immediately; note and date shown in breakdown
- Parent deletes savings contribution β balance updates; already-recorded allocations unchanged
- "Got it!" moves wish to completed section
- Delete removes wish permanently
- Switch user returns to user select screen
- Data persists across full browser page reload
- Node.js 18+
- Android Studio β developer.android.com/studio
- During install: include Android SDK and API 36 build tools
- Java JDK 17+ β bundled with Android Studio
# Install Node dependencies (Capacitor CLI, Android bridge)
npm install
# Copy www/ assets into the Android project
npx cap sync android
# Open the Android project in Android Studio
npx cap open android
- On your phone: Settings β About Phone β tap Build Number 7 times (enables Developer Options)
- Settings β Developer Options β enable USB Debugging
- Connect via USB and accept the debugging permission dialog on the phone
- In Android Studio: select your device in the toolbar, then click Run βΆ (or Shift+F10)
First build takes 5β10 minutes while Gradle downloads dependencies. Subsequent builds are fast.
In Android Studio: Tools β Device Manager β Create Device β choose Pixel, select API 36 system image.
To see www/ changes instantly on your phone without rebuilding, add this to capacitor.config.json temporarily (remove before a release build):
"server": {
"url": "http://YOUR_LOCAL_IP:8080",
"cleartext": true
}
Then serve the web files:
npx serve www
Your Android device will now load from your machine live.
- App icon appears in launcher
- Splash screen is dark purple (no white flash)
- Status bar colour matches theme
- Content does not appear under notch or Android navigation bar
- Bottom tab bar sits above the Android nav bar
- FAB clears the bottom tab bar
- Haptic feedback fires on wish add, delete, and "Got it!"
- PIN keypad is comfortable to use one-handed
- Data survives force-close and device restart
- Portrait orientation only (no landscape breakage)
keytool -genkey -v -keystore wishmaster-upload.jks \
-alias wishmaster -keyalg RSA -keysize 2048 -validity 10000
Store this file securely. Never commit it to git. If you lose it you cannot update the app on the Play Store.
storeFile=../wishmaster-upload.jks
storePassword=YOUR_STORE_PASSWORD
keyAlias=wishmaster
keyPassword=YOUR_KEY_PASSWORD
The signing config is already wired up in android/app/build.gradle β it reads from this file automatically.
npx cap sync android
Play Store (AAB β recommended):
cd android && ./gradlew bundleRelease
# Output: android/app/build/outputs/bundle/release/app-release.aab
Direct-install APK (sideloading / testing):
cd android && ./gradlew assembleRelease
# Output: android/app/build/outputs/apk/release/app-release.apk
adb install android/app/build/outputs/apk/release/app-release.apk
Or copy the APK to your phone and open it (enable "Install from unknown sources" in settings).
- Go to play.google.com/console
- Create a developer account β one-time fee of USD $25
- Accept the developer distribution agreement
| Asset | Size | Notes |
|---|---|---|
| App icon | 512 Γ 512 px PNG | Arabian lamp design |
| Feature graphic | 1024 Γ 500 px PNG/JPG | Banner at top of store listing |
| Phone screenshots | At least 2, up to 8 | 9:16 portrait recommended |
Recommended screenshot scenes:
- Account selection screen (lamp animation + account cards)
- Wish list view with savings balance bar and can-afford badge
- "Cast a Wish" modal open
- Savings breakdown modal (child view)
- Grant wish deduction dialog (parent view)
- Granted wish detail with savings allocation breakdown
- PIN entry screen
- Account management screen
Google Play requires a privacy policy even for apps with no network access. Host a simple page (GitHub Pages works). Sample text:
Wishmaster stores all data locally on your device using IndexedDB.
No data is transmitted to any server. No personal information is collected.
No analytics, advertisements, or external network requests are made.
- Category: Entertainment or Utility
- Targets mixed audience (children and parents)
- No violence, sexual content, or controlled substances
- Complies with Google Families policy (no ads, no external data collection)
- Create a new app in Play Console (select Free)
- Fill in the store listing: title, short description (β€80 chars), full description (β€4000 chars)
- Upload icon and feature graphic
- Add at least 2 phone screenshots
- Add your privacy policy URL
- Complete the content rating questionnaire
- Set target countries
- Upload the signed
.aabfile - Submit for review β first-time submissions typically take 3β7 days
Title: Wishmaster πͺ
Short description: Tell your family what you really want. No more socks. No more duplicates. No more wrong gifts.
Full description:
πͺ Got a birthday coming up? Christmas? A random Tuesday?
Wishmaster is the magical wish list app that makes sure everyone in your family knows exactly what you want β with zero chance of getting the wrong thing.
No more socks. No more duplicates. No more "oh you shouldn't have" (but secretly you agree).
β¨ FOR THE WISHERS
β’ Write your wishes. All of them. Go wild.
β’ Rate how badly you want each one with 1β5 stars (you know which ones get 5 β)
β’ Add the link so there's absolutely no excuse for getting the wrong one
β’ Watch your wishes get ticked off one by one π―
π΅οΈ FOR THE BUYERS (the grown-ups)
β’ Secretly claim "I'm buying this!" so no one else buys the same thing
β’ The wish owner can't see who's getting them what β no spoilers!
β’ Parent accounts are PIN-locked so nosy kids stay out π
β’ Grant a wish with one tap when it arrives
π° YOUR MONEY, TRACKED
β’ Got birthday money? Gift cards? Grandma's annual fiver?
β’ Parents log every contribution β you see your balance and where it came from
β’ Wishes you can already afford get a shiny "Can afford!" badge β
β’ Parents can spend your savings to grant a wish automatically
π± NO INTERNET? NO PROBLEM
β’ Everything lives on your device β no account, no cloud, no nonsense
β’ Works on planes, in the middle of nowhere, absolutely anywhere
π¨ LOOKS PRETTY GREAT TOO
β’ Magic lamp. Flying carpet. Stars. Gold. You get it. π
Designed by AJ (age 9) and built with Dad (Trev) using Claude Code. πͺ