All projects

Daily Vibe

A small site to drop by each day — read a line meant for today, or draw a tarot card when you're unsure about something. It sells a feeling, not features.

Date08/2026Tech
  • Next.js 16
  • React 19
  • TypeScript
  • Tailwind CSS 4
  • Zod
  • Zustand
  • React Hook Form
  • Gemini API
Daily Vibe

Highlights

  • A line for you: open the page and it's already there, unchanged for the whole day.
  • Two tarot modes — draw 1 card for a quick question, spread 3 cards for something you're stuck on.
  • AI readings grounded in your own story. Works without AI too: the app drafts the question for you to take to ChatGPT or Gemini.
  • Results stay the same all day — refreshing never changes them, because that would break trust.
  • A full 78-card tarot deck.
  • Your private questions stay private and never leak through the link.
  • All copy written in natural Vietnamese — no machine translation, no sloganeering.

About the project

Daily Vibe is a personal project I started in August 2026, now live at daily.liqwy.com.

The idea is simple: a small page people drop by each day, feel a little better, and leave. Two parts are open — “A line for you” and “Tarot” (draw one card, or spread three).

What decides whether this product lives isn't features but two things. One: results must be stable per day — if a refresh changes the line, users realize “oh, it's just random” and stop trusting it. Two: the copy must sound like a person, because one hollow sentence does more damage than any bug.

The tarot reading uses AI to interpret the drawn cards against what the user actually asked. When AI isn't available the app still works: it drafts the question for users to take to ChatGPT or Gemini themselves.

Under the hood

  • Next.js 16 (App Router, Turbopack) + React 19 + Tailwind CSS 4; Zod as the source of both types and validation, Zustand for session state, React Hook Form for forms.
  • Every result is derived from a day seed (day boundary at UTC+7) instead of randomness — deterministic, so a refresh never changes it.
  • The reading route re-draws the cards from the seed instead of accepting them from the client, so nobody can tamper with the request to get a reading for arbitrary cards.
  • Readings call the Gemini API; without an API key the app falls back to a copy-prompt flow.
  • Source data (the quote set and the 78-card deck) is read server-side only and never bundled to the client — lighter pages, and the deck stays hidden.
  • Private questions are sent via POST, not query strings, so they stay out of logs and Referer headers.

Got questions?

I'm always excited to collaborate on innovative and exciting projects!