-
-
Petame turns dreams, goals, and inspirations into vision boards that stay close to you every day.
-
Organize your vision boards in one place and create new boards whenever inspiration strikes.
-
Create personalized vision boards by combining photos, cutouts, and decorative elements on a customizable canvas.
-
Turn any photo into a clean, ready-to-use sticker with automatic background removal.
-
Unlock premium backgrounds and creative themes through a seamless subscription experience powered by RevenueCat.
-
Keep your goals visible every day with a beautiful vision board widget on your iPhone Home Screen.
-
Petame - app icon
Inspiration
Vision boards are a proven way to keep your goals in front of you — but a cork board on the wall can't follow you around, and most "mood board" apps stop at making something pretty. I wanted a board that is playful to build (like cutting out photos and pasting stickers as a kid) and that actually tracks whether your wishes come true. That became Petame: Vision Board — "picture your dreams, then make them real."
What it does
Petame turns your photos into a living vision board:
- 📸 Snap or pick a photo → instant sticker. On-device background removal (VisionKit) cuts out the subject automatically, so every photo becomes a paste-able sticker.
- ✍️ Attach a wish. Each sticker carries a short intention ("run a full marathon", "move to the coast") plus a category tag.
- ✅ Track it from "manifesting" to "achieved." Not just a mood board — when a wish comes true you check it off and the board celebrates it.
- 🎨 Make it yours. Free-form drag / pinch / rotate collage, 28 background designs (watercolor, cork, washi, sakura…), handwriting stickers drawn with Skia, and text stickers in 7 hand-picked fonts.
- 📱 Home Screen widget. Your board lives on your Home Screen (small & large families), so your dreams stay in sight every day.
- 📤 Share. Export a square image or a 9:16 story card with a motivational quote, localized per language.
- 🌏 4 in-app languages (EN / JA / KO / zh-Hans) and 8 App Store locales.
How I built it
- Expo SDK 56 + React Native 0.85 on the New Architecture, with the React Compiler enabled and expo-router typed routes.
- @shopify/react-native-skia + Reanimated 4 + Gesture Handler power the collage canvas: normalized [0,1] transforms so a board lays out identically on any device, a 25-step undo stack, and a handwriting tool with a native SwiftUI color picker.
- zustand + SQLite (expo-sqlite) as the local source of truth — no backend server, everything stays on device.
- expo-widgets + App Groups render the board into an iOS widget; a custom config plugin injects a live AppEntity picker so the widget's settings show your real board names.
- OneSignal for push (permission asked at the value moment — right after creating a board, never at launch), PostHog for product analytics.
How I use RevenueCat
RevenueCat is the entire monetization layer of Petame Pro:
- Custom paywall designed as a tear-off "Pro Pass" ticket (perforated edge, shimmer CTA, staggered entry animations), rendered generically from
getOfferings()— Monthly / Annual ("Best value") / Lifetime ("Yours forever"). - Honest trial disclosure: intro-price data is normalized to days and
checkTrialOrIntroductoryPriceEligibilitymakes sure "7 days free" is only shown to users who actually qualify. - Entitlement-driven gating: a single
Petame Proentitlement unlocks 50 boards, 100 stickers per board, premium backgrounds and the large widget; the free tier stays genuinely useful (1 board, 20 stickers). - Offer code redemption via
presentCodeRedemptionSheet()right from Settings. - Analytics joined end-to-end: the RevenueCat app user ID and pro status are PostHog super-properties, and every paywall view carries a typed source (
board_limit,sticker_limit,premium_background,settings) so I can see exactly which limit converts. - Purchase listener keeps entitlements in sync across purchase / restore / expiry, with localized error handling per RevenueCat error code.
Challenges I ran into
- Config-plugin ordering: OneSignal's plugin must run before expo-widgets or the widget extension loses its
aps-environmententitlement — the reasonapp.config.tsis TypeScript with carefully ordered plugins. - Widget memory limits: synchronous full-size image decode crashed the widget extension; boards are now auto-captured and downscaled to 720px JPEG before hitting the App Group.
- A 36.5 MB share image 😅 — the story export pipeline now produces ~660 KB.
- The iOS Simulator can't do background removal, so the core feature could only be tested on real devices.
- RevenueCat Test Store keys don't support Customer Center, so it's temporarily replaced with restore +
showManageSubscriptions()until production keys land.
Accomplishments I'm proud of
- Shipped v1.0.1 solo in ~7.5 weeks — 172 commits from empty repo to App Store submission.
- An onboarding that isn't a slideshow: a 6-step interactive tour where you build a real mini-collage and paste your first photo before you ever see the main screen.
- A data-driven ASO baseline: keyword research across 14 storefronts and 250+ keywords before writing a single line of store metadata.
- Thoughtful defaults everywhere: review prompts gated by real engagement (3 days / 3 launches / 3 stickers), pro-gating that never deletes user data, and graceful degradation when native modules are missing.
What I learned
- Monetization is a product feature, not an afterthought — typed paywall sources and trial-eligibility checks took hours to build and completely change what you can learn from week one.
- On-device ML (VisionKit subject segmentation) is finally good enough to build a whole UX around — as long as you design a fallback for older devices.
- Widgets are a retention feature disguised as a rendering problem.
What's next
- RevenueCat Customer Center once production API keys replace the Test Store.
- Android launch — the code ships dark (API key deliberately null so Test Store purchases can never leak into production).
- Board sharing between friends, more background designs, and richer "achieved" celebrations.
Built With
- expo.io
- onesignal
- posthog
- react-native
- react-native-reanimated
- react-native-skia
- revenuecat
- skia
- sqlite
- swiftui
- tailwindcss
- typescript
- visionkit
- widgetkit
- zustand
Log in or sign up for Devpost to join the conversation.