WallpaperMachine
당신이 사랑하는 배경화면, 맥에서 새롭게 만나보세요
원본 78장 카드의 몰입형 3D 타로 독서 방, 손으로 섞고 뽑아 해석, 무료·개인·영어·베트남어 지원
An immersive 3D tarot reading chamber with an original 78-card deck. Shuffle, draw by hand and reflect on your reading — free, private, in English and Vietnamese.
라이프스타일TypeScript · CSSGitHub @LeQuy-123온라인운영자 미확인
써 보셨어요? 한 번만 눌러 주세요. 로그인은 필요 없어요.
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗An immersive 3D tarot reading web app with an original 78-card deck, an AI interpreter, and full English / Vietnamese support.
Pick a spread, ask a question, then shuffle, draw and turn your own cards on an astral table rendered in WebGL. When the last card is revealed, ARCANA weaves the actual cards, their positions and orientations into a written reading you can explore card by card, save, and come back to later.
▶ Try the live demo — no sign-up, nothing to install, works on phones.
ARCANA is built for reflection, culture and entertainment. It does not predict the future and is not professional advice — see the in-app legal notice.
| 🔮 Do a reading | Four spreads — Daily Guidance (1 card), Past · Present · Future (3), The Crossroads for decisions (5) and the classic Celtic Cross (10). Add an optional question and pick a tone: gentle, direct, poetic or practical. |
| 🃏 Draw by hand | Shuffle, then draw each card from the deck and turn it over yourself — by mouse, touch or keyboard — or skip straight to the result. |
| 📜 Read the interpretation | A theme for the whole spread, a paragraph per card in its position, how the cards relate, patterns (shared elements, Major Arcana, reversals), reflection questions, small next steps and a closing summary. Tap any card for its full meaning. |
| 📚 Explore the deck | An encyclopedia of all 78 cards with search and suit filters: upright and reversed meanings, keywords, symbols and what each card means as a situation, challenge, advice or outcome. |
| 🕰️ Keep a history | Every reading is saved on your device and can be reopened (or re-interpreted) later. |
| 🌐 Switch language | One tap switches everything — interface, all 78 cards, the card artwork's titles and the readings themselves — between English and Tiếng Việt. |
| ♿ Make it comfortable | Reduced motion, a 2D mode, high contrast, larger text, optional sound, full keyboard control and screen-reader announcements. |
ANTHROPIC_API_KEY is configured.| Area | Technology |
|---|---|
| Framework | Next.js 16 (App Router, Turbopack, Cache Components), React 19, TypeScript |
| 3D | Three.js with React Three Fiber and drei — custom table, sky shader, particles and card meshes |
| Animation | Motion for UI transitions; CSS keyframes for ambient effects |
| Styling | Tailwind CSS 4 with a small custom design system (gold-on-midnight tokens, engraved type) |
| AI | Claude via the official Anthropic SDK, with structured outputs validated by Zod |
| Testing | Vitest and Testing Library — 79 unit, integration and component tests |
| Hosting | Vercel (static pages plus one serverless API route) |
crypto.getRandomValues, done once up front. Animations
can never influence which cards you get, and the card back is symmetric so a reversal can't be spotted early./api/reading checks the deal (right count, right positions, no duplicates,
known card ids), rebuilds every card's meaning from its own data, and validates the model's answer against a Zod
schema — including that it discusses exactly the cards drawn, in order. Failures come back as typed, retryable
errors; a reading is never made up. The route is rate-limited and has a request-size cap and a timeout.lib/tarot/art): a unique illustration for each Major Arcana card, engraved suit emblems for the minors, and a
star field seeded from each card's id. No third-party artwork is used.localStorage, and a
question leaves the device only if the user turns AI interpretation on.sitemap.xml, robots.txt, a web app manifest with
install icons, and a version, commit and build-time stamp in the footer of every deploy.Requires Node.js 20.9 or newer.
git clone https://github.com/LeQuy-123/tarrot.git
cd tarrot
npm install
npm run dev # http://localhost:3000
The app works immediately in its offline-archive mode. To enable AI readings:
cp .env.example .env.local and set ANTHROPIC_API_KEY=...If AI interpretation is on but no key is configured, the reading shows a clear "isn't set up" message with a link to Settings — the cards are still drawn and saved.
| Script | What it does |
|---|---|
npm run dev | Development server |
npm run build / npm start | Production build / serve it |
npm run typecheck | Generate Next route types, then tsc --noEmit |
npm run lint | ESLint (Next core-web-vitals, TypeScript and React Compiler rules) |
npm test | Vitest suites |
npm run check | typecheck + lint + test |
Server-side only — never prefix these with NEXT_PUBLIC_. The API key is read only inside the /api/reading route
handler and never reaches the browser bundle.
| Variable | Default | Purpose |
|---|---|---|
ANTHROPIC_API_KEY | — | Enables Claude for AI readings |
ARCANA_AI_PROVIDER | auto | Unset: Claude if a key is present, otherwise AI is unavailable. anthropic or mock force a provider |
ARCANA_AI_MODEL | claude-opus-5-5 | Override the Claude model |
ARCANA_AI_TIMEOUT_MS | 45000 | Abort provider calls after this long |
ARCANA_MOCK_FAIL | — | Mock only: simulate timeout, rate_limit, malformed, unavailable |
ARCANA_MOCK_DELAY_MS | 900 | Mock only: artificial latency |
Public, optional:
| Variable | Purpose |
|---|---|
NEXT_PUBLIC_SITE_URL | Origin for canonical links, sitemap.xml, robots.txt and the share card. Defaults to the Vercel production domain; set it for a custom domain |
NEXT_PUBLIC_ARCANA_OPERATOR, NEXT_PUBLIC_ARCANA_CONTACT_EMAIL, NEXT_PUBLIC_ARCANA_ADDRESS | Contact details shown on the legal notice |
The Claude provider uses structured outputs (a Zod schema), effort: "medium", and server-side refusal fallbacks
(fallbacks: "default", beta server-side-fallback-2026-07-01), so a policy decline on the primary model is retried
on the default fallback model. Remove those two fields in lib/ai/providers/anthropic.ts if you prefer declined
requests to stay declined.
Import the repository in Vercel — no settings are needed for the demo. Add ANTHROPIC_API_KEY in the project's
environment variables to offer AI readings. The rate limiter is in-memory per instance, which is fine for a demo; use
a shared store (for example Redis) before relying on it to cap API spend under real traffic.
app/
page.tsx landing page (animated hero, card ribbon, spreads, how it works)
reading/ the reading chamber
deck/ history/ settings/ legal/
api/reading/route.ts POST endpoint: validation, rate limit, error mapping
api/reading/status/ GET: is an AI provider configured?
sitemap.ts robots.ts manifest.ts opengraph-image.tsx icon.svg
components/
scene/ R3F canvas, environment (table, rings, sky, dust), camera rig, textures
cards/ 3D card and deck (shuffle animation), SVG→texture, 2D card images
spreads/ spread layout maths, 2D spread renderer, spread diagrams
reading/ reading flow orchestrator, setup, HUD, card detail, interpretation, history
deck/ encyclopedia with search and filters
ui/ header, footer, hero, landing sections, settings, sigils
lib/
tarot/deck/ 78 card records (data only) + Vietnamese translations + search
tarot/art/ procedural SVG artwork: frame, 22 Major illustrations, minor emblems, back
tarot/spreads.ts the four spreads: positions, labels, lenses, layout coordinates
tarot/selection.ts pure shuffle / deal / validate functions
tarot/random.ts crypto RNG + seeded PRNG for tests
reading/machine.ts pure reducer for the reading flow
reading/interpretation.ts offline archive reading vs. AI endpoint, chosen by the setting
ai/ schemas, prompt context, engine, providers (anthropic, mock), client fetcher
i18n/ English / Vietnamese messages and language store
storage/ validated localStorage stores (history, settings)
site.ts site URL and shared SEO metadata
types/tarot.ts shared domain types
tests/ Vitest suites
| Spread | Cards | Positions |
|---|---|---|
| Daily Guidance | 1 | Today's Lens |
| Past · Present · Future | 3 | Past, Present, Future |
| The Crossroads (decision) | 5 | Heart of the Matter, Path A, Path B, Unseen Factor, Counsel |
| Celtic Cross | 10 | Present, Challenge (crossing), Foundation, Recent Past, Crown, Near Future, Self, Environment, Hopes & Fears, Outcome |
Each position carries an interpretation lens (self, obstacle, guidance, outcome), and every card has a
sentence for each lens, so position-specific meaning comes from data rather than templates.
next/dynamic (ssr: false) from a client component.Space / Enter / D draw · R reveals the next card · A draws and reveals everything · ← / → move between revealed cards · S / Esc skip animations or close a card.
The art is emblematic (no human figures), pip cards 3–10 share one arrangement per number across suits, and a few small details (the Chariot's sphinxes, Judgement's trumpet) are crude at thumbnail size.
ARCANA is presented as a tool for self-reflection, culture and entertainment, not fortune-telling. A bilingual
disclaimer appears in the footer of every page except the full-screen chamber, which links to the notice from its
setup screen and reading panel. The full notice (/legal) covers: no predictions or guarantees, not professional
advice, no paid readings / rituals / "giải hạn" plus a scam warning, lawful use, AI-generated content, data and
privacy, age, and artwork.
Keep it that way when extending the product: avoid paid predictions, ritual or bad-luck-removal services, and
promises about the future. The AI system prompt (lib/ai/context.ts) also forbids recommending rituals or paid
services, asking for money or personal data, and claiming certainty. The notice is not legal advice — get proper
legal review before charging users or targeting a specific market.
The header's EN / VI toggle (also in Settings) is saved in the browser; visitors whose browser language is Vietnamese get Vietnamese by default. Pages render in English on the server and switch after load, so there is no hydration mismatch, but Vietnamese visitors may briefly see English on first paint.
Keep these true, or update components/legal/LegalNotice.tsx (and its "Last updated" date) when they change:
localStorage (arcana.history.v1, arcana.settings.v1,
arcana.lang.v1); Settings → "Clear all data on this device" removes all three.NEXT_PUBLIC_ARCANA_* contact variables before a public launch; until then the Contact section says no
contact details have been published.