🔮
Next.js 15 · Supabase · Korean Saju Engine

แปะก่าจู้ · Saju Kaaju
ดูดวงสาจูเกาหลี อ่านดวงเป็นกระจก — คุยกับ "อาแปะ" ผ่าน AI

เว็บแอปดูดวงสาจูเกาหลี (사주팔자) ที่แยก "คำนวณ" ออกจาก "เล่า" — Python engine คำนวณ 4 เสาชะตาจากฐานดาราศาสตร์เกาหลี (KASI) จริง แม่นระดับนาที แล้วให้ อาแปะ (AI) เล่าเป็นภาษาคน อ่านดวงเป็นกระจกสะท้อนตัวเอง ไม่ฟันธง ไม่ขายความกลัว

Next.js 15 React 19 Supabase (RLS) Stripe Python · KASI korean-saju Gemini / OpenAI PWA
Empathize · Define

ปัญหาที่เจอ

ทำไมการ "ดูดวง" ออนไลน์ให้แม่นและอบอุ่นพร้อมกัน ถึงยากกว่าที่คิด?

สาจูเกาหลี (四柱 — 4 เสาชะตา) คำนวณยากมาก: เสาปีขึ้นกับ 입춘, เสาเดือนขึ้นกับ 12 절기, เสาชั่วโมงต้องแก้ 진태양시 ตาม longitude เพราะเวลามาตรฐานเกาหลีอิงเส้นเมอริเดียนญี่ปุ่น (คลาดได้ ~32 นาที) พลาดนาทีเดียวเสาเปลี่ยน คำทำนายเพี้ยนทั้งใบ — แล้วถ้าปล่อยให้ AI คำนวณเอง มันก็ "มโน" ตัวเลข

— โจทย์ตั้งต้น ก่อนเริ่มทำแปะก่าจู้
😱

ดูดวงออนไลน์ส่วนใหญ่ "ฟันธง" + ขายความกลัว

บอกว่าลื้อจะเป็นอย่างนี้แน่ ๆ แล้วปิดท้ายด้วยของมงคลให้ซื้อ — ไม่เหลือทางเลือกให้คนฟัง ไม่ได้ช่วยให้เข้าใจตัวเองจริง ๆ

📏

คำนวณสาจูเกาหลีให้แม่นระดับนาที ยากมาก

ต้องรู้จัก 입춘/절기 boundary, แก้ 진태양시 ตาม longitude, แยก 야자시/조자시 — พลาดนาทีเดียวเสาวัน/เสาชั่วโมงเปลี่ยน

🤖

ให้ AI คำนวณดวงเอง = มโนเลข

โมเดลภาษาไม่ใช่เครื่องคิดเลขดาราศาสตร์ — ถามว่าเสาชั่วโมงคืออะไร มันเดา (hallucinate) ตอบผิดแบบมั่นใจ เชื่อไม่ได้เลย

📜

ศัพท์ 오행 / 십신 / 격국 คนทั่วไปอ่านไม่รู้เรื่อง

ผลลัพธ์ของศาสตร์เป็นฮันจา/เกาหลีล้วน — ต่อให้คำนวณถูก ถ้าเล่าไม่เป็นภาษาคน คนก็ไม่ได้อะไรกลับไป

💳

ต้องมี auth จริง + โควตา + จ่ายเงิน โดยกันโกง

ไม่ใช่แค่หน้า demo — ต้อง login จริง, นับโควตาคำถามแบบกันแก้ฝั่ง client, รับเงินผ่าน Stripe แล้วเติมโควตาให้ถูกต้องแบบ idempotent


Ideate

วิธีแก้ปัญหา

แยก "เครื่องคำนวณข้อเท็จจริง" ออกจาก "คนเล่าเรื่อง" — engine แม่น ๆ ป้อน AI ที่พูดภาษาคน

🧩

แยก "คำนวณ" ออกจาก "เล่า" — กัน hallucination

Python engine คำนวณ 4 เสา, 격국, 용신, forecast เป็น ข้อเท็จจริง → ส่งให้ AI แค่ "เล่าต่อ" ไม่ให้ AI แตะการคำนวณเลย ตัวเลขจึงเชื่อได้

👴

"อาแปะ" — character voice อบอุ่น อ่านดวงเป็นกระจก

system prompt เป็นบุคลิกอาแปะชาวเกาหลี พูดตรงแต่มีเมตตา ไม่ขู่ ไม่ฟันธง ไม่ขายของมงคล — เหลือทางเลือกให้คนฟังเสมอ

🌱

เครื่องคำนวณสาจูเกาหลีของจริง (KASI)

ใช้ engine korean-saju ฝังข้อมูล KASI จริง แก้ 진태양시 ตาม longitude ของเมืองเกิด แม่นระดับนาที ครอบคลุมปฏิทินถึงปี 2050

📅

ปฏิทินดวง personalized + cache รายวัน

forecast รายวัน/รายยามอิงดวงกำเนิดของแต่ละคน — deterministic จึง cache ต่อ user ต่อวันใน DB ได้ เปิดซ้ำไม่ต้องคำนวณใหม่

🔒

โควตา + จ่ายเงินฝั่ง server เท่านั้น

หักโควตาด้วย Postgres function แบบ atomic, เปิด RLS ทุกตาราง, เติมเงินผ่าน Stripe webhook แบบ idempotent — client แก้โควตาเองไม่ได้


Prototype

วิธีทำงาน — 4 จังหวะ

ตั้งแต่กรอกวันเกิด จนอาแปะเล่าดวงให้ฟัง

1
📋

กรอกวันเกิด

Onboarding: วัน·เวลา·เมืองเกิด → ดึง longitude จาก city list

2
🧮

Engine คำนวณ

Python (KASI) คำนวณ 4 เสา + 격국/용신 → cache ลง DB

3
💬

อาแปะเล่า

AI รับข้อเท็จจริงมาเล่าเป็นภาษาคน แบบ streaming เบสวันเกิด

4
🌱

ปฏิทิน + คุยต่อ

เปิดปฏิทินดวงรายวัน → คุยต่อ → หมดโควตา → เติม 99฿


Prototype

Tech Stack & Architecture

Next.js เดียวจบ (web + api) บน Vercel · Python engine เป็น serverless function · Supabase คุม DB + Auth + RLS

หน้าเว็บ (PWA · mobile-first ≤768px)
แชตอาแปะ ปฏิทินดวง โปรไฟล์ + ผังธาตุ Onboarding
Next.js 15 (App Router) บน Vercel
/api/chat /api/calendar /api/onboarding /api/stripe
Saju Engine (Python · KASI) + AI อาแปะ (Gemini → OpenAI)
calculate.py forecast.py streaming prompt cache
Supabase (Postgres + Auth + RLS) + Stripe
profiles chats / messages quota_ledger stripe webhook
ทำไมเลือก stack นี้?

Next.js 15 App Router — web + API route + Python function อยู่ deploy เดียว แชร์ session ตรง ๆ · Supabase ตัวเดียวจบ Postgres + Google/Email Auth + merge-by-email + RLS — ลด moving parts · Python บน Vercel รัน engine korean-saju ที่ 0 dependency ได้เลย (คำนวณดาราศาสตร์ = งานของ Python) · Provider abstraction — สลับ AI (Gemini ↔ OpenAI ↔ Claude) ได้ที่ไฟล์เดียว ไม่ต้องแตะ route/UI


Prototype

สิ่งที่สร้าง — 8 ความสามารถหลัก

ครบ loop ตั้งแต่กรอกวันเกิด ถึงคุยกับอาแปะแล้วจ่ายเงินเติมโควตา

💬

แชตกับอาแปะ

ห้องแชต streaming เบสจากวันเกิด — ปักหมุด/เปลี่ยนชื่อ/ลบ/แชตใหม่ + starter prompts (ภาพรวม/การงาน/ความรัก/เงิน)

🧮

Korean Saju Engine

คำนวณ 4 เสา · 오행 · 십신 · 격국 · 용신 · 대운/세운 จากฐาน KASI จริง แก้ 진태양시 ตาม longitude

📅

ปฏิทินดวง personalized

forecast รายวัน/รายยามตามดวงผู้ใช้ — ไฮไลต์วันดี/ระวัง, ฤกษ์ยามราย ชม. → deep-link คุยกับแปะเรื่องวันนั้น

🎉

Onboarding + ผังธาตุ

กรอกวัน·เวลา·เมืองเกิด (city picker → longitude) → สร้างผังสาจู แสดง 4 เสา + สมดุลธาตุ (오행 balance)

👥

Multi-profile

ดูดวงให้คนอื่นได้ — สลับโปรไฟล์ (active profile), เพิ่มคนใหม่, แต่ละคนมีผังสาจู + ห้องแชตของตัวเอง

📜

รายงานดวงเต็ม + Reveal

สร้างรายงานดวงฉบับเต็ม + หน้า reveal พร้อม share card (html-to-image) และเสียงอาแปะเล่า (TTS)

🔒

Auth + โควตา atomic

Google + Email/Password (merge-by-email), หักโควตาด้วย Postgres function แบบ atomic + ledger append-only + RLS

💳

Payment + Admin หลังบ้าน

Stripe consumable (99฿ = 100 คำถาม) เติมผ่าน webhook idempotent + admin dashboard: ลูกค้า/โควตา/รายได้/cost


Prototype

หน้าตา — แชตกับอาแปะ

เปิดแอป → เห็นผังธาตุของตัวเอง → คุยกับอาแปะได้เลย บนจอเดียว (mobile-first)

👴 อาแปะ ผังธาตุ ปฏิทิน โควตา 8
เสา時 ยาม日 วัน月 เดือน年 ปี
ก้าน·กิ่ง 癸巳 丙寅 丙子 己巳
🌲 ไม้ 1 🔥 ไฟ 3 🏔 ดิน 1 ⚡ ทอง 0 💧 น้ำ 3
👴 อาแปะ ไฟในตัวลื้อแรงนะ — ดวงว่าใจร้อน ตัดสินใจไว มันไม่ได้แปลว่าลื้อไม่ดี มันแปลว่าไฟลื้อร้อน ถ้าใช้ถูกก็ให้ความอบอุ่น ถ้าใช้ผิดก็เผาตัวเอง ปีนี้ค่อย ๆ ก้าว อย่าเพิ่งรีบ
ภาพรวม การงาน ความรัก เงิน ปีนี้

Prototype · UI Craft

งานออกแบบ UI & Design System

มองแปะก่าจู้ในมุม Product Designer — ระบบ token, หน้าจอจริงจาก flow, และเหตุผลเบื้องหลังทุกการตัดสินใจด้าน UX

Design Tokens — ออกแบบเป็นระบบ
accent
#6D28D9
accent-dark
#4C1D95
accent-light
#EDE9FE
bg
#FDFBF6
text
#1C1917
border
#E7E5E4
H1 · 28 / 700แปะก่าจู้
Body · 16 / 400อาแปะเล่าดวงเป็นภาษาคน
Caption · 12IBM Plex Sans Thai · 300–700
spacing 4 8 12 16 24
radius 12px 16px
Screen Showcase — flow จริงบนมือถือ
ขั้นที่ 1 · Onboarding
บอกวันเกิดให้แปะดู
วันเกิด
14 มีนาคม 2537
เวลาเกิด
23:20 น.
เมืองเกิด
กรุงเทพฯ · 100.50°E

แปะขอไว้เปิดเสาให้เท่านั้น — เวลาเกิดยิ่งตรง เสายิ่งแม่น (ปรับ 진태양시 ตาม longitude)

ให้แปะอ่านให้
กรอกวันเกิด · ขอข้อมูลพร้อมบอกเหตุผล
โปรไฟล์ · ผังสาจู
ผังธาตุของลื้อ
時 ยาม
癸巳
日 วัน
丙寅
月 เดือน
丙子
年 ปี
己巳
🌲 ไม้1
🔥 ไฟ3
🏔 ดิน1
⚡ ทอง0
💧 น้ำ3

ไฟกับน้ำเด่น ทองพร่อง — ใจร้อนแต่คิดลึก แปะสรุปให้เป็นภาษาคน

ผังธาตุ 4 เสา · 오행 balance อ่านง่าย
ปฏิทินดวง · เดือนนี้
วันไหนควรก้าว วันไหนควรรอ
อาพฤ
1234567 891011121314 15161718192021
วันนี้ · ไฟแรง
ค่อย ๆ ก้าว อย่าเพิ่งรีบตัดสินใจเรื่องใหญ่ในวันนี้นะ
ก้าวได้: คุยงานระวัง: ปากร้อน
ปฏิทินดวงรายวัน · deep-link คุยกับแปะ
UI Decisions — ทำไมถึงเลือกแบบนี้
📱

Mobile-first แล้ว letterbox ที่ 768px

คนมาหาแปะบนมือถือเกือบทั้งหมด ออกแบบ 393 ก่อน แล้วขยับ 768 → 1440

ทำไม: บนจอใหญ่จัดกลาง (cap 768) ไม่ยืด layout ให้โล่งเก้อ — คงบรรยากาศ "โต๊ะน้ำชา" ที่สงบ ไม่ฝืนทำ desktop grid

Accessibility floor ที่ไม่ยอมลด

Base font ≥ 16px, touch target ≥ 44px, contrast ≥ 4.5:1 ทุก text/สีปุ่ม

ทำไม: กลุ่มผู้ใช้กว้าง อ่านคำอ่านยาว ๆ บนมือถือ — ตัวเล็กหรือปุ่มชิดกันคือ barrier จริง ไม่ใช่แค่ nice-to-have
💬

Microcopy พูดด้วยเสียง "อาแปะ"

Loading = "แปะกำลังชงคำอ่านให้ ใจเย็นก่อนนะ" · Error = "ไอ้หยา ระบบสะดุดนิดหน่อย ลองใหม่นะ"

ทำไม: state ที่คนหงุดหงิดที่สุด (รอ/พัง) คือจุดที่ character ต้องอยู่ — ไม่ทำให้ผู้ใช้รู้สึกผิดตอนกรอกพลาด
🧩

ผลอ่านเป็นการ์ด ไม่ใช่กำแพงข้อความ

ศัพท์ 오행/십신/격국 map เป็นไทยก่อนโชว์ + ซอยคำอ่านยาวเป็นท่อน/การ์ด + starter prompts

ทำไม: ต่อให้ engine แม่นแค่ไหน ถ้าเทข้อความก้อนเดียวคนก็ไม่อ่าน — visual hierarchy ทำให้ศาสตร์ที่ลึกกลายเป็นเรื่องเข้าใจง่าย

Test & Iterate

Hack กับปัญหา

6 โจทย์ที่ต้องคิดทางแก้เอง — ความแม่นของศาสตร์เกาหลี + การคุม AI + เงินที่พลาดไม่ได้

📏

เวลามาตรฐานเกาหลีอิงเส้นญี่ปุ่น — เสาชั่วโมงเพี้ยน

KST อิงเมอริเดียน 135° (ญี่ปุ่น) แต่โซลอยู่ 126.98° — เวลาสุริยะจริงช้ากว่า ~32 นาที เอา KST มาคิดเสาชั่วโมงตรง ๆ เสาผิด

แก้: ใช้ engine korean-saju ที่แก้ 진태양시 ตาม longitude ของเมืองเกิด + อ้าง 절기/입춘 boundary จาก KASI + แยก 야자시/조자시 — verify ตรง 100% กับ 35,000 วัน
🤖

ถ้าให้ AI คำนวณดวง มันมโนตัวเลข

โมเดลภาษาตอบเลขดวงแบบมั่นใจแต่ผิด — จะเชื่อคำทำนายไม่ได้ถ้าฐานตัวเลขมั่ว

แก้: แยกหน้าที่เด็ดขาด — Python engine คำนวณ "ข้อเท็จจริง" (เสา/격국/forecast) ส่งเป็น context ให้ AI, AI มีหน้าที่ "เล่า" อย่างเดียว + prompt caching ส่วน system + ผังสาจู กัน token บาน
🐍

รัน engine เกาหลี (Python) ร่วมกับ Next.js

เว็บเป็น TypeScript/Next.js แต่ศาสตร์คำนวณอยู่ในแพ็กเกจ Python — จะเอามารันบน serverless เดียวกันยังไง

แก้: วาง engine เป็น Vercel Python function (/api/*.py) — inject korean_saju/src เข้า sys.path, แพ็กเกจ 0 dependency จึง bundle ง่าย, Next.js เรียกผ่าน fetch ภายใน แล้ว cache ผลลง DB
💳

กันโกงโควตา + race condition ตอนหักเลข

ถ้าหักโควตาฝั่ง client แก้ได้เอง / ยิงพร้อมกันหลาย request อาจหักพลาดหรือติดลบ + เติมเงินซ้ำจาก webhook ที่มาซ้ำ

แก้: Postgres function consume_question() หัก free/paid แบบ atomic ใน query เดียว + RLS เขียนได้เฉพาะ service-role + quota_ledger append-only + Stripe webhook idempotent ด้วย stripe_session_id unique
👴

ศาสตร์เป็นฮันจา + AI ต้องอบอุ่นไม่ขู่

ผล engine เป็น 오행/십신/격국 ล้วน คนอ่านไม่ออก — และ AI default มักฟันธง/ทางการเกินไป ไม่ใช่เสียงอาแปะ

แก้: engine map ป้ายเป็นภาษาไทยก่อนส่ง + system prompt ฝัง brand pillars ของอาแปะ (อ่านดวงเป็นกระจก ไม่ขู่ ไม่ขายของมงคล เหลือทางเลือกเสมอ) + starter prompts พาคนเริ่มคุย

ปฏิทินเดือน = คำนวณหลายสิบวัน ช้า + เปลือง

เปิดปฏิทินมุมมองเดือนต้อง forecast ทุกวัน ถ้าเรียก Python ใหม่ทุกครั้งที่เปิด ทั้งช้าและเปลือง

แก้: forecast เป็น deterministic (ดวงเดิม + วันเดิม = ผลเดิม) จึง cache ต่อ user ต่อวันในตาราง daily_forecast_cache — เปิดปฏิทินเช็ค cache ก่อน ไม่มีค่อยเรียก engine แล้วเก็บไว้

Define

Design Decision ที่ตั้งใจเลือก

ขอบเขตที่จงใจ "ไม่ทำ" สำคัญพอ ๆ กับสิ่งที่ทำ

แปะก่าจู้จงใจ "อ่านดวงเป็นกระจก ไม่ฟันธงชะตา" — ไม่ขายของมงคล ไม่ขายความกลัว เหลือทางเลือกให้คนฟังเสมอ · engine คำนวณ AI เล่า (แยกหน้าที่กัน hallucination) · mobile-first cap 768px จัดกลางจอ ไม่ฝืนทำ desktop layout · โควตาเป็น consumable ไม่ผูกมัด subscription · มี disclaimer + 18+ ขอบเขตชัดตั้งแต่ต้น = implement ตรงและ maintain ง่าย

🫒
อ่านดวงเป็นกระจก

สะท้อนให้เห็นตัวเอง ไม่ฟันธง ไม่ขายความกลัว

🧩
Engine คำนวณ · AI เล่า

แยกหน้าที่เด็ดขาด กัน AI มโนตัวเลข

📱
Mobile-first ≤768

จัดกลางจอ (letterbox) ไม่ฝืนทำ desktop

🍵
99฿ consumable

เติมครั้งเดียว ไม่หมดอายุ ไม่ผูกมัด sub


Level Up · Reflect

Knowledge Domain ที่แข็งขึ้น

5 พื้นที่ความรู้ที่ระดับเราขยับขึ้นจริงจากการทำโปรเจกต์นี้

1. โหราศาสตร์เกาหลี / สาจู 사주팔자 — จาก 0 เป็นเข้าใจโครงสร้าง:

เข้าใจ 4 เสา (연·월·일·시), 오행 (5 ธาตุ), 십신, 격국, 용신, 대운/세운, และเหตุผลเชิงดาราศาสตร์เบื้องหลัง (진태양시, 절기, 입춘 boundary) — ลึกพอจะแปลงเป็น data model + UX ได้ บทเรียน: domain knowledge ที่ลึกจริงคือสิ่งที่ทำให้ product น่าเชื่อถือ ไม่ใช่แค่ UI สวย

2. Full-stack Next.js 15 + Supabase — App Router + RLS + Auth:

ทำ App Router (RSC), Supabase Auth (Google + Email/Password + merge-by-email), RLS ทุกตาราง, และหักโควตาด้วย Postgres function แบบ atomic บทเรียน: Supabase ตัวเดียวคุม DB + Auth + security surface ได้ — ลด moving parts ทำให้ทีมเล็กปล่อยเร็ว

3. Polyglot serverless — TypeScript + Python บน Vercel เดียวกัน:

เชื่อม engine Python (korean-saju, 0 dependency) เข้ากับ Next.js ผ่าน Vercel Python function + sys.path injection แล้ว cache ผลลง DB บทเรียน: เลือกภาษาให้เหมาะกับงาน — คำนวณดาราศาสตร์คือของ Python ไม่ต้องฝืนเขียนใหม่ใน TS

4. AI product engineering — provider abstraction + คุมไม่ให้มโน:

ทำชั้น provider ที่สลับ Gemini → OpenAI → template fallback ได้ที่ไฟล์เดียว, streaming, prompt caching, และกัน hallucination ด้วยการ inject ข้อเท็จจริงจาก engine + character/system prompt บทเรียน: คุม AI ด้วย "ขอบเขต + ข้อเท็จจริง" ไม่ปล่อยให้มันคิดเลขเอง

5. Payments & quota economics — เงินคือ path ที่พลาดไม่ได้:

ออกแบบ Stripe consumable + webhook idempotent + quota_ledger append-only + snapshot ราคา ณ ตอนซื้อ (แก้ราคาภายหลังไม่กระทบประวัติเก่า) บทเรียน: อะไรที่เกี่ยวกับเงิน ต้อง atomic + server-only + idempotent เสมอ ไม่มีข้อยกเว้น

35,000
วันที่ engine คำนวณตรง 100% (vs lunar-python)
8
ตาราง Postgres — เปิด RLS ทุกตาราง
15
เส้นทางในแอป (mobile-first)
0
dependency ของ Saju engine (pure Python)
Aw mascot

แปะก่าจู้ · Saju Kaaju

เว็บแอปดูดวงสาจูเกาหลี (사주팔자) ที่แยก "คำนวณ" ออกจาก "เล่า" — Python engine คำนวณจากฐานดาราศาสตร์ KASI จริงแม่นระดับนาที แล้วให้อาแปะ (AI) เล่าเป็นภาษาคน อ่านดวงเป็นกระจกสะท้อนตัวเอง สร้างด้วย Next.js 15 + Supabase + Stripe · mobile-first · PWA

Next.js 15 React 19 Supabase (RLS) Stripe Python · KASI korean-saju Gemini / OpenAI Tailwind 4 PWA
Projects