AI Builder OS — เว็บไซต์ส่วนตัวที่สร้างจาก spec เดียว
เว็บไซต์ส่วนตัวแบบ static ที่สร้างด้วย Astro โดยเขียน spec ให้ครบก่อนแล้วค่อยสร้างตามทีละเฟส ทุกหน้าเป็น HTML ที่ build ไว้ล่วงหน้า มีระบบค้นหา RSS sitemap และชุดทดสอบอัตโนมัติที่รันบน CI
- ปัญหา
- งานที่ทำและสิ่งที่เรียนรู้กระจายอยู่บนแพลตฟอร์มของคนอื่น ค้นย้อนหลังไม่ได้และไม่มีที่ที่เป็นของตัวเองจริง ๆ
- วิธีแก้
- เว็บไซต์ static ที่เก็บเนื้อหาเป็นไฟล์ Markdown ใน git มี schema บังคับความถูกต้องตั้งแต่ตอน build และ deploy อัตโนมัติจากการ push
เทคโนโลยีที่ใช้
- Astro
- TypeScript
- Tailwind CSS
- Markdown
- Zod
- Pagefind
- Vitest
- Playwright
- GitHub Actions
- Vercel
ผลลัพธ์
- build ออกมาเป็นหน้า static 37 หน้าโดยไม่มี client-side framework (pnpm build ณ วันที่เขียน)
- unit test 57 เคสใน 6 ไฟล์ ผ่านทั้งหมด (pnpm test)
- end-to-end test 38 เคสใน 4 ไฟล์ รันทั้ง desktop และ mobile profile (pnpm exec playwright test --list)
- Pagefind สร้าง search index ครอบคลุมทุกหน้าที่ build ในขั้นตอนเดียวกัน (log จาก pnpm build)
ปัญหาคืออะไร
งานที่ทำและบันทึกสิ่งที่เรียนรู้ระหว่างทางกระจายอยู่บนแพลตฟอร์มของคนอื่น — โพสต์บน social media, ข้อความในแชท, ไฟล์ในเครื่อง เมื่ออยากกลับไปหาว่าเคยแก้ปัญหาเรื่องหนึ่งไว้ อย่างไร ก็ค้นไม่เจอ และเนื้อหาเหล่านั้นก็ขึ้นอยู่กับว่าแพลตฟอร์มจะยังอยู่และยังแสดงผลให้ใคร เห็นหรือไม่
อีกด้านหนึ่งคือเรื่องความน่าเชื่อถือ การจะบอกว่าทำอะไรได้บ้าง ต้องมีที่ให้คนเข้ามาดูงานจริง ไม่ใช่แค่รายการทักษะ
ใครเจอปัญหานี้
คนที่สร้างของและอยากให้งานของตัวเองค้นเจอได้ในระยะยาว — developer, freelance, คนที่ทำงานสาย AI ที่ต้องอธิบายงานให้ลูกค้าหรือผู้ร่วมงานเข้าใจ
ในกรณีนี้ผู้ใช้คนแรกและคนหลักคือตัวผมเอง เว็บไซต์นี้เป็นทั้งที่เก็บงานและเป็นตัวอย่างงาน ในตัวเดียวกัน
สร้างอะไรขึ้นมา
เว็บไซต์ส่วนตัวแบบ static ประกอบด้วยหน้าแรก, about, บทความ, โปรเจกต์, builder log, experiments, talks, products, newsletter, contact และหน้า archive ที่ generate อัตโนมัติแยกตาม category กับ tag รวมแล้ว 37 หน้า ณ ตอนที่เขียนบทความนี้ — จำนวน จะเพิ่มเองทุกครั้งที่มีเนื้อหาใหม่
ทุกหน้าถูก build เป็นไฟล์ HTML ล่วงหน้าตั้งแต่ตอน deploy ไม่มีเซิร์ฟเวอร์ที่ต้อง render ตอนมีคนเข้า และไม่มีฐานข้อมูล
จุดตั้งต้นของโปรเจกต์นี้ไม่ใช่โค้ด แต่เป็นไฟล์ spec (AGENTS.md) ที่เขียนขอบเขต
version หนึ่ง, สิ่งที่ตั้งใจ ไม่ ทำ, และลำดับการสร้างหกเฟสไว้ก่อนจะเริ่มเขียนบรรทัดแรก
เฟสหนึ่งถึงหกคือ foundation, content system, core pages, discovery, quality และ
launch — git history ของ repo นี้เดินตามลำดับนั้นตรง ๆ
ทำงานอย่างไร
เนื้อหาทุกชิ้นเป็นไฟล์ Markdown ที่อยู่ใน git โดยแยกโฟลเดอร์ตามประเภท แต่ละประเภทมี
schema ของตัวเองเขียนด้วย Zod ใน src/content.config.ts เวลา build Astro จะ
ตรวจ frontmatter ทุกไฟล์กับ schema — ถ้าพิมพ์ชื่อ field ผิดหรือใส่ค่าที่ไม่อยู่ในชุดที่
กำหนด build จะพังทันที ไม่ปล่อยให้หน้าเว็บออกมาเสียแล้วค่อยมาเจอทีหลัง
จุดที่ตั้งใจออกแบบไว้คือ field ที่พูดถึงผลลัพธ์จริง เช่น results เป็น optional ทั้งหมด
เพราะถ้าบังคับให้กรอก มันจะกลายเป็นแรงกดดันให้เขียนตัวเลขที่ยังไม่มี
ขั้นตอนตั้งแต่เขียนจนขึ้นเว็บคือ: เขียนไฟล์ Markdown → commit → push → GitHub Actions รัน lint, type check, unit test, build และ end-to-end test → Vercel build แล้ว deploy หน้าใหม่ ไม่มีขั้นตอนที่ต้องเข้าไปกดใน admin panel
ระบบค้นหาใช้ Pagefind ซึ่งทำ index หลังจาก Astro build เสร็จ ตัว index เป็นไฟล์ static ที่โหลดเฉพาะตอนผู้ใช้เปิดกล่องค้นหา ไม่มี search API อยู่เบื้องหลัง
ธีมสว่าง/มืดถูก apply ด้วย inline script ก่อน first paint เพื่อไม่ให้เห็นหน้าจอกระพริบ ตอนโหลด และ markup เขียนโดยยึดแนวทาง WCAG — heading เรียงลำดับ, ทุก interactive element ใช้คีย์บอร์ดได้, มี skip link
ใช้เทคโนโลยีอะไร
- Astro 7 — เลือกเพราะ output เป็น static HTML ล้วนโดยไม่ต้องแลกกับการเขียน component แบบเก่า ๆ และไม่ส่ง JavaScript framework ไปหาผู้ใช้
- TypeScript (pin ไว้ที่ 6.x) — type check ทั้ง
.astroและ.ts - Tailwind CSS v4 — ตั้ง design token ไว้ที่
src/styles/global.cssที่เดียว ไม่มีไฟล์ config แยก - Markdown + Zod ผ่าน Astro content collections — เนื้อหาอยู่ใน git, schema บังคับความถูกต้องตั้งแต่ build
- Pagefind — search index แบบ static
- RSS, sitemap, JSON-LD, OG image ที่ generate ตอน build — สำหรับ SEO และการแชร์
- Vitest สำหรับ unit test และ Playwright สำหรับ end-to-end
- GitHub Actions สำหรับ CI และ Vercel สำหรับ hosting โดยตั้ง CSP กับ
security header ไว้ใน
vercel.json
เจออุปสรรคอะไรบ้าง
TypeScript 7 ใช้ไม่ได้ — ตอนตั้งโปรเจกต์ TypeScript 7 ออกแล้ว แต่ทั้ง
@astrojs/check และ typescript-eslint ยังกำหนด peer dependency ไว้ต่ำกว่า
สุดท้าย pin TypeScript ไว้ที่ 6.x และเขียนหมายเหตุไว้ใน README ว่าเป็นการรอ
เครื่องมือ ไม่ใช่การเลือกเอง
ระบบค้นหาพังเพราะ Vite — script ที่ import Pagefind ถูก Vite แปลง dynamic
import() เป็น helper ชื่อ __vitePreload แต่สำหรับ script ที่ Astro inline ลงใน
HTML อาร์กิวเมนต์ __VITE_PRELOAD__ ไม่ถูกแทนค่า ทำให้โยน ReferenceError ก่อน
จะได้ import ด้วยซ้ำ และ catch ที่ครอบอยู่ก็รายงานผิดเป็น “index ยังไม่ได้ build”
ทางแก้คือย้ายไปใช้ is:inline script ซึ่ง Astro ปล่อยออกมาตามที่เขียนโดยไม่ผ่าน
Vite — คำอธิบายอยู่ในคอมเมนต์เหนือ script ใน SearchDialog.astro
CSP บล็อก WebAssembly — หลังเพิ่ม CSP ค้นหาบนเว็บจริงพังทันที เพราะ Pagefind
compile WASM module ซึ่ง script-src บล็อกถ้าไม่มี 'wasm-unsafe-eval' ที่แย่กว่านั้น
คือมองไม่เห็นตอน dev เลย เพราะ dev server และ preview server ไม่ได้ใส่ CSP —
มีแต่ host ที่ใส่ ทางแก้คือเพิ่ม 'wasm-unsafe-eval' (ซึ่งอนุญาตเฉพาะ WebAssembly
ไม่รวม eval ธรรมดา) แล้วเขียน unit test ล็อกไว้ว่า policy ต้องมี directive ที่เว็บ
พึ่งพาอยู่ครบและต้องเหมือนกันทั้ง vercel.json กับ public/_headers
Vercel ไม่อ่าน public/_headers — ไฟล์นั้นใช้กับ Cloudflare Pages และ Netlify
เท่านั้น พอ deploy ขึ้น Vercel จริงแล้วไปเช็ค header ที่ตอบกลับมา พบว่ามีแค่ HSTS
ของ Vercel เอง ไม่มี CSP, X-Content-Type-Options, Referrer-Policy,
X-Frame-Options หรือ Permissions-Policy เลย ทางแก้คือเพิ่ม vercel.json ที่มี
เนื้อหาตรงกับ public/_headers เพื่อให้ย้าย host ได้โดยไม่เสีย policy
บทเรียนร่วมของสองข้อหลังคือ config ที่ทำงานเฉพาะบน production เป็นจุดบอดที่การ ทดสอบในเครื่องมองไม่เห็น
ผลลัพธ์ที่ได้
ตัวเลขทั้งหมดนี้มาจากการรันคำสั่งใน repo:
pnpm build— build สำเร็จเป็นหน้า static 37 หน้า ไม่มี client-side framework (ตัวเลขนี้โตตามเนื้อหาที่เพิ่ม)pnpm test— unit test 57 เคสใน 6 ไฟล์ ผ่านทั้งหมดpnpm exec playwright test --list— end-to-end 38 เคสใน 4 ไฟล์ รันบนทั้ง desktop และ mobile profile- log จาก
pnpm build— Pagefind ทำ search index ครอบคลุมทุกหน้าที่ build
ทั้งหกเฟสตาม AGENTS.md §34 ทำครบและเว็บ deploy ขึ้น production แล้ว
สิ่งที่ยัง ไม่มี ตัวเลข: จำนวนผู้เข้าชม, ผู้สมัคร newsletter, และรายได้ — analytics ต่อผ่าน environment variable ไว้แล้วแต่ยังไม่มีข้อมูลย้อนหลังพอที่จะรายงาน เมื่อมี ตัวเลขจริงจะกลับมาอัปเดตตรงนี้
จะปรับปรุงอะไรต่อ
สิ่งที่ยังค้างอยู่คือส่วนที่ต้องใช้บัญชีจริงและเวลาสะสม:
- ต่อ newsletter provider จริง — ตอนนี้ฟอร์มยังแสดงสถานะ disabled ที่ระบุชัดว่ายัง ไม่พร้อม
- เก็บข้อมูล analytics จนพอที่จะรายงานได้อย่างซื่อสัตย์
- เขียนเนื้อหาให้ครบตามที่วางไว้ — ตอนนี้ collection หลายอันยังว่างและ project
ส่วนใหญ่ยังเป็นโครงที่มีสถานะ
ideaหรือbuilding - ถอด pin TypeScript ออกเมื่อ
@astrojs/checkและtypescript-eslintรองรับ version 7 - เพิ่มการวัด performance เป็นตัวเลขจริง แทนที่จะอ้างว่าเร็วเพราะเป็น static
ลองใช้ได้ที่ไหน
เว็บไซต์อยู่ที่ site.aiparuay.com — หน้าที่คุณกำลังอ่านอยู่นี้ คือส่วนหนึ่งของระบบที่กำลังอธิบาย ถ้าอยากลองส่วนที่น่าสนใจที่สุด ให้ลองกดค้นหา (ปุ่มค้นหาบน header) แล้วสังเกตว่ามันตอบทันทีโดยไม่มี request ไปหาเซิร์ฟเวอร์ใด ๆ หรือสลับธีมสว่าง/มืดแล้ว reload ดูว่าไม่มีการกระพริบ
ซอร์สโค้ดอยู่ที่ไหน
repository ยังเป็น private อยู่ จึงไม่มีลิงก์ให้ในตอนนี้ รายละเอียดเชิงเทคนิคที่พอจะ แบ่งปันได้ถูกเขียนไว้ในหัวข้อ “เจออุปสรรคอะไรบ้าง” ข้างบน และจะทยอยเขียนเพิ่มใน builder log
รับบทเรียน AI ที่ใช้ได้จริง ทางอีเมล
หนึ่งบทเรียน AI ที่ใช้ได้จริง การแกะโปรเจกต์ หรือข้อคิดจากการสร้างของ สัปดาห์ละครั้ง