DEV Community

Xianghua Feng
Xianghua Feng

Posted on • Originally published at jackfeng1.substack.com

I Vibe Coded a Daily Tarot App in 2 Months with Cursor + Cloudflare — Here's What AI Can't Do (Yet)

A few months ago, I had a clear idea for a project: a clean, free daily tarot reading site where people could draw cards and get meaningful interpretations — no paywalls, no dark patterns, no "your future is blocked, upgrade to unlock." The result is dailytarot.io, a fully working tarot reading web app featuring one-card, three-card, Celtic Cross, and Yes/No spreads, plus a full 78-card meaning library. It took me roughly two months of vibe coding to get there — and the journey taught me a lot about where AI shines, and where it absolutely cannot replace a human eye.


The Stack: Why I Went All-In on Cloudflare

When I started the project, I wanted the simplest possible hosting setup that could still scale if the site somehow got traction. I landed on the Cloudflare full-stack combo:

  • Cloudflare Pages for hosting the frontend
  • Cloudflare D1 (SQLite at the edge) for storing card data, spreads, and interpretations
  • Cloudflare R2 for storing card images and static assets

The beauty of this trio is that they integrate seamlessly. D1 bindings slot right into your Pages functions, R2 is just an environment variable away, and the whole thing deploys from a GitHub push. Zero cold start anxiety, generous free tiers, and no AWS invoice trauma. If you're building a content-heavy side project and haven't tried Cloudflare's full-stack offering, dailytarot.io is basically a live demo of what it can pull off.


The Tooling: Cursor + Two Different AI Brains

My primary coding environment was Cursor with the built-in Composer 1.5. This was the workhorse — generating route handlers, building the card spread UI, writing the D1 query logic, scaffolding components, and iterating on layout. Composer is excellent for sustained, multi-file "build this feature" sessions where you're essentially pair programming with the AI and letting it hold context across your whole repo.

For debugging, I brought in Claude Opus 4.6 separately. Whenever something broke in a subtle or confusing way — a D1 migration not applying correctly, a card spread state management bug, an R2 presigned URL that worked locally but not in production — I'd paste the relevant context into Opus and ask it to reason through the problem. The difference in reasoning depth between the two models for hairy debugging tasks was noticeable. Opus would often surface the actual root cause rather than just suggesting surface-level patches.

The workflow looked roughly like this:

  1. Composer 1.5 to scaffold and iterate fast
  2. Claude Opus 4.6 when something made no sense and I needed genuine reasoning
  3. Rinse, repeat, deploy to Cloudflare Pages

The Part AI Really Struggled With: Tarot Card Meanings

Here's the thing nobody tells you about building a tarot app: the hardest part isn't the code. The hardest part is the content.

Dailytarot.io covers all 78 tarot cards — Major Arcana and both suits of the Minor Arcana — each with upright and reversed meanings across multiple reading contexts (love, career, health, general guidance). That's a lot of interpretive content.

My initial assumption was: "I'll just prompt an AI to generate all the card meanings, review them quickly, and be done in a weekend." I was deeply wrong.

The Problem with AI-Generated Tarot Interpretations

When I asked AI models to generate tarot card meanings, I got text that was fluent, nicely formatted, and often subtly wrong in ways that matter to people who actually use tarot. The issues fell into a few categories:

Tone mismatches. Traditional tarot interpretation has a specific register — it's reflective, not prescriptive. AI-generated text tended to drift toward either generic self-help language ("embrace your inner strength!") or overly ominous warnings that would genuinely upset someone who drew a reversed Tower on a hard day.

Contextual inconsistency. A card's meaning shifts meaningfully depending on spread position. The Three of Swords in a "past" position reads very differently from the same card in a "future" position. AI would often produce meanings that ignored positional nuance or contradicted themselves across spread types.

Accuracy drift on esoteric details. Some cards carry specific traditional symbolism — Rider-Waite imagery, Thoth system variations, numerological associations — that AI would casually get wrong or blend into a mash. For users who know their tarot, this destroys trust instantly.

False positivity/negativity on reversals. AI models have a detectable tendency to soften reversed card meanings. Reversed cards aren't just "the upright meaning but slightly bad" — they often carry completely distinct archetypal weight. The AI kept flattening this distinction.

What I Had to Do Instead

I ended up doing a manual review pass on every single card meaning. Not just a skim — I cross-referenced traditional sources, checked positional logic, adjusted tone, and rewrote sections that were subtly misleading. This is what turned a "two-week project" into a two-month project.

AI was still useful here — it was a great first draft engine and a good sparring partner when I was trying to articulate why a meaning felt wrong. But a human had to make the final call on every interpretation that would actually appear on dailytarot.io. For a product where people are drawing cards during vulnerable moments in their lives, "good enough" AI output wasn't acceptable.


What Vibe Coding Actually Looks Like (The Good Parts)

I don't want to sound overly negative about the AI coding experience — because for the code itself, Composer was genuinely transformative. Here's where it genuinely saved me:

Feature scaffolding at speed. Saying "add a Celtic Cross spread with these 10 positions, store the draw in D1, and display results with card flip animations" and watching Cursor scaffold that across multiple files in one shot — that's the vibe. It would've taken me a week to write that by hand; Composer did a working draft in minutes.

Cloudflare integration boilerplate. D1 and R2 have their own quirks (binding declarations, wrangler.toml configuration, the way you reference env in Pages Functions). Composer just knew this stuff. I didn't have to spelunk through docs every time I needed a new integration point.

CSS and responsive layout. I have the design taste of a senior engineer but the CSS skills of someone who learned it in 2009. Composer handled responsive card grid layouts, spread diagrams, and the card flip animation CSS without me having to suffer through flex vs. grid debates.

Iteration speed. "This doesn't look right, move the card image to the left and make the interpretation text scroll independently" — done in 30 seconds. The feedback loop for UI iteration was genuinely fast in a way that made me feel like the product was alive.


Lessons Learned for Anyone Building a Content + AI Site

If you're planning to vibe code something where AI-generated content is part of the product (not just the tooling), here's what I'd tell myself at the start:

Budget real time for content QA. AI is a first-draft machine, not a publisher. Factor in human review time before you ship, especially if accuracy or tone matters to your users.

Domain knowledge is irreplaceable. The reason I could catch the AI's tarot meaning errors is that I spent time understanding tarot before building the app. If you're building in a domain you don't understand, AI content QA becomes nearly impossible.

Separate your "build fast" model from your "think deep" model. Using Composer for iteration and Opus for debugging was the right call. Don't use the heavyweight model for everything — you'll blow your budget. But don't use the lightweight model when you actually need reasoning depth.

Cloudflare's free tier is shockingly good for side projects. D1, R2, and Pages together cover a meaningful amount of traffic before you pay a dollar. For a project like dailytarot.io, it's essentially free infrastructure for a real production app.


The Result

Dailytarot.io is live, free, and covers the full 78-card tarot deck with multiple spread types. Every meaning has been human-reviewed. The app runs on Cloudflare's edge with zero servers to manage.

Would I do it again? Absolutely. The two months felt long in the moment, but compare it to building the same thing without AI assistance — that would've been six months at minimum, or I simply wouldn't have done it. Vibe coding got a real product shipped. The lesson is just that "vibe coding" doesn't mean "no judgment required." It means you bring the judgment; the AI brings the velocity.

If you draw a card today, I hope it's a good one. 🃏

Top comments (0)

The discussion has been locked. New comments can't be added.