NewPlatano

I Built an AI Tattoo App with Expo - Here’s Everything I Learned

Beto, December 2, 2025 · 6,279 views

I recently launched an AI tattoo try-on app built with Expo and React Native, and in this video, I share everything I learned from the process. I cover the full tech stack, the challenges of publishing to the App Store, and my marketing approach to get users. This tutorial is for mobile developers interested in AI integration, app publishing, and building polished native experiences.

I also explain why I chose to ship iOS first, how I integrated Google’s Gemini AI models for realistic tattoo generation, and the tools I used for authentication, payments, and analytics. If you want to build your own AI-powered app or learn from real-world experience, this video will save you time and headaches.

What's inside

  • Launching my AI tattoo app and the motivation behind it
  • Using Expo UI and Expo Router for a native feel and smooth navigation
  • Loading images efficiently with Expo Image and handling gestures like pinch and swipe
  • Integrating Google Gemini AI models (Nano Banana) for realistic tattoo generation
  • Authentication with BetterStack and Prisma for user management
  • Handling payments and subscriptions with RevenueCat
  • Using Vexo for analytics and session replays to understand user behavior
  • Publishing challenges, iOS-first strategy, and UI polish lessons

Launching my AI tattoo app and the motivation behind it

I wanted to build a real published app after many prototypes and lessons. The AI space is crowded with generic apps, many with poor UI or outdated AI models. After testing Google’s new Gemini image models (Nano Banana), I was blown away by the realistic image editing capabilities. This inspired me to create an AI tattoo try-on app that lets users generate and try tattoos on their own skin with realistic results.

I aimed for a simple, clean, and native-feeling app that stands out from the competition by properly using the latest AI tech and focusing on user experience. The app lets users explore tattoo styles, iterate on designs, and see results that look real.

Using Expo UI and Expo Router for a native feel and smooth navigation

For the tech stack, I chose Expo with Expo Router for navigation, which felt like a no-brainer for React Native apps. To achieve a native look and feel, I used Expo UI, even though it’s still in beta. Expo UI unlocked features like context menus and liquid glass effects that enhance the app’s polish.

I built custom context menus with SwiftUI for iOS, especially for the playground input screen. The app uses experimental features like glass effects at the top and bottom of the screen, which look amazing and add to the native polish. This approach helped me create a smooth and intuitive user interface.

Loading images efficiently with Expo Image and handling gestures like pinch and swipe

To load tattoo images, I used Expo Image, which provides fast loading with a blur placeholder effect. When scrolling quickly, you see a blur that quickly resolves into the full image, improving perceived performance.

The app supports gestures users expect, like pinch-to-zoom on tattoos. I also added swipe gestures to navigate between previous and next tattoo prompts or images. These interactions make the app feel responsive and natural.

Integrating Google Gemini AI models (Nano Banana) for realistic tattoo generation

The core AI functionality uses Google’s Gemini image models, nicknamed Nano Banana, accessed via their API. I created two API routes using Expo Router’s API routes feature: one for text-to-image generation and another for text-and-image-to-image editing.

The API routes validate requests with Zod and handle prompts sent from the app. This setup is extendable, allowing multiple images to be sent to the model for editing. All AI processing happens server-side via Expo Application Services (EAS) hosting, keeping the app lightweight.

Authentication with BetterStack and Prisma for user management

For authentication, I integrated BetterStack, which is easy to set up and has a nice Prisma integration. Prisma offers a fully managed Postgres database, which I use to store user data. This gives me full control over the database and the ability to query or migrate data as needed.

The app supports anonymous usage, so users can try it without signing in, but signing in unlocks more features. This flexibility improves user onboarding and retention.

Handling payments and subscriptions with RevenueCat

I use RevenueCat to manage in-app purchases and subscriptions. RevenueCat simplifies the complex process of handling payments on iOS and Android, including webhooks and receipt validation.

Currently, the app has over 350 customers and two paying subscribers, generating about $15 in monthly recurring revenue. Integrating RevenueCat required testing on real devices and setting up HTTPS endpoints for webhooks, which can be tricky but is essential for production apps.

Using Vexo for analytics and session replays to understand user behavior

To track user behavior and app usage, I integrated Vexo analytics. Vexo supports React Native and provides session replays, letting me watch how users interact with the app in real time.

This insight helps me identify usability issues and improve the user experience. Vexo also offers a promo code “betto10” for a 10% discount if you want to try it yourself.

Publishing challenges, iOS-first strategy, and UI polish lessons

Publishing an app is much harder than just writing code. I focused on shipping iOS first to validate the idea quickly and because some modules I used (like Expo UI context menus and SwiftUI components) are iOS-only.

Creating a beautiful UI requires taste, attention to detail, and recognizing when something feels off. I learned a lot by following designers and developers on X (Twitter) and watching their demos.

The app took about two months of part-time work to reach its current polished state. Testing on real devices was crucial to catch issues and improve transitions, animations, and overall flow. Simplicity and clarity always trump fancy animations if the app feels confusing.

Resources

CourseReact Native course

Premium resourcePro membership

Let's connect!

Had a win? Get featured on Code with Beto.Share your story