Ton Story
เว็บนี้เอง — พอร์ตโฟลิโอ + บล็อกสองภาษา ด้วย Next 15, Tailwind v4, MDX
เว็บที่คุณกำลังดูอยู่นี้ — สองภาษา EN/TH สไตล์ editorial มี theme สามตัว
(milk, coffee, tea) และหน้า /bio ที่ตั้งใจไม่ใส่สไตล์เลย เป็นมุกเล็ก ๆ
สำหรับคนที่เปิด source ดู
มันคืออะไร
- หนึ่ง repo ใช้ Next.js 15 App Router, React 19
- บทความและโปรเจกต์เก็บเป็นไฟล์
.mdxในcontent/บทความเขียนภาษาเดียว ต่อโพสต์ (กำหนดผ่านlang:ใน frontmatter) ส่วนโปรเจกต์มี.en.mdxคู่กับ.th.mdx - Theme สามตัว (milk / coffee / tea) ทำผ่าน CSS variables ไม่ swap class
ด้วย JS แค่ตั้ง
data-themeบน html ที่เหลือเป็นเรื่องของ CSS ล้วน ๆ - IBM Plex Serif คู่กับ Plex Sans Thai Looped เลือกเพราะ x-height และจังหวะบรรทัดของอักษรไทยกับอังกฤษเข้ากัน ไม่ต้องแก้ line-height ทีละ block
ทำไมถึงรื้อสร้างใหม่
เวอร์ชันก่อนเป็น next starter template ที่ผมปรับแต่งยากและรู้สึกไม่ค่อยเข้ากับมัน การแก้มันรู้สึก เหมือนตกแต่งห้องในโรงแรม สร้างใหม่จากศูนย์ทำให้โครงสร้างตรงกับวิธีที่ผมเขียนจริง ๆ — และทำให้ผมเลือกการตัดสินใจที่ "น่าเบื่อ" ได้อย่างตั้งใจ (ไม่มี CMS, ไม่มี analytics, ไม่มี auth)
สองภาษาทำงานยังไง
หนึ่งภาษาต่อหนึ่งหน้า ภาษาอังกฤษคือ canonical: URL เปล่า
(/projects/class-peek) คือเวอร์ชันอังกฤษ ภาษาไทยใช้ prefix /th/
(/th/projects/class-peek) ตัวสลับ EN | TH เล็ก ๆ บน header
จะคงเส้นทางปัจจุบันไว้ตอนสลับ — ไม่ทำให้ลิงก์ลึกพังข้ามภาษา
บทความบล็อกเขียนภาษาเดียวต่อโพสต์ผ่าน frontmatter หน้า index แสดงทุกบทความ
ไม่ว่าตอนนั้นจะเลือก EN หรือ TH โดยมี chip EN/TH เล็ก ๆ บนแต่ละการ์ด
ให้ผู้อ่านเห็นคลังเขียนทั้งหมดและเลือกเอง ส่วนชื่อแบรนด์ Aritoton · อริโตต้น
คือจุดเดียวที่ตั้งใจให้สองภาษาคู่กันตลอด
หมายเหตุเรื่อง stack
- Tailwind v4 พร้อม
@themeสำหรับ token เดียวกันนี้ขับ theme สามตัว และ (แยกกัน) Class Peek ใช้ reverse lookup กลับมาหา token ตัวเดียวกันนี้ - MDX ผ่าน
next-mdx-remote/rsc— บทความ render ฝั่ง server แบบ static ไม่มี client runtime สำหรับเนื้อหาเลย - Sitemap ปล่อย URL ทั้งแบบเปล่าและ
/th/ต่อหนึ่งหน้า พร้อม hreflang alternates แต่ละภาษามี canonical เดียว ไม่มีปัญหา duplicate content