กำลังโหลดโมเดล 3 มิติ...
เบื้องหลัง MilerDev
เว็บนี้สร้างด้วยอะไร
ทุกส่วนในระบบ
ชั้นผู้ใช้
สิ่งที่อยู่ในมือผู้เรียน
- เบราว์เซอร์คอม · มือถือ
ผู้เรียนดูคอร์ส ซื้อคอร์ส และเรียนผ่านเว็บโดยตรง
ไม่ต้องติดตั้งแอป เปิดจากเครื่องไหนก็เรียนต่อจากที่ค้างไว้ได้
- แอปธนาคารพร้อมเพย์
สแกน QR พร้อมเพย์ที่ใส่ยอดไว้แล้ว โอนเงิน แล้วออกสลิปให้
คนไทยส่วนใหญ่จ่ายด้วยพร้อมเพย์อยู่แล้ว ไม่ต้องมีบัตร
ชั้นแอป
โค้ดของ MilerDev ที่รันบน Railway
- Next.jsApp Router · Server Components
สร้างหน้าเว็บบนเซิร์ฟเวอร์ แล้วส่ง HTML ที่พร้อมอ่านไปให้เบราว์เซอร์
หน้าโหลดเร็ว Google อ่านเนื้อหาได้ทันที และหน้าเว็บกับ API อยู่ในโปรเจกต์เดียวกัน
- React UIReact · Tailwind · shadcn/ui
ส่วนที่โต้ตอบได้ในเบราว์เซอร์ เช่น หน้าชำระเงิน ตัวเล่นวิดีโอ และเครื่องมือแอดมิน
ใช้คอมโพเนนต์ชุดเดียวกันทั้งเว็บ หน้าตาจึงไปทางเดียวกันและแก้ที่เดียวได้
- API RoutesTypeScript · Zod
รับคำขอที่เปลี่ยนข้อมูล เช่น สร้างรายการชำระเงิน สร้าง QR ตรวจสลิป และบันทึกความคืบหน้า
ตรวจข้อมูลที่ส่งเข้ามาและตรวจสิทธิ์บนเซิร์ฟเวอร์ทุกครั้ง ไม่เชื่อสิ่งที่เบราว์เซอร์บอก
- Auth.jsNextAuth v5
จัดการการสมัครและล็อกอินด้วย Google หรืออีเมล แล้วบอกทุกหน้าว่าใครกำลังใช้งาน
เป็นตัวมาตรฐานของ Next.js รองรับหลายวิธีล็อกอินในระบบเดียว
ชั้นข้อมูล
ที่เก็บข้อมูลถาวร
- Drizzle ORMTypeScript → SQL
แปลงโค้ด TypeScript เป็นคำสั่ง SQL และจัดการ migration เวลาเปลี่ยนโครงสร้างตาราง
TypeScript เช็กชื่อตารางและคอลัมน์ให้ตั้งแต่ตอนเขียน ไม่ต้องรอไปพังตอนรัน
- MySQLฐานข้อมูล
เก็บผู้ใช้ คอร์ส บทเรียน การลงทะเบียน การชำระเงิน ความคืบหน้า และใบประกาศ
ข้อมูลเงินและสิทธิ์เรียนต้องถูกต้องเสมอ ฐานข้อมูลแบบตารางที่มี transaction จึงเหมาะ
ชั้นบริการภายนอก
งานเฉพาะทางที่ให้ผู้เชี่ยวชาญแต่ละด้านทำ
- Stripeบัตรเครดิต · เดบิต
รับชำระด้วยบัตรบนหน้าของ Stripe แล้วแจ้งผลกลับมาที่ระบบ
เว็บเราไม่ต้องเห็นหรือเก็บเลขบัตรเลย
- SlipOKตรวจสลิป
อ่าน QR บนสลิปแล้วเช็กกับข้อมูลธนาคารว่าโอนจริงและยอดถึง
เปิดสิทธิ์เรียนได้เองภายในไม่กี่วินาที ไม่ต้องรอแอดมินเช็กยอด
- Bunny.netStream · CDN
เก็บและสตรีมวิดีโอบทเรียน รวมถึงรูปคอร์ส ผ่านเซิร์ฟเวอร์ที่อยู่ใกล้ผู้เรียน
วิดีโอเล่นลื่นและถูกกว่าเก็บเอง ลิงก์วิดีโอหมดอายุเองและออกให้เฉพาะผู้มีสิทธิ์
- Resendอีเมล
ส่งอีเมลยืนยันการสมัคร รีเซ็ตรหัสผ่าน ยืนยันการชำระเงิน และใบประกาศ
ไม่ต้องดูแลเมลเซิร์ฟเวอร์เอง และส่งถึงกล่องจดหมายได้ดีกว่าส่งเอง
- GoogleSign-In
ให้ผู้เรียนล็อกอินด้วยบัญชี Google ที่มีอยู่แล้ว
ไม่ต้องตั้งและจำรหัสผ่านใหม่
ชั้นการส่งขึ้นเว็บ
เส้นทางจากโค้ดในเครื่องไปถึงเว็บจริง
- GitHubโค้ด · Pull Request
เก็บโค้ดทั้งหมด ทุกการเปลี่ยนแปลงเข้ามาเป็น Pull Request ที่ตรวจได้ก่อน
ย้อนดูได้ว่าอะไรเปลี่ยน เมื่อไหร่ และเพราะอะไร
- GitHub ActionsVitest · Playwright
ทุก Pull Request ต้องผ่าน lint, type check, เทสต์อัตโนมัติ และเทสต์บนเบราว์เซอร์จริงกับ MySQL ก่อน merge
จับบั๊กก่อนถึงผู้เรียน โดยเฉพาะเรื่องเงินและสิทธิ์เรียน
- Railwayโฮสต์
build โค้ดล่าสุด อัปเดตโครงสร้างฐานข้อมูล แล้วสลับไปใช้เวอร์ชันใหม่เมื่อเช็กแล้วว่าทำงาน
merge แล้ว deploy เอง ถ้าขั้นไหนพัง เวอร์ชันเดิมยังให้บริการต่อ
ข้อมูลวิ่งยังไง
ซื้อคอร์สด้วยพร้อมเพย์
จากกดซื้อ ถึงได้สิทธิ์เรียนโดยไม่ต้องรอแอดมิน
- เบราว์เซอร์ → React UI: กดซื้อคอร์สแล้วเลือกพร้อมเพย์
- React UI → API Routes: ขอสร้างรายการชำระเงิน ระบบคิดราคาจากฐานข้อมูลเอง
- API Routes → Drizzle ORM: บันทึกรายการพร้อมยอดที่ต้องจ่าย
- Drizzle ORM → MySQL: เก็บรายการลงฐานข้อมูล
- API Routes → React UI: ส่ง QR ที่ใส่ยอดไว้แล้วกลับไปแสดง
- เบราว์เซอร์ → แอปธนาคาร: สแกน QR โอนเงิน แล้วได้สลิป
- React UI → API Routes: แนบสลิปของรายการนี้
- API Routes → SlipOK: ส่งสลิปไปเช็กกับข้อมูลธนาคาร
- SlipOK → API Routes: ยืนยันว่าโอนจริงและยอดถึง
- API Routes → Drizzle ORM: เปิดสิทธิ์เรียนพร้อมบันทึกการชำระเงิน
- API Routes → Resend: ส่งอีเมลยืนยันการชำระเงิน
ซื้อคอร์สด้วยบัตร
จ่ายบนหน้าของ Stripe แล้วระบบเปิดสิทธิ์เมื่อได้รับผล
- เบราว์เซอร์ → React UI: กดซื้อคอร์สแล้วเลือกจ่ายด้วยบัตร
- React UI → API Routes: ขอสร้างหน้าชำระเงิน
- API Routes → Stripe: สร้างหน้าชำระเงินด้วยราคาจากฐานข้อมูล
- เบราว์เซอร์ → Stripe: กรอกบัตรบนหน้าของ Stripe
- Stripe → API Routes: Stripe แจ้งผลการชำระกลับมา
- API Routes → Drizzle ORM: เปิดสิทธิ์เรียนพร้อมบันทึกการชำระเงิน
- API Routes → Resend: ส่งอีเมลยืนยันการชำระเงิน
เปิดดูวิดีโอบทเรียน
ระบบเช็กสิทธิ์ก่อน แล้ววิดีโอวิ่งจาก CDN ตรงถึงผู้เรียน
- เบราว์เซอร์ → Next.js: เปิดหน้าบทเรียน
- Next.js → Auth.js: เช็กว่าล็อกอินแล้ว
- Next.js → Drizzle ORM: เช็กว่ามีสิทธิ์เรียนคอร์สนี้
- Drizzle ORM → MySQL: อ่านการลงทะเบียนจากฐานข้อมูล
- Next.js → Bunny.net: ออกลิงก์วิดีโอที่หมดอายุเอง
- Bunny.net → เบราว์เซอร์: สตรีมวิดีโอจากเซิร์ฟเวอร์ใกล้ผู้เรียน
- React UI → API Routes: บันทึกความคืบหน้าเมื่อเรียนจบบท
ล็อกอินด้วย Google
ยืนยันตัวตนกับ Google แล้วจำการล็อกอินไว้
- เบราว์เซอร์ → Auth.js: กดล็อกอินด้วย Google
- Auth.js → Google: ส่งไปยืนยันตัวตนกับ Google
- Google → Auth.js: Google ยืนยันกลับมา
- Auth.js → Drizzle ORM: หาบัญชีเดิมหรือสร้างบัญชีใหม่
- Drizzle ORM → MySQL: อ่านและบันทึกบัญชีผู้ใช้
- Auth.js → เบราว์เซอร์: ออก session ที่เข้ารหัสไว้ในคุกกี้
ส่งโค้ดขึ้นเว็บจริง
ทุกการเปลี่ยนแปลงต้องผ่านเทสต์ก่อนถึงผู้เรียน
- GitHub → GitHub Actions: เปิด Pull Request แล้ว CI รันเทสต์ทั้งหมด
- GitHub Actions → GitHub: ทุกด่านผ่าน พร้อม merge
- GitHub → Railway: merge เข้า master แล้ว Railway เริ่ม deploy
- Railway → MySQL: อัปเดตโครงสร้างฐานข้อมูลก่อน
- Railway → Next.js: สลับไปใช้เวอร์ชันใหม่เมื่อเช็กแล้วว่าทำงาน
อยากสร้างเว็บแบบนี้ได้เอง
เริ่มจากพื้นฐานที่ใช้จริงในเว็บนี้ แล้วค่อยต่อยอดทีละส่วน