🏥
Next.js 16 · Sanity CMS · i18n TH / EN

VINTA Hospital
เว็บ pre-opening + ระบบรับสมัครงาน ของโรงพยาบาลเฉพาะทาง

เว็บไซต์ full-stack 2 ภาษา สำหรับโรงพยาบาลเฉพาะทางที่กำลังก่อสร้าง — สื่อสารเรื่องราว pre-opening อย่างสงบและมีศักดิ์ศรี พร้อมระบบรับสมัครงาน (ATS) ในตัว ที่รับใบสมัคร เก็บเข้า CMS แล้วสร้าง PDFใบสมัครภาษาไทยส่งเข้าเมล HR อัตโนมัติ

Next.js 16 (App Router) React 19 next-intl Sanity CMS Tailwind v4 Motion Puppeteer + pdf-lib Resend
Empathize · Define

ปัญหาที่เจอ

ทำเว็บให้โรงพยาบาลที่ "ยังไม่เปิด" — ต้องสร้างความเชื่อใจโดยไม่ขายฝัน และต้องพร้อมรับทีมงานก่อนวันเปิดจริง

โรงพยาบาลเฉพาะทางด้านมะเร็งกำลังอยู่ระหว่างก่อสร้าง — เว็บต้องไม่ทำเหมือนเปิดเต็มระบบแล้ว แต่ต้องสื่อสารว่า "ที่นี่กำลังจะเป็นที่ที่เข้าใจคุณ" อย่างอบอุ่นและน่าเชื่อถือ ขณะเดียวกันก็ต้องเริ่มรับสมัครทีมแพทย์ พยาบาล และเจ้าหน้าที่ตั้งแต่ก่อนเปิด ทั้งหมดนี้ต้อง deploy ได้เร็ว งบก่อนเปิดจำกัด และดูแลข้อมูลผู้สมัครซึ่งอ่อนไหวให้ปลอดภัย

— โจทย์ตั้งต้น ก่อนเริ่มทำเว็บ VINTA Hospital
🏗️

โรงพยาบาลยังไม่เปิด — สื่อสารยาก

ถ้าทำเหมือนเปิดแล้วจะเสียความน่าเชื่อถือ แต่ถ้าโชว์แค่ "กำลังก่อสร้าง" ก็ดูเย็นชา ต้องบอกความจริงว่ากำลังสร้าง โดยยังทำให้คนรู้สึกว่ามีที่พึ่งกำลังจะมา

📋

ต้องรับสมัครทีมก่อนเปิด แต่ไม่มีระบบ

โรงพยาบาลต้องหาแพทย์/พยาบาล/เภสัชกรตั้งแต่ก่อนเปิด — ถ้าไม่มีระบบ ใบสมัครจะกระจัดกระจายตามอีเมล/แชต ไม่มีที่เก็บกลาง ไม่มีรูปแบบมาตรฐานให้ HR อ่าน

🔒

ข้อมูลผู้สมัคร = ข้อมูลอ่อนไหว (PII)

ใบสมัครมีเลขบัตร เบอร์โทร เลขใบประกอบวิชาชีพ ผู้ติดต่อฉุกเฉิน — ถ้าเก็บผิดที่หรือหลุดออก public API มีความเสี่ยงทั้งด้าน PDPA และความไว้วางใจ

🌐

2 กลุ่มผู้ชม + แบรนด์เฉพาะตัว

ต้องรองรับทั้งคนไทยและผู้ชมต่างชาติ (แพทย์/พาร์ทเนอร์) และต้องคุมโทนแบรนด์เข้ม — ฟอนต์ไทยแบบไม่มีหัวให้เข้ากับโลโก้ ห้ามใช้กากบาทแดง/ภาษาสู้รบเรื่องมะเร็ง

ต้อง deploy ได้เร็ว งบก่อนเปิดจำกัด

ยังไม่พร้อมตั้ง backend แยก, ยังไม่มีคีย์ CMS/เมลตอนเริ่ม — แต่ต้อง publish เว็บให้ทันเพื่อเริ่มประชาสัมพันธ์และเปิดรับสมัคร ต้องไม่ผูกกับ vendor เยอะจนขยับตัวไม่ได้


Ideate

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

เว็บ pre-opening ที่ซื่อสัตย์ + ระบบ ATS ในตัว — serverless ล้วน เชื่อม CMS/เมลทีหลังได้โดยเว็บไม่ล้ม

🌅

เว็บ pre-opening ที่บอกความจริงอย่างอบอุ่น

Mood แสง–น้ำ–ร่มเงา, motion แบบ "ลมหายใจ" (fade + reveal ช้า ๆ), CTA แบบไม่กดดัน ("คุยกับทีมดูแล" / "ติดต่อรับคำแนะนำ") — สร้างความเชื่อใจโดยไม่ทำเหมือนเปิดแล้ว

💼

ระบบ Careers + ATS ในตัวเว็บเดียว

หน้าประกาศงาน + ฟอร์มสมัครหลายส่วน + เก็บใบสมัครเข้า CMS อัตโนมัติ — HR เปิดดูใน Studio ได้ที่เดียว ไม่ต้องไล่เก็บจากอีเมล/แชตอีก

🔐

เก็บใบสมัครเป็น "draft" กัน PII รั่ว

บันทึกเอกสารเป็น draft (drafts.<uuid>) ที่ public API อ่านไม่ได้ แต่ HR เห็นใน Studio + write token เป็น server-only + เก็บเฉพาะฟิลด์ที่จำเป็น

📄

สร้าง PDF ใบสมัครไทยให้ HR อัตโนมัติ

เมื่อมีคนสมัคร ระบบ render หน้าปกใบสมัคร (ภาษาไทยเป๊ะ) ด้วย headless Chrome แล้ว merge กับไฟล์เรซูเม่เป็น PDF เดียว ส่งแนบเข้าเมล HR — พร้อมอ่านทันที

🧩

Serverless ล้วน + fallback ทุกจุด

Next.js + Sanity + Resend (เรียกผ่าน fetch ไม่เพิ่ม dependency) — ยังไม่เชื่อม CMS ก็ใช้ seed data, ยังไม่ตั้งเมลก็ตอบสำเร็จแบบ stub เว็บทำงานได้ตั้งแต่ deploy แรก


Prototype

วิธีทำงาน — 4 จังหวะ (เส้นทางใบสมัคร)

ตั้งแต่ผู้สมัครกดส่ง จนใบสมัคร PDF ถึงมือ HR

1
✍️

ผู้สมัครกรอกฟอร์ม

ฟอร์มหลายส่วน มือถือเป็น bottom-sheet, มี date-wheel + ครอปรูปในตัว

2
🔐

Validate + เก็บ draft

ตรวจฝั่ง server แล้วบันทึกเป็น draft ใน CMS ที่ public อ่านไม่ได้

3
📄

สร้าง PDF เบื้องหลัง

headless Chrome render หน้าปก + merge เรซูเม่ (ไม่หน่วงผู้สมัคร)

4
📧

แจ้ง HR พร้อม PDF

ส่งเมลแนบ PDF + ลิงก์เปิดใน Studio ให้ทีมงานอ่านต่อ


Prototype

Tech Stack & Architecture

Serverless ล้วน — ไม่มี backend แยก, ไม่มี DB ที่ต้องดูแลเอง, เชื่อม service ทีหลังได้โดยเว็บไม่ล้ม

ผู้เข้าชม & ผู้สมัครงาน (2 ภาษา · /th · /en)
ผู้ป่วย/ครอบครัว แพทย์/พาร์ทเนอร์ ผู้สมัครงาน ทีม HR
Next.js 16 App Router — RSC + Route Handlers
Server Components /api/apply /api/contact after() background
Services — i18n · CMS · PDF · Mail
next-intl Sanity Studio Puppeteer + pdf-lib Resend (fetch)
Serverless (Vercel) + Sanity dataset + draft docs
@sparticuz/chromium seed fallback server-only token
ทำไมเลือก stack นี้?

Next.js 16 + RSC — render เนื้อหา 2 ภาษาฝั่ง server ได้เร็วและ SEO ดี, route handlers ทำหน้าที่ API ในตัวเดียวกัน ไม่ต้องมี backend แยก · Sanity CMS — ให้ HR แก้ประกาศงาน/อ่านใบสมัครเองผ่าน Studio ภาษาไทย โดย dev ไม่ต้องแตะโค้ด · next-intl — แยก "ข้อความ" (dictionary) ออกจาก "โครงหน้า" (โค้ด) เพิ่ม/แก้ภาษาไม่กระทบ layout · Puppeteer + pdf-lib — render หน้าปกไทยด้วยเบราว์เซอร์จริงแล้ว merge เรซูเม่ ได้ PDF ที่ตัวอักษรไทยเป๊ะ · Resend ผ่าน fetch — ส่งเมลได้โดยไม่เพิ่ม dependency · ทุก service มี fallback เว็บจึง deploy ได้ตั้งแต่ยังไม่ครบคีย์


Prototype

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

ครบตั้งแต่หน้าเว็บสื่อสารแบรนด์ ถึงระบบหลังบ้านรับสมัครงาน

🌐

Bilingual i18n (TH / EN)

next-intl + App Router, URL prefix /th · /en, ไทยเป็นดีฟอลต์ — ข้อความอยู่ใน dictionary แยกจาก layout

🌅

Pre-opening Homepage

Hero วิดีโอ + reveal ช้า ๆ, section เล่าเรื่อง who/why/healing/services/process/FAQ ในโทนสงบและมีศักดิ์ศรี

💼

Careers Listing

หน้าประกาศงานพร้อม badge ระดับความต้องการ (เร่งด่วน/สูง) — ดึงจาก CMS ถ้าเชื่อมแล้ว ไม่งั้นใช้ seed data

✍️

Multi-section Application Form

ฟอร์มสมัครหลายส่วน 30+ ฟิลด์ — มือถือใช้ bottom-sheet, มี date-wheel เลือกวันเกิด, ครอปรูปถ่ายในเบราว์เซอร์, ค้นหาสัญชาติ

🗃️

Sanity CMS (Thai Studio)

8 content models (งาน/หมวด/แผนก/ทำเล/ใบสมัคร/ข้อความติดต่อ ฯลฯ), รองรับ i18n ระดับเอกสาร, custom input + ปุ่ม export PDF

📄

Auto PDF Generation

render หน้าปกใบสมัครด้วย headless Chrome (ไทยเป๊ะ) แล้ว merge เรซูเม่ (PDF/รูป) เป็นไฟล์เดียวด้วย pdf-lib + ปั๊ม footer/เลขหน้า

📧

Email Notify

แจ้งเตือน HR ทุกใบสมัคร/ข้อความติดต่อ ผ่าน Resend (เรียก REST ด้วย fetch) พร้อมแนบ PDF และ header แบรนด์

💬

Contact Form + Chat Widget

ฟอร์มติดต่อ (เก็บ draft + แจ้งเมล) และปุ่มแชตลอย "คุยกับทีมดูแล" ที่เชื่อมช่องทางแชตของโรงพยาบาล


Prototype

หน้าตา — Careers

หน้าประกาศงานที่ผู้สมัครเห็น — การ์ดตำแหน่งพร้อมป้ายความต้องการ กดสมัครแล้วเข้าสู่ฟอร์มหลายส่วน

vinta · ร่วมงานกับเรา
Careers · ร่วมสร้างทีมดูแล
ตำแหน่งที่เปิดรับ
🩺
อายุรแพทย์มะเร็งวิทยา
ฝ่ายการแพทย์ · เต็มเวลา · ศาลายา นครปฐม
เร่งด่วน สมัคร
🩹
พยาบาลวิชาชีพ – หน่วยเคมีบำบัด
ฝ่ายการพยาบาล · เต็มเวลา · ศาลายา นครปฐม
ต้องการสูง สมัคร
💊
เภสัชกรเฉพาะทางยาเคมีบำบัด
ฝ่ายเภสัชกรรม · เต็มเวลา · ศาลายา นครปฐม
เปิดรับ สมัคร
ส่งใบสมัคร → กรอกฟอร์มหลายส่วน → ระบบสร้าง PDF ใบสมัคร ส่งเข้าเมลทีม HR อัตโนมัติ

Prototype · UI Craft

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

ในมุม Product Designer: แปลงโจทย์ "โรงพยาบาลมะเร็งก่อนเปิด" เป็นระบบดีไซน์ที่สงบ มีศักดิ์ศรี และรองรับฟอร์มสมัครงาน 30+ ฟิลด์ 2 ภาษาได้จริง

Design Tokens แกะจากโลโก้จริง · VINTA Brand Book v1.0
Healing Green
#259B94
Humility Gold
#AF9C84
Quiet Water
#7FA6A2
Deep Bark
#4A342D
Vinta Brown
#604036
Hope Beige
#F3ECE5
Warm Mist
#D9D1C8
Ink (text)
#35231F
การดูแลที่เริ่มจากคุณ ไม่ใช่จากโรค Display · Marcellus / Anuphan · 300
เนื้อความภาษาไทยใช้ฟอนต์มีหัวเพื่อการอ่านต่อเนื่อง คุมโทนอบอุ่นและชัดเจน Body · Garuda / Acumin · 400 · 1.06rem
Careers · ร่วมงานกับเรา Eyebrow · 0.825rem · tracking 0.14em
radius การ์ด 20px radius ฟิลด์ 12px container 90rem heading tracking 0.14em heading weight 300 shadow card
เว็บไซต์ · Web (Desktop)
vinta · หน้าแรก
Pre-opening · เปิดเร็ว ๆ นี้

เป็นมะเร็ง ไม่ได้แปลว่า
ต้องเผชิญเรื่องนี้คนเดียว

ตั้งแต่วันแรกที่รู้ผล จนถึงวันที่มีแผนการดูแลที่ชัดเจน VINTA อยู่ในทุกขั้นตอนกับคุณ

คุยกับทีมดูแล ส่งข้อมูลผู้ป่วย

Pre-opening Homepage
โทนสงบ พื้นเข้ม heading serif น้ำหนักเบา CTA ไม่กดดัน

application-cover.pdf
V VINTASpecialized Cancer Hospital

ใบสมัครงาน — อายุรแพทย์มะเร็งวิทยา

ชื่อ–สกุลนพ. ศิริพร ใจดี (ตัวอย่าง)
ฝ่ายฝ่ายการแพทย์ · เต็มเวลา
ประสบการณ์8 ปี · เงินเดือนที่คาดหวัง —
ใบประกอบฯว. XXXXX (ตัวอย่าง)
แนบเรซูเม่ + รูปถ่าย (merge แล้ว)
สร้างอัตโนมัติด้วย headless Chrome · ฟอนต์ไทยเป๊ะ · ส่งเข้าเมล HR

Auto-generated PDF
หน้าปกไทยจาก Chrome จริง → merge เรซูเม่เป็นไฟล์เดียว

แอปมือถือ · Mobile
👤 ข้อมูลส่วนตัว
ศิริพร
siriporn.mail
รูปแบบอีเมลไม่ถูกต้อง
14 มีนาคม 2535
ปี (พ.ศ.)เดือนวัน
กุมภาพันธ์
มีนาคม
เมษายน
ค้นหาสัญชาติ…
ส่งใบสมัคร

Application Form (มือถือ)
bottom-sheet + date-wheel · states: focus / error / empty

Mobile-first: ฟอร์ม 30+ ฟิลด์ ไม่ให้ล้นจอ (393 → 768 → 1440)

บนมือถือ ฟอร์มยาว = คนเลิกกรอกกลางคัน จึงแตกเป็น section stepper + ใช้ bottom-sheet สำหรับตัวเลือก, date-wheel เลือกวันเกิด (พ.ศ.) และครอปรูปในเบราว์เซอร์ — ผู้สมัครเห็นทีละส่วน ไม่เจอกำแพงช่องกรอก ส่วนบน ≥768 ค่อยขยายเป็น popover/2 คอลัมน์

Component states: บอก error ตอนที่ควรบอก ไม่ใช่ระหว่างพิมพ์

ทุกฟิลด์มี state ครบ — default / focus (ring ทอง #AF9C84) / invalid (แดง #b4452f) แต่ใช้ :not(:placeholder-shown):invalid ให้ error โผล่หลังผู้ใช้กรอกแล้วออกจากช่อง ไม่ใช่ทันทีที่เริ่มพิมพ์ — ลดความรู้สึกโดนตำหนิ พร้อมข้อความบอกวิธีแก้เป็นภาษาไทย

Accessibility & แบรนด์: ลดความกลัว ไม่ใช่เพิ่ม

จงใจไม่ใช้กากบาทแดง/ภาษาสู้รบ — ใช้ Healing Green เป็น accent เงียบ ๆ ไม่ใช่สีเตือนภัย, คุม contrast ให้ผ่าน AA บนพื้นเบจ, touch target ≥44px, :focus-visible เส้นเขียว, และ motion แบบ "ลมหายใจ" ที่เคารพ prefers-reduced-motion

Typography 2 ภาษา: เลือกฟอนต์ตามหน้าที่

ไทยใช้ 2 ฟอนต์คนละงาน — Anuphan (ไม่มีหัว เข้ากับโลโก้) สำหรับ heading/display, Garuda (มีหัว) สำหรับ body ให้อ่านต่อเนื่อง; อังกฤษใช้ Marcellus (serif) คู่กัน · เผื่อ line-height 1.28 ให้สระ/วรรณยุกต์ไทย · แยกข้อความออกจาก layout ให้ทั้ง 2 ภาษาไม่หลุดจากกัน


Test & Iterate

Hack กับปัญหา

6 โจทย์ที่ต้องคิดทางแก้เอง — ภาษาไทยบน PDF, browser บน serverless, ความปลอดภัยของ PII

📄

สร้าง PDF ภาษาไทยให้ตัวอักษรเป๊ะ

ฟอนต์มาตรฐานของ pdf-lib วาดภาษาไทยไม่ได้ (สระ/วรรณยุกต์เพี้ยน) แต่ HR ต้องอ่านใบสมัครไทยที่ถูกต้อง 100%

แก้: render หน้าปกด้วย headless Chrome (puppeteer) ที่โหลดฟอนต์ Anuphan จริง → ได้ PDF หน้าปก แล้วค่อยใช้ pdf-lib merge กับเรซูเม่ · ส่วน footer ที่ต้องปั๊มทุกหน้า ใช้วิธี screenshot เป็นรูป แล้ว embed กัน glyph ไทยเพี้ยนตอน stamp
🌐

เปิดเบราว์เซอร์บน serverless ไม่ได้ตรง ๆ

Puppeteer ต้องมี Chrome binary — บนเครื่อง dev มี Chrome อยู่แล้ว แต่บน serverless ไม่มี และ Chrome เต็มตัวใหญ่เกิน limit

แก้: ตรวจ env (VERCEL / AWS_REGION) → บน serverless โหลด @sparticuz/chromium (binary ที่ตัดให้เล็กพอ), บนเครื่อง dev ชี้ไป Chrome ที่ติดตั้งไว้ — โค้ดชุดเดียวรันได้ทั้งสอง environment
🔐

ใบสมัครมี PII ห้ามหลุด public API

Sanity เอกสารที่ published อ่านได้ผ่าน public API — ถ้าเก็บใบสมัครแบบปกติ ใครก็ query เลขบัตร/เบอร์โทรผู้สมัครได้

แก้: บันทึกเป็น draft (_id = drafts.<uuid>) ซึ่ง public API มองไม่เห็น แต่ HR เห็นใน Studio · write token เป็น server-only (ไม่ขึ้นต้น NEXT_PUBLIC_) · ตรวจ input ฝั่ง server ทุกฟิลด์ก่อนบันทึก

Gen PDF + ส่งเมล ช้า → ผู้สมัครรอนาน

ถ้ารอ render PDF และส่งเมลให้เสร็จก่อนตอบ ผู้สมัครจะเห็น loading ค้างหลายวินาที — ประสบการณ์แย่

แก้: ใช้ after() ของ Next.js — ตอบผู้สมัครว่า "สำเร็จ" ทันที หลังบันทึก แล้วค่อย generate PDF + ส่งเมลแจ้ง HR เป็นงานเบื้องหลัง (ตั้ง maxDuration = 60 เผื่องานหนัก) ผู้สมัครไม่ต้องรอ
🧩

เว็บต้อง live ก่อนคีย์ครบ

ตอนเริ่มยังไม่มี Sanity project / Resend key / write token — แต่ต้อง publish เว็บให้ทันเพื่อเริ่มประชาสัมพันธ์

แก้: ทุกจุดที่ต่อ service มี fallback — CMS ยังไม่ตั้งก็ใช้ seed data (ตำแหน่งงานตัวอย่าง), เมลยังไม่ตั้งก็ตอบ stub แล้ว log, ฟอร์มยังทำงานได้ครบ — พอใส่ env ทีหลัง ระบบ "สลับไปของจริง" อัตโนมัติโดยไม่ต้องแก้โค้ด
🎨

แยกไอคอน/ภาพ ออกจากข้อความ 2 ภาษา

section ในหน้าแรกมีทั้งไอคอน รูป และข้อความ — ถ้าเก็บทุกอย่างปนกันใน dictionary จะแก้ภาษายากและ layout พังง่าย

แก้: เก็บ ข้อความไว้ใน dictionary (แปลได้), แต่ ไอคอน/ลำดับรูปผูกไว้ในโค้ดเป็น metadata แล้ว map เข้ากันด้วย index ตอน render — นักแปลแก้เฉพาะข้อความ ส่วนโครงหน้าคงเดิมทั้ง 2 ภาษา

Define

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

สำหรับเว็บโรงพยาบาลมะเร็ง สิ่งที่จงใจ "ไม่ทำ" สำคัญพอ ๆ กับสิ่งที่ทำ

เว็บนี้ต้องลดความกลัว ไม่ใช่เพิ่ม — จึงไม่ใช้กากบาทแดง ไม่ใช้ภาษาสู้รบเรื่องมะเร็ง ไม่ทำเหมือนโรงพยาบาลเปิดเต็มระบบทั้งที่ยังก่อสร้าง และไม่เก็บข้อมูลผู้สมัครไว้ที่ที่ public เข้าถึงได้ ทุกการตัดสินใจยึดความสงบ ศักดิ์ศรี และความปลอดภัยของข้อมูลเป็นหลัก มากกว่าลูกเล่นทางการตลาด

🦺
บอกความจริง ไม่ขายฝัน

สื่อสารว่า "กำลังสร้าง" อย่างอบอุ่น ไม่ทำเหมือนเปิดแล้ว


ไม่ใช้กากบาทแดง/ภาษาสู้รบ

ความน่าเชื่อถือมาจาก typography & layout ไม่ใช่สัญลักษณ์เร่งด่วน

🔐
PII เก็บเป็น draft เท่านั้น

public API อ่านไม่ได้ · token อยู่ฝั่ง server

📏
Motion แบบลมหายใจ

reveal ช้า นุ่ม เคารพ reduced-motion ไม่ flashy


Level Up · Reflect

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

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

1. i18n Architecture — ทำเว็บ 2 ภาษาให้ maintain ได้จริง:

เข้าใจ next-intl บน App Router — routing/URL prefix, setRequestLocale ใน RSC, การแยก "ข้อความ" (dictionary) ออกจาก "โครงหน้า" (โค้ด) แล้ว map ไอคอน/รูปด้วย index — บทเรียน: i18n ที่ดีคือทำให้นักแปลแก้เฉพาะข้อความได้ โดยไม่ต้องแตะ layout และไม่ทำให้ทั้งสองภาษาหลุดจากกัน

2. Headless-browser PDF Pipeline — จากศูนย์เป็นสร้างเอกสารเองได้:

ประกอบ pipeline: puppeteer render HTML→PDF (ฟอนต์ไทยเป๊ะ) + pdf-lib merge หลายไฟล์ + embed รูป/ปั๊ม footer/เลขหน้า + จัดการ dual-environment (Chrome เครื่อง vs @sparticuz/chromium บน serverless) — บทเรียน: การสร้างเอกสารคุณภาพระดับพร้อมส่ง ไม่ใช่ของลึกลับ ถ้ารู้จักจุดแข็งของแต่ละเครื่องมือแล้วเอามาต่อกัน

3. Structured Content / Headless CMS — ออกแบบ schema ให้คนอื่นใช้ต่อ:

โมเดล content 8 ชนิดใน Sanity (งาน/หมวด/แผนก/ทำเล/ใบสมัคร/ข้อความ ฯลฯ), แยก draft vs published, ทำ i18n ระดับเอกสาร, custom Studio input + ปุ่ม export — บทเรียน: งานหลังบ้านที่ดีคือส่งมอบ "ระบบที่ HR ดูแลเองได้" ไม่ใช่หน้าจอที่ต้องกลับมาหา dev ทุกครั้งที่จะแก้ข้อความ

4. Data Safety บน Serverless — คิดเรื่องความปลอดภัยตั้งแต่ออกแบบ:

วางระบบให้ PII ปลอดภัย: เก็บเป็น draft ที่ public API อ่านไม่ได้, แยก server-only token ออกจาก client, validate ทุก input ฝั่ง server, ใช้ after() ทำงานหนักเบื้องหลังโดยไม่หน่วงผู้ใช้ — บทเรียน: กับข้อมูลอ่อนไหว "ที่เก็บ" และ "ใครอ่านได้" ต้องออกแบบมาตั้งแต่แรก ไม่ใช่มาแปะทีหลัง

5. Healthcare UX / Brand สำหรับผู้ใช้เปราะบาง — ดีไซน์ที่ลดความกลัว:

แปลง mood & tone (แสง–น้ำ–ร่มเงา, ศักดิ์ศรี) เป็น UI จริง — คุมโทน copy ให้ปลอบประคองไม่กดดัน, เลี่ยงสัญลักษณ์เร่งด่วน, ทำ contrast ให้ผ่านบนพื้นเบจ/น้ำตาล, motion แบบลมหายใจที่เคารพ reduced-motion — บทเรียน: สำหรับผู้ป่วยและครอบครัว "ความสงบและความชัดเจน" คือฟีเจอร์ ไม่ใช่การตกแต่ง

2
ภาษา — ไทย/อังกฤษ (i18n เต็มเว็บ)
8
content models ใน Sanity CMS
30+
ฟิลด์ในฟอร์มสมัครงาน → PDF อัตโนมัติ
0
PII ที่อ่านได้ผ่าน public API
Aw mascot

VINTA Hospital

เว็บไซต์ full-stack 2 ภาษาสำหรับโรงพยาบาลเฉพาะทางที่กำลังก่อสร้าง — เล่าเรื่อง pre-opening อย่างสงบและมีศักดิ์ศรี พร้อมระบบรับสมัครงานในตัวที่รับใบสมัคร เก็บเข้า CMS อย่างปลอดภัย และสร้าง PDF ใบสมัครภาษาไทยส่งให้ HR อัตโนมัติ สร้างด้วย Next.js 16, Sanity และ serverless ล้วน

Next.js 16 React 19 next-intl Sanity CMS Tailwind v4 Motion Puppeteer + pdf-lib Resend
Projects