Inspiration

Every small seller I know has an AI image tool on their phone now. Their promo posters still look cheap.

The AI isn't the problem. The prompt is. "make me a sale poster" is five words and gets you a generic image. A poster that actually sells needs 150+ words of art direction: composition, lighting, type hierarchy, where the brand name sits, how the countdown reads. Nobody running a café or an online shop has time to write that, or knows what to write.

So I built the thing I wished existed: a library of those 150-word prompts, already written and ready to personalize.

What it does

PromptPoster is a curated library of 100+ hand-written AI image prompts for promo posters, sale & discount creatives, product launches, menus, events and Instagram carousels. Every card shows an example of what the prompt produces.

The core loop takes under a minute:

  1. Pick a poster: browse Home (spotlight rails, categories), search, or the Library: one filterable wall with a sticky filter bar (category, type, free/PRO) and honest sorting (Curated, New first, A–Z).
  2. Read the whole prompt: every prompt is written out in full, with its variables {BRAND_NAME}, {TAGLINE}, {DATE}, {TIME}, {HASHTAG} highlighted.
  3. Personalize: fill in your brand once and the prompt rewrites itself with a live preview. Brand Kit remembers your details on-device, so the next prompt is faster.
  4. Copy and paste into any AI image tool you already use.

Plus:

  • Moments: seasonal collections (Black Friday, Ramadan sales, year-end) surfaced before the date, with optional local reminders.
  • History & Saved: every prompt you've copied stays in your history, and re-copying never costs a copy again.
  • Content drops via push (opt-in, off by default), light & dark themes, in-app updates.

It is honest by design: PromptPoster is a prompt library, not an image generator. The app never pretends to make the image, and the store listing says so.

How I built it

  • 100% Kotlin + Jetpack Compose (Material 3), Navigation 3, Hilt, Room, DataStore, WorkManager, Coil.
  • 24 Gradle modules (:feature:*, :shared:ui, :core:*) with Konsist architecture tests that fail the build if a feature imports another feature or an SDK leaks outside its core module.
  • RevenueCat lives entirely in :core:billing:
    • Offerings.current decides which packages are sold, their order, localized prices and trial eligibility. Nothing about price is hardcoded.
    • The "Antasena Pro" entitlement drives PRO state as a Flow<Entitlements> that every screen observes.
    • A custom native Compose paywall driven by RevenueCat Offering Metadata: headline, description, benefits, CTA, featured package, trial badge and layout variant can all come from the dashboard, with safe in-app defaults. Today the live offering uses it to feature the Yearly plan (featured_package_id: $rc_annual). Copy and layout can change, and be A/B tested with RevenueCat Experiments and Targeting, without an app release.
    • Customer Center for self-serve subscription management, plus restore purchases.
  • Server-driven catalog: a static JSON manifest plus WebP thumbnails on Cloudflare, versioned through Firebase Remote Config, so new prompts ship without an app update.
  • Google Mobile Ads with UMP consent (rewarded + tightly capped placements), Firebase Analytics/Crashlytics, an FCM topic for content drops, Play in-app updates.

Challenges I ran into

  • Making "free" honest and still sustainable. The quota meter shows what's left ("3/5 today"), rewarded ads add copies but never unlock PRO, and re-copying from history is always free. Getting those rules right mattered more than any single screen.
  • The paywall. RevenueCat's hosted paywall didn't match the app's visual identity, but I didn't want to give up Offerings, Targeting or Experiments. I rebuilt it natively in Compose on top of Offering Metadata, with defaults for missing or future-version fields so a dashboard typo can never break checkout.
  • Designing for the catalog I'll have, not the one I had. The offline seed had 6 items and the live catalog has 104. I redesigned the catalog screen (Library) for 300–500 items with a sticky filter bar, and only offered sorts I could back with real data.
  • Release engineering. R8 and bundletool ran out of heap on release builds, and I added a build gate that refuses to produce a release bundle with test ad IDs.

Accomplishments that I'm proud of

  • Shipped a complete, working monetization stack on day one: three subscription plans (Monthly, 3-Month, Yearly with a free trial), a native paywall, Customer Center, rewarded ads and capped ads.
  • A distinct visual identity (Soft Studio) instead of default Material: warm sand and terracotta, a cocoa & gold PRO language, Nunito display type, JetBrains Mono for prompts.
  • A copy flow that goes from app open to prompt on the clipboard in under a minute.

What I learned

  • Let RevenueCat own what should change without a release (packages, prices, paywall copy, experiments) and keep in code what shouldn't (brand colors, contrast, accessibility).
  • Being honest about what the product is (a prompt library) makes the value proposition clearer, not weaker.

What's next for PromptPoster

  • Grow the catalog toward 300–500 prompts and add popularity/newest sorting once the catalog carries that data.
  • Run paywall experiments through Offering Metadata (copy, featured package, layout variant).
  • More carousel packs and regional Moments, plus purchasing-power-adjusted pricing.

Shipaton categories I'm entering

RevenueCat Design Award and HAMM Award. Details for each are in the category answers.

Built With

Share this project:

Updates

Submission history