RORK LABJP
MAX — Rork Max builds native Swift apps instead of React Native, supporting iPhone, iPad, Watch, TV, Vision Pro, and iMessageNATIVE — It unlocks native capabilities: AR/LiDAR, Metal 3D games, Dynamic Island, Live Activities, HealthKit, and Core MLCORE — Standard Rork generates iOS/Android apps with React Native (Expo), taking you from plain English to the app storesFUNDING — Rork raised $2.8M from a16z (Andreessen Horowitz)GROWTH — The platform now sees 743,000 monthly visits with 85% growthPRICING — Free to start, with paid plans from $25/monthMAX — Rork Max builds native Swift apps instead of React Native, supporting iPhone, iPad, Watch, TV, Vision Pro, and iMessageNATIVE — It unlocks native capabilities: AR/LiDAR, Metal 3D games, Dynamic Island, Live Activities, HealthKit, and Core MLCORE — Standard Rork generates iOS/Android apps with React Native (Expo), taking you from plain English to the app storesFUNDING — Rork raised $2.8M from a16z (Andreessen Horowitz)GROWTH — The platform now sees 743,000 monthly visits with 85% growthPRICING — Free to start, with paid plans from $25/month
Articles/Business
Business/2026-06-22Advanced

A Wallpaper App's Real Work Starts After Launch — Content, Retention, and Revenue Notes from Running One on Rork

A wallpaper app is decided less by its launch and more by how you tend it afterward. Building on a Rork implementation, here are field notes on scheduled publishing that keeps content fresh, onboarding that survives the first week, and a revenue setup whose per-download return doesn't thin out over time.

wallpaper app21Rork436RevenueCat25AdMob64Supabase29indie dev28retention8monetization47

Premium Article

After running several wallpaper apps, the assumption that changed most for me was this: launch is only the starting line. The day the app appears on the store feels like an achievement, but it's the months that follow that quietly split the apps that grow from the ones that fade.

The build itself got far lighter once Rork arrived. Describe the screens and features in plain English, and you get working React Native code back. But the same ease means more lookalike apps ship every week. What sets an app apart isn't the initial polish — it's how you keep tending it, day after day, once it's live.

Assuming you've assembled a wallpaper app in Rork, these are notes on the three areas that actually mattered to me once I moved into operations: keeping content fresh, surviving the first week, and a revenue design that doesn't thin out. Whether you're building your first one or already running one that has plateaued, I hope these land at a level you can act on.

Freshness Carries DAU — Use Scheduled Publishing to Add a Little Every Day

For wallpaper retention, the most direct lever is the feeling that there's "a little new" every time someone opens the app. Dump 200 images in at once and people exhaust them in a few days, then stop coming back. Release those same 200 at five a day, and each visit offers a small discovery.

Scheduled publishing is what supports this in practice. Give each piece of content a publish timestamp and only serve the ones whose time has passed. Without touching app code at all, setting a future publish date is enough to create a "grows a little every day" experience.

-- Supabase: wallpapers table, with published_at driving scheduled delivery
create table wallpapers (
  id uuid default gen_random_uuid() primary key,
  title text not null,
  category text not null check (
    category in ('nature', 'city', 'abstract', 'minimal')
  ),
  tags text[] default '{}',
  -- split thumbnail and full image to keep bandwidth down
  thumbnail_url text not null,   -- low-res preview (~400×700px)
  full_url text not null,        -- high-res original (1080×1920px+)
  is_premium boolean default false,
  is_active boolean default true,
  published_at timestamptz default now(),  -- a future time makes it scheduled
  download_count integer default 0,
  created_at timestamptz default now()
);
 
-- RLS: only published (published_at <= now) and active rows are readable
alter table wallpapers enable row level security;
 
create policy "Public wallpapers are readable when published"
  on wallpapers for select
  using (is_active = true and published_at <= now());

The key is to put the visibility filter in RLS (Row Level Security), not in app logic. Even if you forget where published_at <= now() on the query side, the policy won't return future rows, so an unpublished wallpaper can't slip into view by accident. I once relied on a client-side filter alone and had an unpublished batch flash through a stale cache for a moment — since then I always keep this second layer in place.

Surfacing new arrivals is also easier to operate when it's resolved on the data side.

// "New" tab: items published in the last 7 days, newest first
async function fetchNewArrivals(supabase: SupabaseClient) {
  const sevenDaysAgo = new Date(
    Date.now() - 7 * 24 * 60 * 60 * 1000
  ).toISOString();
 
  const { data, error } = await supabase
    .from("wallpapers")
    .select("id, title, thumbnail_url, is_premium, published_at")
    .gte("published_at", sevenDaysAgo)
    .lte("published_at", new Date().toISOString()) // exclude future, just in case
    .order("published_at", { ascending: false })
    .limit(30);
 
  if (error) throw error;
  return data;
}

The extra lte excluding future rows absorbs drift between server and client clocks. RLS makes it unnecessary in principle, but on a screen that orders strictly by date, being explicit avoids ordering surprises.

Operationally, all this takes is spreading the published_at values of a batch you made at the start of the month across future days, a few at a time. That sustains the experience of "an app updated daily" without posting by hand every day. After switching to scheduled publishing, the rhythm of return visits became visibly steadier for me.

Don't Lose Them in Week One — Onboarding and Reasons to Return

Even after a download, if the first few minutes say "this isn't for me," that person almost never comes back. First-week churn in wallpaper apps tends to come less from missing features and more from a first experience that's simply too flat.

What helped me was a light onboarding that asks for a category right after launch. Asking about taste just once lets you bias the initial home view toward that person. Keep the questions modest — confined to a single screen.

// Ask for one preferred category on first launch
function OnboardingCategory({ onDone }: { onDone: (c: string) => void }) {
  const categories = [
    { key: "nature", label: "Nature" },
    { key: "minimal", label: "Minimal" },
    { key: "abstract", label: "Abstract" },
    { key: "city", label: "City" },
  ];
 
  return (
    <View style={styles.wrap}>
      <Text style={styles.heading}>Pick a mood you like</Text>
      <Text style={styles.sub}>You can change this later</Text>
      <View style={styles.grid}>
        {categories.map((c) => (
          <Pressable
            key={c.key}
            style={styles.card}
            onPress={() => onDone(c.key)}
          >
            <Text style={styles.cardLabel}>{c.label}</Text>
          </Pressable>
        ))}
      </View>
    </View>
  );
}

The "You can change this later" line is there to lower the pressure of choosing. Make the first choice feel heavy and some people drop off right there. An easygoing tone tends to carry them forward.

As reasons to return, favorites and notifications work plainly. But notifications are easy to resent, so my rule is to limit the reason for sending to "a category you like has new arrivals." Send everyone the same promotional push and you'll swing them straight to notifications-off or uninstall.

// Notify only when a favorited category gets new arrivals
async function scheduleNewArrivalNotice(
  favoriteCategory: string,
  newCount: number
) {
  if (newCount <= 0) return;
 
  await Notifications.scheduleNotificationAsync({
    content: {
      title: "New wallpapers just landed",
      body: `${newCount} new in "${categoryLabel(favoriteCategory)}"`,
      data: { category: favoriteCategory },
    },
    // aim for a time people actually open, e.g. 8am next morning
    trigger: nextMorningAt(8),
  });
}

Make sure a user who opens from the notification lands on "new arrivals in their favorite category," not the top of the app. If the copy and the landing don't match, even an opened notification disappoints, and the next one goes unopened.

When reading retention, day-based survival rates anchored on install day are the clearest. The figures below are roughly where I feel a wallpaper app is healthy.

MetricStrugglingFeels healthy
Day-1 retention (D1)under 20%30% or more
Day-7 retention (D7)under 5%12% or more
Avg sessions in week oneunder 24 or more

More than the absolute numbers, watching how these survival rates move before and after you add scheduled publishing and onboarding gives you a clearer sense of whether a change worked.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
Scheduled publishing driven by a publish date, so a little new content appears each day — and why freshness moves DAU
Onboarding that keeps people past the first week, plus favorites and notifications turned into real retention
Pairing AdMob rewarded ads with RevenueCat so per-download revenue holds up after the launch surge fades
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

Business2026-05-15
A 50-Million-Download Developer Rebuilt an App with Rork Max — Honest Time and Revenue Comparison
An indie developer with 50 million total downloads rebuilt a wallpaper app using Rork Max. Honest breakdown of dev time, code quality, AdMob, RevenueCat integration, and revenue impact — with real numbers.
Business2026-05-12
I Built a Wallpaper App with Rork — An Honest Review from a Developer with 50M App Downloads
After running wallpaper and healing apps with 50M+ downloads since 2014, I prototype-tested Rork on the same genre. Here's my honest take on where it shines, where it struggles, and what it means for solo developers.
Business2026-05-04
Monetizing Healing Apps Built with Rork — A Creator's Strategy Guide
How artists and individual creators can build and monetize healing apps — wallpapers, meditation, breathing, sleep — using Rork. Covers AdMob, subscriptions, hybrid models, and long-term content strategy.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →