DESIGN.md สำหรับเว็บภาษาไทย: เขียน token, lint และ export
เขียน token สีและฟอนต์ใน DESIGN.md ตามสเปก @google/design.md 0.4.0 รัน spec, lint, diff และ export เป็น Tailwind บน Node ของ Ubuntu พร้อมเลือกฟอนต์ที่มีอักษรไทยจริง
DESIGN.md แบบมี token ต่างจากไฟล์บรรยายธรรมดาอย่างไร
DESIGN.md ที่ coding agent ทำตามได้แม่นที่สุดคือไฟล์ที่ค่าซึ่งต้องตรงทุกครั้ง เช่น รหัสสี ชื่อฟอนต์ และระยะห่าง อยู่ใน token ส่วนคำบรรยายทำหน้าที่อธิบายเหตุผลและวิธีใช้ค่าเหล่านั้น ฟอร์แมตของ Google Labs ที่มากับแพ็กเกจ npm @google/design.md แบ่งไฟล์เป็นสองส่วน ส่วนบนเป็น YAML front matter ที่เก็บค่าจริง เช่น รหัสสี ชื่อฟอนต์ และระยะห่าง ส่วนล่างเป็น markdown ที่อธิบายว่าควรใช้ค่าไหนตอนไหน แพ็กเกจเดียวกันมี CLI ให้ตรวจ เทียบ และแปลง token ได้เองบนเครื่องหรือบน VPS
บทความนี้ถือว่าคุณรู้จัก DESIGN.md อยู่แล้ว ถ้ายังสงสัยว่าทำไม agent ต้องมีไฟล์นี้ หรืออยากใช้ไฟล์แบบเดียวกันจดการตัดสินใจที่ไม่ใช่เรื่องหน้าจอ อ่าน DESIGN.md คืออะไร และทำไม coding agent ต้องมี ก่อน ที่นี่เป็นงานลงมือล้วน ตั้งแต่ติดตั้ง Node.js ไปจนถึงให้ Claude Code โหลดไฟล์ทุกครั้งที่เริ่ม session และมีเรื่องที่คนทำเว็บภาษาไทยต้องระวังเป็นพิเศษ คือฟอนต์ต้องมีอักษรไทยจริง และ line-height ต้องเหลือที่ให้สระบนกับวรรณยุกต์
ตัวฟอร์แมตยังอยู่ในสถานะ alpha README ของโปรเจกต์เขียนไว้ตรงๆ ว่า "The DESIGN.md format is at version alpha" แปลว่ากฎอาจเปลี่ยนระหว่างเวอร์ชัน ทุกคำสั่งในบทความนี้จึง pin ไว้ที่ 0.4.0 ซึ่งเป็นเวอร์ชัน latest บน npm registry ณ วันที่ 17 ตุลาคม 2026 (เผยแพร่เมื่อ 27 กรกฎาคม 2026) ก่อนใช้จริงให้เช็กว่ามีเวอร์ชันใหม่กว่าหรือยังด้วย npm view @google/design.md dist-tags
ติดตั้ง Node.js 18 ขึ้นไปจากแพ็กเกจของ Ubuntu
แพ็กเกจ 0.4.0 ประกาศในช่อง engines ว่าต้องใช้ Node >=18.0.0 คุณไม่ต้องเพิ่ม repository ภายนอก เพราะ Ubuntu 24.04 มี nodejs 18.19.1 กับ npm 9.2.0 ในคลังแพ็กเกจของตัวเอง ส่วน Ubuntu 26.04 มี nodejs 22.22.1 ทั้งสองรุ่นผ่านเกณฑ์
sudo apt update
sudo apt install -y nodejs npm
node -v
npm -vบน 24.04 node -v ควรแสดง v18.19.1 ซึ่งผ่านเกณฑ์ >=18.0.0 ของ engines ได้สบาย ช่อง engines เป็นแค่สิ่งที่แพ็กเกจประกาศไว้ ไม่ได้รับประกันว่าผู้พัฒนาทดสอบบนรุ่นนี้ ถ้าคำสั่งไหนล้มด้วย error ที่ดูไม่เกี่ยวกับไฟล์ของคุณ ให้ลองรันซ้ำบน Node 22 ก่อนสรุปว่าไฟล์ผิด
README แนะนำ npm install @google/design.md แต่ในบทความนี้เราจะรันผ่าน npx และระบุเวอร์ชันทุกครั้ง แบบนี้ไม่ต้องติดตั้งอะไรแบบ global ด้วย sudo และทุกคนในทีมได้โค้ดชุดเดียวกัน ครั้งแรกที่รัน npm จะถามยืนยันก่อนดาวน์โหลดแพ็กเกจ ให้ตอบ y เหตุผลด้านความปลอดภัยของการ pin เวอร์ชันอธิบายไว้ละเอียดใน การโจมตี supply chain ผ่าน npm บนเซิร์ฟเวอร์ ถ้าติดตั้งแพ็กเกจลงในโปรเจกต์ คุณจะได้คำสั่งสองชื่อคือ design.md และ designmd ซึ่งชี้ไปที่โปรแกรมเดียวกัน
ดูกฎของเวอร์ชันที่ติดตั้งด้วยคำสั่ง spec
เอกสารแต่ละแหล่งของโปรเจกต์นี้ไม่ได้ตรงกันเสมอ ตัวอย่างที่เห็นชัดคือรายการกฎของ lint README ที่แนบมาในแพ็กเกจ 0.4.0 บน npm มีตารางกฎแปดข้อ แต่ README ใน repository ทั้งที่ tag 0.4.0 และบน main มีสิบเอ็ดข้อ โดยเพิ่ม unknown-key token-like-ignored และ omitted-rules ซอร์สโค้ดที่ tag 0.4.0 มีไฟล์ของกฎชุดสิบเอ็ดข้อนี้อยู่แล้ว แปลว่า README ในแพ็กเกจตกรุ่น ไม่ใช่ว่าโปรแกรมขาดกฎ ส่วน main ก็เดินหน้าไปก่อนรุ่นถัดไปบน npm ได้ เช่น commit ที่แก้สเปกเมื่อ 16 ตุลาคม 2026 หลัง release 0.4.0 ถ้าอ่านจากแหล่งเดียว คุณอาจเชื่อรายการที่ไม่ตรงกับโปรแกรมที่รันอยู่จริง ทางที่ถูกคือถามตัวโปรแกรมเอง
npx @google/design.md@0.4.0 spec > design-md-spec.md
npx @google/design.md@0.4.0 spec --helpคำสั่ง spec พิมพ์สเปกของฟอร์แมตตามเวอร์ชันที่ติดตั้ง README บอกว่าออกแบบมาให้ใส่เป็นบริบทใน prompt ของ agent ได้ด้วย ไฟล์ design-md-spec.md จึงใช้ได้สองทาง: คุณอ่านเอง และส่งให้ agent ตอนสั่งให้มันร่าง DESIGN.md
README ทั้งในแพ็กเกจ 0.4.0 และบน main ระบุ flag ของ spec ไว้อีกสามตัว ได้แก่ --rules ที่ต่อท้ายด้วยตารางกฎ lint ที่ใช้งานอยู่ --rules-only ที่พิมพ์เฉพาะตารางนั้น และ --format markdown|json ซอร์สของคำสั่ง spec ที่ tag 0.4.0 ก็ประกาศ option ทั้งสามตัวนี้ โดยค่าเริ่มต้นของ --format คือ markdown ถ้าพิมพ์ flag แล้วไม่ได้ผลตามที่คาด ให้ยึดชื่อที่ spec --help บนเครื่องคุณแสดงเป็นหลัก
โครงสร้างไฟล์ DESIGN.md: token คือค่าจริง markdown คือเหตุผล
README เรียก token ใน YAML front matter ว่าค่าที่เป็นบรรทัดฐาน (normative values) ส่วน markdown คือเหตุผลประกอบว่าจะใช้ค่าเหล่านั้นอย่างไร ถ้าสองส่วนดูขัดกัน ให้ถือ token เป็นหลัก เหตุผลที่ต้องแยกแบบนี้ง่ายมาก ประโยคอย่าง "ใช้สีเขียวเข้มเป็นสีหลัก" ทำให้ agent ต้องเดารหัสสีเอง และเดาไม่เหมือนกันทุกครั้ง ส่วน primary: "#0B5D4B" ไม่มีอะไรให้เดา และ lint ก็ตรวจได้เฉพาะสิ่งที่อยู่ใน token
สเปกใน 0.4.0 กำหนด key ระดับบนสุดไว้ดังนี้:
name: ชื่อระบบดีไซน์ เป็น key ที่บังคับต้องมีversionและdescription: ไม่บังคับ ค่าversionปัจจุบันคือalphacolors: ชื่อ token คู่กับค่าสี รับสี CSS ที่ถูกต้องทุกแบบ แต่สเปกแนะนำ#RRGGBBเป็นค่าเริ่มต้นtypography: ชื่อ token คู่กับชุดค่าตัวอักษร ได้แก่fontFamilyfontSizefontWeightlineHeightletterSpacingและมีfontFeatureกับfontVariationให้ใช้เมื่อจำเป็นroundedและspacing: สเกลของมุมโค้งและระยะห่างcomponents: ชื่อ component คู่กับ property เช่นbackgroundColortextColortypographyroundedpaddingsizeheightwidth
ค่าที่เป็นขนาด (dimension) ต้องเป็นสตริงที่มีหน่วย px em หรือ rem การอ้างถึง token อื่นใช้วงเล็บปีกกาครอบ path เช่น {colors.primary} หรือ {rounded.md} ถ้า path ชี้ไปที่ token ที่ไม่มีอยู่ lint จะรายงานเป็น error
สเปกของ 0.4.0 เขียนไว้ว่า token อยู่ใน YAML front matter ที่ต้นไฟล์ บทความนี้จึงใช้วิธีนั้น สเปกบน main ที่แก้เมื่อ 16 ตุลาคม 2026 หลัง release 0.4.0 อธิบายทางเลือกที่สองไว้ด้วย คือวาง token เป็น code block แบบ yaml ใต้หัวข้อ ## แต่ละหัวข้อ โดย key ระดับบนสุดแต่ละตัวประกาศได้ครั้งเดียวทั้งไฟล์ ถ้าอยากใช้แบบนี้ ให้เช็กผลของคำสั่ง spec ในเวอร์ชันที่คุณติดตั้งก่อน
ฝั่ง markdown ใช้หัวข้อระดับ ## จะข้ามบางหัวข้อก็ได้ แต่หัวข้อที่มีต้องเรียงตามลำดับนี้:
- Overview (หรือ Brand & Style)
- Colors
- Typography
- Layout (หรือ Layout & Spacing)
- Elevation & Depth (หรือ Elevation)
- Shapes
- Components
- Do's and Don'ts
เขียนชื่อหัวข้อเป็นภาษาอังกฤษตามสเปก ส่วนเนื้อหาใต้หัวข้อเขียนภาษาไทยได้ตามปกติ
ตัวอย่าง DESIGN.md สำหรับเว็บภาษาไทย
ตัวอย่างนี้เป็นระบบจองโต๊ะของร้านกาแฟสมมติชื่อ Baan Doi หน้าจอเป็นภาษาไทยเกือบทั้งหมด มีคำภาษาอังกฤษปนบ้าง เช่น ชื่อเมนู บันทึกเป็น DESIGN.md ที่ root ของโปรเจกต์
---
version: alpha
name: Baan Doi Booking
description: ระบบจองโต๊ะร้านกาแฟ หน้าจอภาษาไทยเป็นหลัก
colors:
primary: "#0B5D4B"
on-primary: "#FFFFFF"
surface: "#FAF7F2"
ink: "#1F1B16"
muted: "#6B6158"
typography:
heading-lg:
fontFamily: IBM Plex Sans Thai
fontSize: 28px
fontWeight: 600
lineHeight: 1.4
body-md:
fontFamily: Sarabun
fontSize: 16px
fontWeight: 400
lineHeight: 1.7
label-sm:
fontFamily: Sarabun
fontSize: 14px
fontWeight: 500
lineHeight: 1.6
rounded:
sm: 4px
md: 8px
spacing:
sm: 8px
md: 16px
lg: 24px
components:
button-primary:
backgroundColor: "{colors.primary}"
textColor: "{colors.on-primary}"
typography: "{typography.label-sm}"
rounded: "{rounded.md}"
padding: 12px
card:
backgroundColor: "{colors.surface}"
textColor: "{colors.ink}"
rounded: "{rounded.md}"
padding: 16px
hint-text:
backgroundColor: "{colors.surface}"
textColor: "{colors.muted}"
typography: "{typography.label-sm}"
---
## Overview
ระบบจองโต๊ะสำหรับลูกค้าคนไทย ออกแบบให้อ่านง่ายบนมือถือก่อน แล้วค่อยขยายเป็นจอใหญ่
## Colors
primary ใช้กับปุ่มหลักและลิงก์เท่านั้น ข้อความทั่วไปใช้ ink บนพื้น surface ข้อความรองใช้ muted
## Typography
หัวข้อใช้ IBM Plex Sans Thai เนื้อหาใช้ Sarabun ทั้งสองฟอนต์มีอักษรไทยและละติน
line-height ตั้งไว้สูงกว่างานภาษาอังกฤษ เพื่อเผื่อที่ให้สระและวรรณยุกต์
## Components
ปุ่มหลักมีได้หนึ่งปุ่มต่อหน้าจอ การ์ดใช้ padding 16px เสมอ
## Do's and Don'ts
- ใช้ token จากไฟล์นี้เท่านั้น ห้ามเขียนรหัสสีลงในโค้ดตรงๆ
- ห้ามเปลี่ยน fontFamily เป็นฟอนต์ที่ไม่มีอักษรไทย
- ห้ามลด lineHeight ของข้อความภาษาไทยให้ต่ำกว่าค่าใน tokenทุก component ที่มีข้อความในตัวอย่างนี้ระบุทั้ง backgroundColor และ textColor แม้แต่ card กับ hint-text ที่ดูเหมือนไม่จำเป็น เหตุผลอยู่ในหัวข้อ lint ด้านล่าง หัวข้อ Do's and Don'ts เขียนเป็นคำสั่งสั้นๆ ถึง agent โดยตรง ส่วนเหตุผลยาวๆ อยู่ในหัวข้อ Typography แทน
ทำไม fontFamily ต้องเป็นฟอนต์ที่มีอักษรไทยจริง
ในสเปก fontFamily เป็นแค่สตริง ฟอร์แมตไม่มีช่องให้ประกาศว่าฟอนต์รองรับภาษาอะไร ถ้าคุณเอา DESIGN.md ที่เขียนมาสำหรับเว็บภาษาอังกฤษให้ agent มันจะใช้ฟอนต์ละตินตามที่ไฟล์บอก หน้าเว็บที่ได้จะแสดงตัวอักษรอังกฤษด้วยฟอนต์นั้น แต่ฟอนต์นั้นไม่มีตัวอักษรไทย browser จึงต้องหาฟอนต์อื่นในเครื่องผู้ใช้มาแสดงอักษรไทยแทน แต่ละระบบปฏิบัติการมีฟอนต์ไทยติดเครื่องต่างกัน หน้าเดียวกันจึงหน้าตาไม่เหมือนกันในแต่ละเครื่อง และขนาดตัวอักษรไทยกับอังกฤษในประโยคเดียวกันก็มักไม่เข้ากัน
วิธีป้องกันคือเลือกฟอนต์ที่มีอักษรไทยตั้งแต่แรก แล้วตรวจให้แน่ใจก่อนเขียนลง token ฟอนต์ของ Google Fonts มีไฟล์ METADATA.pb อยู่ใน repository google/fonts บน GitHub ไฟล์นี้บอกว่าฟอนต์มี subset ภาษาอะไรบ้าง ตรวจฟอนต์ที่คนไทยใช้กันบ่อยได้แบบนี้
for f in sarabun notosansthai ibmplexsansthai; do
echo "== $f"
curl -s "https://raw.githubusercontent.com/google/fonts/main/ofl/$f/METADATA.pb" | grep -E '^(subsets|primary_script)'
doneฟอนต์ที่ใช้กับภาษาไทยได้ต้องมีบรรทัด subsets: "thai" ทั้ง Sarabun, Noto Sans Thai และ IBM Plex Sans Thai มีบรรทัดนี้ และมี primary_script: "Thai" ด้วย ทั้งสามฟอนต์ยังมี subset latin คำภาษาอังกฤษในประโยคไทยจึงแสดงด้วยฟอนต์เดียวกัน
ถ้าคุณเลือกฟอนต์อื่นจากเว็บ Google Fonts ให้ใช้ลูปเดียวกันเช็ก โดยเปลี่ยนเป็นชื่อโฟลเดอร์ของฟอนต์นั้น ชื่อโฟลเดอร์คือชื่อฟอนต์ตัวพิมพ์เล็กที่ไม่มีช่องว่าง ฟอนต์ส่วนใหญ่อยู่ใต้ ofl/ บางตัวอยู่ใต้ apache/ หรือ ufl/ ถ้าไม่มีบรรทัดไหนออกมาเลย ให้เช็ก path ก่อน เพราะ path ผิดก็ให้ผลว่างแบบเดียวกัน
line-height เท่าไรถึงพอสำหรับสระและวรรณยุกต์
ตัวอักษรไทยใช้พื้นที่แนวตั้งมากกว่าตัวละติน สระบนอย่าง ิ ี ึ ื อยู่เหนือพยัญชนะ วรรณยุกต์ซ้อนอยู่เหนือสระบนอีกชั้น ส่วนสระล่างอย่าง ุ ู และหางของ ฎ ฏ ลงไปต่ำกว่าเส้นฐาน line-height ที่พอดีสำหรับภาษาอังกฤษจึงมักแน่นเกินไปสำหรับภาษาไทย ผลคือวรรณยุกต์ของบรรทัดล่างไปชิดหรือชนกับสระล่างของบรรทัดบน
สเปก 0.4.0 รับ lineHeight ได้ทั้งแบบมีหน่วย เช่น 24px และแบบตัวเลขไม่มีหน่วย เช่น 1.6 ตัวเลขไม่มีหน่วยหมายถึงตัวคูณของ fontSize แบบนี้สะดวกกว่า เพราะค่าเดียวใช้ได้กับทุกขนาดตัวอักษร สเปกไม่ได้ให้คำแนะนำเรื่องภาษาไทยไว้ ค่า 1.7 สำหรับเนื้อหาและ 1.4 สำหรับหัวข้อในตัวอย่างเป็นค่าเริ่มต้นที่ผมเลือกเอง ไม่ใช่ตัวเลขจาก Google
ให้ทดสอบด้วยตาของคุณเอง ใส่ประโยคที่มีวรรณยุกต์ซ้อนเยอะลงในหน้าทดสอบ เช่น ปู่ญี่ปุ่นที่นี่ซื้อน้ำแข็งกี่ถุง ทำให้ข้อความยาวพอจะขึ้นบรรทัดใหม่อย่างน้อยสามบรรทัด แล้วดูบนจอขนาดมือถือ ถ้าวรรณยุกต์ของบรรทัดหนึ่งไปแตะสระล่างของบรรทัดก่อนหน้า ให้เพิ่ม lineHeight ใน token แล้วสั่ง agent สร้างหน้าใหม่ อย่าไปแก้ CSS ทีละจุด เพราะ token คือแหล่งค่าเพียงแหล่งเดียว
lint ตรวจอะไรใน DESIGN.md และอะไรที่ lint ไม่ตรวจ
npx @google/design.md@0.4.0 lint DESIGN.md
npx @google/design.md@0.4.0 lint --helpตาม README คำสั่ง lint ตรวจว่าไฟล์ถูกต้องตามโครงสร้าง กฎที่สำคัญที่สุดมีสองข้อ ข้อแรกคือ broken-ref ระดับ error จับการอ้างถึง token ที่ไม่มีอยู่ เช่น พิมพ์ {colors.primay} ผิด ข้อสองคือ contrast-ratio ระดับ warning เตือนเมื่อคู่ backgroundColor กับ textColor ของ component มี contrast ต่ำกว่า 4.5:1 ซึ่งเป็นเกณฑ์ขั้นต่ำระดับ AA ของ WCAG (Web Content Accessibility Guidelines) นอกจากชื่อไฟล์แล้ว lint ยังรับ - เพื่ออ่านจาก stdin และมี --format json สำหรับให้โปรแกรมอื่นอ่านผล
รายละเอียดของกฎ contrast สำคัญกว่าที่เห็น lint ตรวจ contrast เฉพาะคู่สีที่อยู่ใน component เดียวกัน ถ้าไฟล์มีแต่ colors และไม่มี components สีของคุณจะไม่ถูกตรวจ contrast เลย นี่คือเหตุผลที่ตัวอย่างข้างบนมี card และ hint-text สอง component นี้ทำให้คู่ ink บน surface และ muted บน surface ถูกตรวจด้วย
อยากเห็นว่า warning หน้าตาเป็นอย่างไร ให้ลองเปลี่ยน muted เป็น "#A39A90" แล้วรัน lint ใหม่ สีนี้บนพื้น #FAF7F2 ได้ contrast ราว 2.6:1 ตามสูตรของ WCAG ซึ่งต่ำกว่าเกณฑ์ ผลที่ขึ้นบนเครื่องคุณคือพฤติกรรมจริงของ 0.4.0 ดูเสร็จแล้วอย่าลืมเปลี่ยนกลับก่อน commit
สิ่งที่ lint ไม่ตรวจก็สำคัญพอกัน ในตารางกฎของ README ทั้งบน main และในแพ็กเกจ 0.4.0 ไม่มีกฎข้อไหนตรวจว่า fontFamily มีอักษรไทยหรือไม่ และไม่มีกฎตรวจว่า lineHeight พอสำหรับภาษาไทย ไฟล์ที่ตั้งฟอนต์ละตินล้วนให้หน้าภาษาไทยจึงผ่าน lint ได้ งานสองอย่างนี้เป็นหน้าที่ของคนเขียนไฟล์ ถ้าอยากเห็นรายการกฎที่เวอร์ชันของคุณใช้จริง ให้รัน spec --rules
lint ตรวจโครงสร้าง ไม่ได้ตรวจรสนิยม ไฟล์ที่ผ่าน lint ทุกข้อก็ยังได้หน้าจอที่จืดได้ ถ้าปัญหาของคุณคือ agent ออกแบบหน้าตาซ้ำแบบเดิมทุกครั้ง ลองใช้ skill ที่ช่วยให้ agent ออกแบบ UI ได้ดีขึ้น ควบคู่กับ DESIGN.md
ใช้ diff หา regression ตอนรีวิว pull request
เมื่อ agent หรือเพื่อนร่วมทีมแก้ DESIGN.md ใน pull request การอ่าน diff ของ YAML ทีละบรรทัดเห็นแค่ข้อความที่เปลี่ยน คำสั่ง diff ของแพ็กเกจเทียบไฟล์สองเวอร์ชันในระดับ token แทน โดยรับไฟล์ "ก่อน" และ "หลัง" ตามลำดับ
git fetch origin
git show origin/main:DESIGN.md > /tmp/DESIGN.main.md
npx @google/design.md@0.4.0 diff /tmp/DESIGN.main.md DESIGN.mdREADME นิยาม regression ว่าไฟล์ "หลัง" มี error หรือ warning มากกว่าไฟล์ "ก่อน" ลองนึกถึง PR ที่เปลี่ยน primary เป็นสีอ่อนลงจนปุ่มหลักผ่านเกณฑ์ contrast ไม่ได้ ไฟล์ใหม่จะมี warning เพิ่มหนึ่งข้อ จึงนับเป็น regression ทั้งที่ diff ของ git แสดงแค่รหัสสีบรรทัดเดียว ค่าเริ่มต้นของ --format สำหรับ diff คือ json ดูตัวเลือกอื่นได้จาก diff --help
export token เป็น Tailwind หรือ W3C DTCG
เมื่อ token ถูกต้องแล้ว ขั้นต่อไปคือให้โค้ดใช้ค่าจากไฟล์เดียวกัน ไม่ใช่ให้ agent คัดลอกรหัสสีไปวางเอง คำสั่ง export บังคับให้ระบุ --format เสมอ เริ่มจากดูรายชื่อ format ที่เวอร์ชันของคุณรองรับจริง
npx @google/design.md@0.4.0 export --helpREADME ที่แนบมาในแพ็กเกจ 0.4.0 ระบุไว้สี่ชื่อ ตรงกับ README บน main:
css-tailwind: CSS แบบ@themeของ Tailwind v4json-tailwind: JSON สำหรับtheme.extendของ Tailwind v3tailwind: ชื่อย่อของjson-tailwinddtcg: รูปแบบ Design Tokens Format Module ของ W3C สำหรับเครื่องมืออื่นที่อ่านมาตรฐานนี้
รายชื่อนี้มาจาก README ไม่ได้มาจากการรัน --help ถ้า --help บนเครื่องคุณแสดงชื่อต่างจากนี้ ให้เชื่อ --help
npx @google/design.md@0.4.0 export --format css-tailwind DESIGN.md > theme.css
npx @google/design.md@0.4.0 export --format json-tailwind DESIGN.md > tailwind.theme.json
npx @google/design.md@0.4.0 export --format dtcg DESIGN.md > tokens.jsonเปิดไฟล์ที่ได้อ่านก่อนนำไปใช้ และอย่าแก้ไฟล์ที่ export ออกมาด้วยมือ ให้แก้ DESIGN.md แล้ว export ใหม่ ถ้าแก้ปลายทางโดยตรง สองไฟล์จะไม่ตรงกันตั้งแต่ครั้งแรกที่มีคนแก้ และ agent จะไม่รู้ว่าควรเชื่อไฟล์ไหน พอแอปพร้อมขึ้นจริง ขั้นตอน deploy อยู่ใน วิธีโฮสต์แอปที่ AI เขียนบน VPS ของคุณเอง
ไฟล์สำเร็จรูปจาก designmd.ai และ awesome-design-md เชื่อได้แค่ไหน
การเริ่มจากไฟล์ที่คนอื่นทำไว้ช่วยประหยัดเวลา แต่ต้องรู้ว่าไฟล์มาจากไหน
designmd.ai เป็นคลังที่ชุมชนอัปโหลด หน้าแรกเขียนว่า "100s of free design systems for AI-powered development" แต่ละรายการเป็น DESIGN.md ไฟล์เดียว ค้นตาม tag ได้ ผู้อัปโหลดเลือก license เอง (MIT, CC0, CC-BY, CC-BY-SA หรือ license เฉพาะ) เว็บมี CLI ชื่อ designmd ที่ต้องใช้ API key ฟรีเพื่อดูและดาวน์โหลด และมี MCP server ด้วย หน้า CLI บอกว่า tool definitions ของ MCP จะถูกโหลดเข้าทุกบทสนทนา ราว 1 ถึง 2 พัน token
ข้อสำคัญอยู่ในข้อตกลงการใช้งานของ designmd.ai เว็บเขียนไว้ว่าไม่รับรองและไม่ตรวจสอบคุณภาพ ความถูกต้อง หรือความปลอดภัยของไฟล์ที่ผู้ใช้อัปโหลด มีแค่การสแกนอัตโนมัติ และเว็บไม่ได้บอกว่าแต่ละไฟล์ออกแบบขึ้นเองหรือถอดแบบมาจากแบรนด์ไหน
awesome-design-md ของ VoltAgent เป็นชุด DESIGN.md ของแบรนด์ดัง repo บอกว่าไฟล์ "extracted from real websites" จากค่า CSS ที่มองเห็นได้สาธารณะ และใช้ฟอร์แมต DESIGN.md ของ Stitch license MIT ครอบคลุมตัว repo ส่วนเรื่องแบรนด์ repo เขียนเองว่าไม่ได้อ้างความเป็นเจ้าของ visual identity ของเว็บไหน แปลว่าหน้าตาของแบรนด์นั้นไม่ได้มาพร้อม license ของ repo ผมยังไม่ได้ตรวจว่าทุกไฟล์ใน repo มี YAML front matter ครบตามที่ lint ต้องการ
ไม่ว่าจะได้ไฟล์มาจากที่ไหน ให้ทำตามลำดับนี้ก่อน commit:
- บันทึกไฟล์เป็นชื่ออื่นก่อน เช่น
DESIGN.candidate.mdแล้วรันlintกับไฟล์นั้น - แทนรหัสสีด้วยสีแบรนด์ของคุณเอง แล้ว lint อีกรอบเพื่อดู contrast ของคู่สีใหม่
- เปลี่ยน
fontFamilyทุกตัวเป็นฟอนต์ที่ผ่านการเช็กsubsets: "thai"แล้วปรับlineHeight - ถ้ามี DESIGN.md เดิมอยู่แล้ว รัน
diffเทียบกับไฟล์เดิม เพื่อดูว่า token ไหนจะเปลี่ยน
ไฟล์ที่ได้มาจะผ่าน lint หรือไม่ก็ตาม เรื่องฟอนต์ไทยยังไม่มีใครตรวจให้คุณ เพราะ lint ไม่มีกฎข้อนั้น
ให้ Claude Code อ่าน DESIGN.md ผ่าน CLAUDE.md หรือ AGENTS.md
ไฟล์ที่ดีแค่ไหนก็ไม่มีผลถ้า agent ไม่ได้อ่าน วิธีที่แน่นอนที่สุดใน Claude Code คือ import ไฟล์จาก CLAUDE.md ด้วยไวยากรณ์ @path/to/import ตามเอกสาร memory ของ Claude Code ไฟล์ที่ import จะถูกโหลดตอนเริ่ม session พร้อมกับ CLAUDE.md
# Project instructions
งาน UI ทุกหน้าต้องใช้ token จาก DESIGN.md ห้ามเขียนรหัสสีหรือชื่อฟอนต์ลงในโค้ดตรงๆ
ถ้าต้องการค่าที่ไม่มีใน token ให้ถามก่อน อย่าคิดค่าใหม่เอง
@DESIGN.mdกฎของการ import ที่คนพลาดบ่อย:
- บรรทัด
@DESIGN.mdต้องเป็นข้อความธรรมดา เอกสารบอกว่าการ parse import จะข้าม code span และ fenced code block ถ้าครอบมันด้วย backtick เพื่อให้ดูสวย ไฟล์จะไม่ถูกโหลด - path ที่อยู่ในเครื่องหมายคำพูดจะไม่ถูก import ถ้า path มีช่องว่าง ให้ใส่ backslash หน้าช่องว่างแต่ละตัว
- path แบบ relative นับจากตำแหน่งของไฟล์ที่เขียน import ไม่ใช่จากโฟลเดอร์ที่คุณเปิด Claude Code
- import ซ้อนกันได้ลึกสุดสี่ชั้น และถ้า path ชี้ออกนอก working directory Claude Code จะขึ้นหน้าต่างขออนุมัติก่อน
ไฟล์ที่ import ถูกโหลดตอนเริ่มทุกครั้ง DESIGN.md จึงกิน context ทุก session การ import ไม่ได้ช่วยประหยัด ให้เขียนไฟล์ให้กระชับ
ถ้าโปรเจกต์ใช้ AGENTS.md เป็นไฟล์กลางให้หลาย agent ให้รู้ว่า Claude Code ตั้งแต่ v2.1.277 อ่าน AGENTS.md ได้เองโดยตรง แต่โดยค่าเริ่มต้นจะอ่านเฉพาะเมื่อไม่มี CLAUDE.md หรือ CLAUDE.local.md ใน working directory หรือโฟลเดอร์ที่อยู่สูงกว่า ถ้ามีทั้งสองไฟล์ Claude Code อ่านแค่ CLAUDE.md เอกสารจึงแนะนำให้ใส่บรรทัด @AGENTS.md ใน CLAUDE.md หรือจะเปลี่ยนค่า Project instructions ใน /config เป็น claude-md-and-agents-md เพื่อให้อ่านทั้งสองไฟล์ก็ได้ เช็กเวอร์ชันของคุณด้วย claude --version
รูปแบบที่ใช้ได้แน่นอนคือให้ CLAUDE.md มีบรรทัด @AGENTS.md และ @DESIGN.md แล้วให้ AGENTS.md มีประโยคบอก agent ตัวอื่นว่ากฎ UI อยู่ใน DESIGN.md เรื่องการแบ่งหน้าที่ของไฟล์คำสั่งแต่ละแบบอ่านต่อได้ใน AGENTS.md กับ HUMAN.md ต่างกันอย่างไร สำหรับ Cursor และ Stitch ผมยังไม่ได้ตรวจกลไกการอ่านไฟล์ของสองตัวนั้น ให้ดูจากเอกสารของแต่ละเครื่องมือ
ข้อสุดท้าย เอกสารของ Claude Code บอกว่าไฟล์ memory เป็นบริบท ไม่ใช่การตั้งค่าที่ถูกบังคับใช้ agent จึงอาจไม่ทำตาม DESIGN.md ทุกครั้ง ตรวจผลงานด้วย lint และด้วยตาเสมอ ถ้าเจอปัญหาซ้ำๆ อ่าน ทำไม agent ถึงไม่ทำตามคำสั่งในไฟล์ของคุณ
FAQ
npx @google/design.md ใช้กับ Node.js 18 ของ Ubuntu 24.04 ได้ไหม
แพ็กเกจ 0.4.0 ประกาศในช่อง engines ว่าต้องใช้ Node >=18.0.0 และ Ubuntu 24.04 มี nodejs 18.19.1 จึงผ่านเกณฑ์ ติดตั้งด้วย sudo apt install -y nodejs npm แล้วเช็กด้วย node -v ช่อง engines เป็นแค่สิ่งที่แพ็กเกจประกาศ ไม่ได้รับประกันว่าผู้พัฒนาทดสอบบนรุ่นนี้ ถ้าเจอ error ที่ไม่เกี่ยวกับไฟล์ของคุณ ให้ลองบน Node 22 ซึ่งเป็นรุ่นที่มากับ Ubuntu 26.04
ไฟล์ผ่าน lint แล้ว ทำไมตัวอักษรไทยบนหน้าเว็บยังดูผิด
กฎ lint ที่ README ระบุไว้ไม่มีข้อไหนตรวจว่าฟอนต์รองรับอักษรไทย หรือ line-height พอสำหรับสระและวรรณยุกต์ ถ้า fontFamily เป็นฟอนต์ละตินล้วน browser จะหยิบฟอนต์ไทยในเครื่องผู้ใช้มาแสดงแทน ผลจึงต่างกันไปในแต่ละเครื่อง เช็กไฟล์ METADATA.pb ของฟอนต์ใน repository google/fonts ว่ามีบรรทัด subsets: "thai" แล้วเพิ่ม lineHeight จนวรรณยุกต์ไม่ชนกับบรรทัดบน
ทำไม lint ไม่เตือนเรื่อง contrast ของสีที่ฉันเพิ่มเข้าไป
กฎ contrast-ratio ตรวจเฉพาะคู่ backgroundColor กับ textColor ที่อยู่ใน component เดียวกัน สีที่อยู่ใน colors อย่างเดียวจะไม่ถูกตรวจ ให้สร้าง component ที่จับคู่สีนั้นกับพื้นหลังที่ใช้จริง เช่น component ข้อความรองบนพื้นการ์ด แล้วรัน lint ใหม่ เกณฑ์ที่ใช้คือ 4.5:1 ระดับ AA ของ WCAG
เขียน @DESIGN.md ไว้ใน CLAUDE.md แล้ว ทำไม Claude Code ไม่โหลดไฟล์
สาเหตุที่พบบ่อยคือบรรทัดนั้นอยู่ใน backtick หรือใน code block ซึ่ง Claude Code ข้ามไปตอน parse import หรือ path อยู่ในเครื่องหมายคำพูด อีกสาเหตุคือ path แบบ relative นับจากตำแหน่งของ CLAUDE.md ไม่ใช่จากโฟลเดอร์ปัจจุบัน ถ้าไฟล์อยู่นอก working directory คุณต้องกดอนุมัติในหน้าต่างที่ขึ้นมาก่อน ไฟล์จึงจะถูกโหลด
ดาวน์โหลด DESIGN.md จาก designmd.ai มาใช้ได้ทันทีไหม
ไม่ควร ข้อตกลงของ designmd.ai เขียนว่าเว็บไม่รับรองและไม่ตรวจสอบคุณภาพ ความถูกต้อง หรือความปลอดภัยของไฟล์ที่ผู้ใช้อัปโหลด และ license ขึ้นกับที่ผู้อัปโหลดเลือก ให้ lint ไฟล์ก่อน แทนสีด้วยสีแบรนด์ของคุณแล้ว lint อีกครั้งเพื่อดู contrast เปลี่ยนฟอนต์เป็นฟอนต์ที่มีอักษรไทย จากนั้นจึง commit