If you build wellness or healing apps, one request comes up again and again: "Can you make a fortune-telling app?"
I've been building iOS apps since 2014 — wallpaper apps, meditation timers, healing content — and I eventually tackled a daily tarot oracle app. What surprised me wasn't the technical complexity. It was the fortune-telling-specific design decisions that nobody writes about.
Rork handles the heavy lifting beautifully. But there are seven specific walls you'll hit with this genre. Here's how to get through all of them.
Why Tarot Apps Are Harder Than They Look
The concept seems simple: draw a card, display its meaning. Done.
But here's what actually happens when you start building:
- 78 cards worth of data need structure (name, upright meaning, reversed meaning, keywords, imagery)
- Daily reset logic requires careful design — device clocks can be manipulated
- Reversed card position handling varies wildly between user preferences
- AI-generated interpretations sound amazing in theory, cost real money at scale
- Monetization choice (subscription vs. one-time) isn't obvious for this genre
- App Store review has specific requirements for entertainment/divination content
Let's work through each one.
Challenge 1: Card Data Architecture
A standard tarot deck has 78 cards: 22 Major Arcana and 56 Minor Arcana. Each card needs at minimum:
{
"id": "major_00",
"name": "The Fool",
"upright_keywords": ["new beginnings", "freedom", "adventure"],
"reversed_keywords": ["recklessness", "impulsiveness", "poor planning"],
"upright_description": "A moment of pure potential stands before you...",
"reversed_description": "The warning here is about moving too fast...",
"image_key": "major_00"
}Prompt Rork with: "Design a JSON schema for 78 tarot cards and create a Supabase cards table with this structure. Then generate INSERT statements for all 22 Major Arcana as seed data."
This gets you a complete data foundation in one session. For the 56 Minor Arcana, do it in batches by suit (Wands, Cups, Swords, Pentacles).
On card imagery: Rider-Waite artwork is public domain in most countries, but some editions have additional copyright. Using AI-generated imagery or licensed asset packs eliminates legal uncertainty entirely.
Challenge 2: The Daily Reset Logic Trap
"Draw one card per day" sounds trivial. But if you rely entirely on device local time, users can advance their clock to redraw as many times as they want.
Tell Rork: "Implement daily card drawing logic. Store the drawn card in AsyncStorage with today's date as the key. If the user has already drawn today, return the stored card instead of drawing a new one."
const getTodayKey = () => {
const now = new Date();
return `drawn_card_${now.getFullYear()}_${now.getMonth()}_${now.getDate()}`;
};
const getOrDrawCard = async (): Promise<Card> => {
const key = getTodayKey();
const stored = await AsyncStorage.getItem(key);
if (stored) return JSON.parse(stored);
const randomCard = await fetchRandomCard();
await AsyncStorage.setItem(key, JSON.stringify(randomCard));
return randomCard;
};For premium features where the one-draw limit matters economically, implement server-side enforcement: a Supabase daily_draws table with a unique constraint on (user_id, draw_date). Duplicate inserts throw an error, which you handle gracefully on the client.
Challenge 3: AI Interpretation — The Real Cost Math
Personalized AI readings are the feature that separates good tarot apps from great ones. The user picks a card, types their question, and gets a reading that connects the two.
Prompt Rork: "Create an API route that takes a card name, its orientation (upright/reversed), and the user's question, then calls the Claude API to generate a 200-character interpretation in a warm, encouraging tone."
// app/api/interpret/route.ts
export async function POST(request: Request) {
const { cardName, isReversed, userQuestion } = await request.json();
const prompt = `The tarot card "${cardName}" in ${isReversed ? 'reversed' : 'upright'} position.
User's question: "${userQuestion}"
Provide a warm, encouraging interpretation in under 200 words.`;
const response = await anthropic.messages.create({
model: 'claude-haiku-4-5-20251001',
max_tokens: 400,
messages: [{ role: 'user', content: prompt }],
});
return Response.json({ interpretation: response.content[0].text });
}Cost reality: With claude-haiku-4-5, one interpretation costs roughly $0.0001. One thousand users each drawing once daily costs about $3/month. This means you can offer AI interpretation in your free tier without financial risk — and use it as a conversion driver toward premium.
Challenge 4: Reversed Card Position
About 30% of users find reversed cards unsettling. Giving them control converts anxious users into retained ones.
Tell Rork: "Add a 'Use reversed cards' toggle to the settings screen. Save the preference to AsyncStorage. When drawing a card, check this setting and apply a 30% probability of reversal if enabled."
const shouldReverse = async (): Promise<boolean> => {
const useReversed = await AsyncStorage.getItem('use_reversed_cards');
if (useReversed !== 'true') return false;
return Math.random() < 0.3;
};This tiny feature consistently appears in positive App Store reviews. "I love that I can turn off reversed cards" shows up more than you'd expect.
Challenge 5: The Journal Feature That Drives Retention
The single highest-impact retention feature I added: a card journal.
After drawing their daily card, users can write a short note — "What this card means to me today" — and save it. Over time, they build a personal record of their readings.
Tell Rork: "Create a daily_journals table in Supabase with user_id, card_id, draw_date, and note_text fields. Implement a journal list screen showing past entries sorted by date."
When users have 30 days of journal entries, churn drops dramatically. They've built something they don't want to lose.
Challenge 6: Monetization Design
After testing several models, this structure works well for tarot apps:
Free tier: Major Arcana only (22 cards), AI interpretations 5 times per month, journal limited to 3 entries.
Premium: Full 78-card deck, unlimited AI interpretations, unlimited journal, reading history access.
Pricing: $3.99/month or $29.99/year (annual at 37% discount).
Implement this with RevenueCat. Tell Rork: "Integrate RevenueCat with a custom paywall screen using a tarot/mystical aesthetic. Show the monthly and annual plans with the annual discount percentage highlighted."
The visual fit matters here. A generic subscription UI breaks the mood. Spend time on the paywall design — it's a direct conversion lever.
Challenge 7: App Store Review Requirements
Fortune-telling content requires an entertainment disclaimer. Without it, your review will likely be rejected or trigger a guidelines violation notice.
Add to your About or Settings screen: "This app is created for entertainment purposes only and does not make actual predictions or provide genuine advice."
In App Store Connect, set the age rating for "Frequent/Intense" mature content appropriately and categorize under Entertainment.
For subscriptions, Apple's Guideline 3.1.3 requires that subscription content be continuously updated. Your daily new card content satisfies this, but document it clearly in your review notes when submitting.
What I Learned Building This
Tarot apps aren't technically complex. The Rork-built skeleton works in half a day.
What takes time — and what users actually notice — is the writing quality in your card descriptions, the warmth of your AI interpretation prompts, and the small UX touches that make the daily ritual feel intentional.
If you make wellness or healing apps, fortune-telling is a genre worth exploring. The combination of daily habit, personalization, and genuine user meaning-making creates retention dynamics that most utility apps can't match.