Este artículo solo está disponible en inglés. Estamos trabajando en traducciones al español.
Tarot Agent: Building an AI Tarot Reading App with Nuxt 3 and Claude AI
How Tarot Agent uses Nuxt 3, Vue 3, Tailwind CSS 4, and Claude AI to create a free, streaming tarot reading experience with custom pixel-art cards.
thelacanians
The Best AI Products Are Focused
Most AI products try to do everything. They bolt a chat interface onto a general-purpose model, add a dozen integrations, and call it a platform. The result is a tool that does many things adequately and nothing well.
Tarot Agent takes the opposite approach. It does exactly one thing: AI-powered tarot readings. You type a question, pick a spread, and get a streaming interpretation backed by Claude AI with custom pixel-art Major Arcana illustrations. No accounts, no paywalls, no feature bloat. Open the page and ask your question.
This is what focused AI product design looks like.
The Stack
Tarot Agent is built on Nuxt 3 with Vue 3, styled with Tailwind CSS 4, and powered by Claude AI from Anthropic. The deployment target is Vercel with SSR enabled.
Nuxt 3 (Vue 3 + SSR)
├── Tailwind CSS 4 (custom mystic theme)
├── Claude AI (Anthropic SDK)
├── Nuxt Color Mode
├── Lucide Icons
├── Google Fonts (Cinzel + Inter)
└── Vercel (deployment + edge)
The choice of Nuxt 3 over a plain Vue SPA is deliberate. Tarot Agent needs server-side rendering for SEO and social sharing — when someone shares a reading, the preview card should actually say something meaningful. More importantly, Nuxt server routes provide a clean way to proxy Claude API calls without exposing API keys to the client.
How the AI Readings Work
The core interaction is deceptively simple: user asks a question, selects a spread type, and the app streams back a tarot interpretation in real time. Under the hood, this is a Nuxt server route calling the Anthropic API with streaming enabled.
The architecture follows a pattern we use often: the client makes a single request, the server route handles the AI interaction, and the response streams back token by token.
// server/api/reading.post.ts
import Anthropic from '@anthropic-ai/sdk'
const client = new Anthropic({
apiKey: useRuntimeConfig().anthropicApiKey,
})
export default defineEventHandler(async (event) => {
const { question, spread, cards } = await readBody(event)
const stream = await client.messages.stream({
model: 'claude-sonnet-4-20250514',
max_tokens: 2048,
system: buildTarotSystemPrompt(spread),
messages: [
{
role: 'user',
content: formatReadingRequest(question, cards),
},
],
})
// Stream tokens back to the client
setResponseHeader(event, 'content-type', 'text/event-stream')
setResponseHeader(event, 'cache-control', 'no-cache')
for await (const event of stream) {
if (event.type === 'content_block_delta') {
sendStream(event, event.delta.text)
}
}
})
The system prompt is where the personality lives. It instructs Claude to interpret the drawn cards in context of the question and spread positions, maintaining the voice of a knowledgeable but approachable tarot reader. The prompt engineering matters here — too formal and it reads like a textbook, too casual and it loses the sense of ritual that makes tarot readings feel meaningful.
On the client side, a Vue composable manages the streaming state:
<script setup lang="ts">
const reading = ref('')
const isStreaming = ref(false)
async function startReading(question: string, spread: SpreadType) {
const cards = drawCards(spread.cardCount)
isStreaming.value = true
reading.value = ''
const response = await $fetch('/api/reading', {
method: 'POST',
body: { question, spread: spread.name, cards },
responseType: 'stream',
})
const reader = response.getReader()
const decoder = new TextDecoder()
while (true) {
const { done, value } = await reader.read()
if (done) break
reading.value += decoder.decode(value)
}
isStreaming.value = false
}
</script>
The streaming is the key UX decision. A tarot reading that appears all at once feels like a search result. A reading that streams in word by word feels like someone is actually interpreting your cards. The latency becomes a feature.
Six Spread Types
Tarot Agent supports six spread types, each with its own layout and interpretation structure:
- Single Card — one card, one answer. Good for quick daily guidance.
- Yes/No — binary question, single card with a directional interpretation.
- Three Card — past, present, future. The classic spread.
- Love — relationship-focused positions covering self, partner, and the dynamic between them.
- Career — professional situation, challenges, and path forward.
- Celtic Cross — the full ten-card spread for deep, nuanced readings.
Each spread defines its positions, and the AI receives both the cards drawn and the positional context. A card in the “challenge” position of a Celtic Cross reads very differently than the same card in the “outcome” position. Claude handles this contextual interpretation naturally, which is exactly the kind of task LLMs excel at — synthesizing structured input into coherent narrative.
Pixel-Art Cards and Flip Animations
Every Major Arcana card has a custom pixel-art illustration. This is not a stock image library. The art style is intentional: pixel art gives the cards a distinctive, slightly retro aesthetic that stands apart from the ornate Victorian imagery most tarot apps use. It also keeps file sizes small and scales cleanly at any resolution.
The card reveal uses a CSS flip animation:
.card {
perspective: 1000px;
}
.card-inner {
transition: transform 0.6s cubic-bezier(0.4, 0, 0.2, 1);
transform-style: preserve-3d;
}
.card-inner.flipped {
transform: rotateY(180deg);
}
.card-front,
.card-back {
position: absolute;
inset: 0;
backface-visibility: hidden;
}
.card-back {
transform: rotateY(180deg);
}
The cards start face down, then flip to reveal the illustration when the reading begins. It is a small touch, but it adds the moment of anticipation that makes a tarot reading feel like a tarot reading, not just a text generation exercise.
The Dark Mystical UI
The visual design commits fully to its theme. The base background is a deep navy (#0a0a1a) with gold accents (#d4a853), built as a custom Tailwind CSS 4 theme:
@theme {
--color-mystic-dark: #0a0a1a;
--color-mystic-deeper: #06060f;
--color-mystic-gold: #d4a853;
--color-mystic-gold-light: #e8c97a;
--color-mystic-purple: #7c3aed;
--color-mystic-card: #1a1a2e;
--color-mystic-border: rgba(212, 168, 83, 0.2);
}
Typography pairs Cinzel for headings — a serif with engraved, classical letterforms that evoke the arcane — with Inter for body text, keeping the interface readable when the AI is streaming paragraphs of interpretation.
A subtle floating star animation in the background reinforces the mystical atmosphere without distracting from the content. The entire visual language says “this is a place for reflection,” which is exactly the mood you want when someone is asking a question they care about.
Single-Page Focus
Tarot Agent is a single-page application in the truest sense. There is no dashboard, no reading history, no user profiles, no social features. You arrive, you ask, you read. The entire flow lives on one page with state transitions managed by Vue’s reactivity system.
This is a product decision, not a technical limitation. Tarot readings are personal and ephemeral. Adding persistence would change the nature of the experience — suddenly it is a journal, not a reading. The constraint keeps the product honest about what it is.
From an engineering perspective, the single-page architecture simplifies everything. No router configuration beyond the Nuxt defaults. No auth flow. No database. The only server-side state is the streaming Claude API call. Deployment is a single Vercel project with one environment variable for the Anthropic API key.
Why This Matters
Tarot Agent is not interesting because of its tech stack — Nuxt, Vue, Tailwind, and Claude are all well-established tools. It is interesting because of what it chooses not to do.
The current wave of AI products suffers from feature anxiety. Every product wants to be a platform. Every chatbot wants to handle every domain. The result is a landscape of tools that are technically impressive and practically unfocused.
Tarot Agent picks one domain, builds a complete experience for it, and stops. The AI is not a general-purpose assistant wearing a tarot costume. It is a tarot reader. The UI is not a chat interface with a theme. It is a tarot table. The product does not ask you to sign up, subscribe, or integrate with anything. It asks you to ask a question.
This is the model we advocate for when building AI products: find a specific human experience that AI can genuinely enhance, build the minimum product that delivers that experience well, and resist the urge to add everything else. The constraint is the feature.
Try it at tarotagent.app. Ask it something you have been thinking about. The cards are waiting.