- สรุปแพตเทิร์นการออกแบบที่ทำซ้ำบ่อย จากประสบการณ์สร้าง HTML tools ที่รวม HTML·JavaScript·CSS ไว้ในไฟล์เดียวและรันได้ทันที
- อธิบายด้วยกรณีศึกษาที่เป็นรูปธรรมว่าเครื่องมือขนาดเล็กกว่า 150 ชิ้นที่สร้างขึ้นตลอด 2 ปี ถูกสร้างและดูแลรักษาจริงอย่างไร
- โครงสร้างที่ไม่มีขั้นตอน build และการใช้ CDN ทำให้เกิดเวิร์กโฟลว์การพัฒนาแบบ คัดลอก·วางเป็นหลัก อย่างเป็นธรรมชาติ
- ขยายขอบเขตสิ่งที่ทำได้ด้วยความสามารถของเบราว์เซอร์เพียงอย่างเดียว ตั้งแต่ URL·localStorage·การเปิดไฟล์·การดาวน์โหลด·Pyodide·WebAssembly
- การบันทึกพรอมป์ต์และผลลัพธ์ รวมถึงการนำเครื่องมือเดิมมาประกอบใหม่ ช่วยเสริมให้ คอลเลกชันเครื่องมือ กลายเป็นฐานสำหรับการพัฒนาเอง
แนวคิดและตัวอย่างของ HTML tools
โครงสร้างพื้นฐานของ HTML tool
- เป็น ไฟล์ HTML เดียว ที่ฝัง JavaScript และ CSS แบบ inline
- ไม่ใช้ React ที่ต้องมีการ build JSX ทำให้ การคัดลอก·แจกจ่ายต่อเป็นเรื่องง่าย
- ไลบรารีที่จำเป็นโหลดตรงจาก CDN เช่น CDNjs หรือ jsDelivr และลด dependency ให้เหลือน้อยที่สุด
- คงขนาดโค้ดไว้ที่ระดับไม่กี่ร้อยบรรทัด เพื่อลดภาระการดูแลรักษาและทำให้ LLM อ่านและแก้ไขได้รวดเร็ว
การทำต้นแบบด้วย Canvas·Artifacts
- ใช้ ChatGPT Canvas, Claude Artifacts, Gemini Canvas เพื่อรัน HTML tool ได้ทันทีและขึ้นรูปต้นแบบเริ่มต้น
- ใส่เงื่อนไข “No React” เพื่อให้ได้โค้ดที่ทำงานได้ทันทีโดยไม่มีขั้นตอน build
- ตัวอย่างการแปลง JSON ที่วางลงไปให้เป็น YAML
ถ้าซับซ้อนขึ้น ให้เปลี่ยนไปใช้ coding agent
- ใช้ Claude Code หรือ Codex CLI เพื่อทำงานวนซ้ำอัตโนมัติ รวมถึงการทดสอบบนเบราว์เซอร์ด้วย Playwright ได้
- สำหรับเครื่องมือที่ซับซ้อนขึ้น (เช่น ตัวดูเธรด Bluesky) จะใช้วิธี “อัปเกรด” ไปยัง agent เหล่านี้
- สร้าง PR เข้าไปยังรีโป simonw/tools โดยตรงเพื่อเพิ่มหรืออัปเดตเครื่องมือ
- ดูขั้นตอนการทำงานด้วย web-based agent ได้จาก วิดีโอการใช้ Claude Code for web
การจัดการ dependency บนพื้นฐาน CDN
- เมื่อต้องใช้ไลบรารีเพิ่มเติม จะโหลดจาก CDN
- Artifacts/Canvas ของ LLM มี CDN allow-list ที่อนุญาตไว้ จึงสามารถออกแบบ URL ได้จากคำสั่งอย่าง “ใช้ PDF.js”
- หากจำเป็น จะค้นหา URL จาก cdnjs·jsDelivr แล้ววางลงในแชต
- ทำงานได้ด้วยไฟล์ HTML ไฟล์เดียว โดยไม่ต้องติดตั้ง npm หรือมีขั้นตอน build
- npm+build step ทำให้ประสิทธิภาพในการแฮ็กเครื่องมือเฉพาะทางอย่างรวดเร็วและ self-host ลดลง
- URL ของ CDN มีเวอร์ชันรวมอยู่ด้วย จึงช่วยคงความสามารถในการทำซ้ำได้ในระยะยาว
โฮสติ้งแบบสแตติกภายนอก
- การโฮสต์ภายในแพลตฟอร์ม LLM มีข้อจำกัดของ sandbox มาก ทำให้บางครั้งโหลดข้อมูล/ภาพจาก URL ภายนอกหรือทำลิงก์ออกภายนอกไม่ได้
- ในแง่ประสบการณ์ผู้ใช้ อาจมีปัญหาอย่างข้อความเตือน การโหลดเพิ่ม หรือการโปรโมตแพลตฟอร์มแทรกเข้ามา
- การจับคู่ “No React + CDN” ทำให้อัปโหลดขึ้นที่ไหนก็ได้ง่ายโดยไม่ต้อง build
- แค่อัปโหลดไฟล์ HTML ไปยัง GitHub Pages ก็เข้าถึงได้ทันทีผ่าน URL คงที่
- เครื่องมือส่วนใหญ่จัดการในรีโป simonw/tools และให้บริการผ่าน tools.simonwillison.net
อินพุต/เอาต์พุตที่เน้นคัดลอก·วาง
- เครื่องมือจำนวนมากใช้กลไกหลักเป็นการแปลงข้อมูลที่ผู้ใช้วางลงไป แล้วให้ คัดลอกกลับไปยังคลิปบอร์ด
- เพราะการคัดลอก·วางบนมือถือไม่สะดวก จึงมักเพิ่มปุ่ม “Copy to clipboard”
- คลิปบอร์ดของ OS สามารถเก็บได้หลายฟอร์แมตพร้อมกัน และใน paste event ของ JavaScript ก็เข้าถึงข้อมูลแบบ “rich” นี้ได้
- เครื่องมือตัวอย่าง
เครื่องมือสำหรับดีบัก
- สร้างเครื่องมือเฉพาะเพื่อดูโครงสร้างข้อมูลจริงที่ถูกจัดการอยู่ในเบราว์เซอร์
- clipboard-viewer: แสดงข้อมูลทั้งหมดในคลิปบอร์ด ทั้งข้อความ·rich text·รูปภาพ·ไฟล์ ฯลฯ
- เครื่องมือเพิ่มเติม
เก็บสถานะไว้ใน URL
- แม้ไม่มีฐานข้อมูลฝั่งเซิร์ฟเวอร์ ก็ยังเก็บสถานะจำนวนมากไว้ใน URL ได้
- นิยมใช้แพตเทิร์นนี้กับเครื่องมือที่คำนึงถึงการบุ๊กมาร์กและการแชร์
- icon-editor: เก็บสถานะการแก้ไขไอคอน 24×24 ไว้ใน URL โดยตรง
การใช้ localStorage
- localStorage คือ Browser API ที่เก็บข้อมูลไว้ถาวรบนอุปกรณ์ผู้ใช้โดยไม่เปิดเผยต่อเซิร์ฟเวอร์
- ใช้เก็บสถานะขนาดใหญ่ที่ใส่ใน URL ได้ยาก หรือค่าลับอย่าง API key เพื่อหลีกเลี่ยงความเสี่ยงจากการถูกบันทึกใน server log ของ static host
- word-counter: บันทึกข้อความที่กำลังเขียนอัตโนมัติ
- render-markdown: คงเนื้อหาที่กำลังเขียนเป็น Markdown ไว้
- haiku: เก็บ API key ใน localStorage เพื่อสร้างไฮกุจากภาพเว็บแคม
การใช้ API ที่รองรับ CORS
- CORS (Cross-origin resource sharing) คือกลไกที่ควบคุมว่า JavaScript บนเบราว์เซอร์จะเรียก API จากโดเมนอื่นได้หรือไม่
- API ที่เปิด CORS เป็นทรัพยากรที่เหมาะกับ HTML tools และเมื่อเวลาผ่านไปก็คุ้มที่จะสะสมรายการไว้
- ใช้งานกับ iNaturalist, PyPI, GitHub (เข้าถึงคอนเทนต์ของรีโปสาธารณะผ่าน raw.githubusercontent.com แบบไม่ระบุตัวตนได้), Bluesky, Mastodon เป็นต้น
- ตัวอย่างเครื่องมือ
เรียกใช้ LLM API โดยตรง
- เรียก OpenAI·Anthropic·Gemini JSON API จากเบราว์เซอร์โดยตรงผ่าน CORS
- หากฝัง API key ไว้ใน HTML จะมีความเสี่ยงทั้งการถูกขโมยและค่าใช้จ่าย จึงใช้ “secrets pattern” ที่เก็บไว้ใน localStorage
- ในแง่ประสบการณ์ผู้ใช้ ขั้นตอนขอและวาง API key มีแรงเสียดทานสูง แต่ก็ใช้งานได้จริง
- ตัวอย่างเครื่องมือ
อย่ากลัวการเปิดไฟล์
- ใช้
<input type="file"> เพื่ออ่านและใช้งานไฟล์ได้โดยตรงในเบราว์เซอร์โดยไม่ต้องอัปโหลดขึ้นเซิร์ฟเวอร์
- ocr: ใช้ PDF.js และ Tesseract.js แปลง PDF เป็นภาพรายหน้าแล้วทำ OCR บนเบราว์เซอร์
- social-media-cropper: เปิด/วางรูปภาพแล้วครอปตามสัดส่วนสำหรับโซเชียลมีเดีย (เช่น Twitter/LinkedIn 2:1, Substack 1.4:1 ฯลฯ)
- ffmpeg-crop: สร้างคำสั่ง ffmpeg สำหรับครอปวิดีโอ
ให้ดาวน์โหลดไฟล์ได้
- แม้ไม่มีเซิร์ฟเวอร์ ก็สามารถสร้างไฟล์ในเบราว์เซอร์แล้วให้ดาวน์โหลดได้
- ใน ecosystem ของ JavaScript มีไลบรารีสำหรับสร้างไฟล์หลายฟอร์แมต
- ตัวอย่างเครื่องมือ
Pyodide และ WebAssembly
- Pyodide คือดิสทริบิวชันที่คอมไพล์ Python เป็น WebAssembly เพื่อให้รันในเบราว์เซอร์ได้
- โหลดจาก CDN ได้อย่างเรียบร้อย จึงแทบไม่มีเหตุผลที่จะไม่ใช้กับ HTML tools
- ผ่าน micropip สามารถโหลดแพ็กเกจ Python ล้วนจาก PyPI เพิ่มเติมผ่าน CORS ได้
- ตัวอย่างเครื่องมือ
ขยายให้กว้างขึ้นด้วย WebAssembly
- พื้นฐานที่ทำให้ Pyodide เป็นไปได้ก็คือ WebAssembly และยังทำให้ซอฟต์แวร์ที่เขียนด้วยภาษาอื่นโหลดมาใช้ในเบราว์เซอร์ได้ด้วย
- Squoosh.app ให้บริการไลบรารีบีบอัดภาพหลายตัวในเบราว์เซอร์
- ตัวอย่างเครื่องมือ
นำเครื่องมือเดิมมาประกอบใหม่
- เมื่อมีคอลเลกชันสาธารณะเดี่ยว ๆ มากกว่า 100 ชิ้น ข้อดีอีกอย่างคือ LLM สามารถ ประกอบเครื่องมือเหล่านั้นใหม่ ได้ง่าย
- บางครั้งใช้วิธีคัดลอกเครื่องมือเก่ามาใส่ในคอนเท็กซ์ หรือใน coding agent ก็อ้างอิงด้วยชื่อหรือให้ค้นหาตัวอย่าง
- ซอร์สโค้ดของเครื่องมือที่ทำงานได้จริง ทำหน้าที่เป็นเอกสารที่รวมถึงรูปแบบการใช้ไลบรารีสำหรับแก้ไขด้วย และช่วยเพิ่มโอกาสความสำเร็จของ LLM
- บันทึกกระบวนการสร้าง pypi-changelog แบบครบถ้วน: พรอมป์ต์ทรานสคริปต์
- พรอมป์ต์ถูกออกแบบโดยสั่งให้ดูเครื่องมือ “pypi package explorer” ก่อน แล้วอ่านซอร์สของ zip-wheel-explorer จากนั้นสร้างเครื่องมือใหม่ที่ดึง wheel จาก PyPI API มาเรนเดอร์ diff ระหว่างเวอร์ชัน และมีปุ่ม Copy ให้
- ดูเพิ่มเติมที่ การรัน OCR บนเบราว์เซอร์
การบันทึกพรอมป์ต์·ทรานสคริปต์
- การมีนิสัยบันทึกและเผยแพร่ประวัติการใช้ LLM ช่วยให้พัฒนาความสามารถในการใช้งานของตนเองได้
- สำหรับเครื่องมือที่สร้างบนแพลตฟอร์ม LLM แบบแชต จะใช้ฟังก์ชัน share เป็นวิธีเก็บบันทึก
- เมื่อใช้ agent อย่าง Claude Code·Codex CLI จะคัดลอกทรานสคริปต์ทั้งเทอร์มินัลแล้วแปลง log เป็น HTML ด้วย terminal-to-html ก่อนแชร์ผ่าน Gist
- เมื่อบันทึกเครื่องมือที่เสร็จแล้วลงรีโป จะใส่ลิงก์ทรานสคริปต์ไว้ใน commit message ด้วย - รวมบันทึก: tools.simonwillison.net/colophon
สรุป
- ตลอดปีครึ่งที่ผ่านมา การสำรวจ LLM และ HTML tools ด้วยวิธีนี้สนุกมาก และช่วยอย่างมากในการทำความเข้าใจทั้งขอบเขตสิ่งที่ HTML ทำได้และความสามารถของ LLM
- หากอยากเริ่มสร้างคอลเลกชันเครื่องมือของตัวเอง แค่สร้างรีโปบน GitHub แล้ว เปิด GitHub Pages จากนั้นคัดลอกไฟล์ .html ใส่ลงไปก็เริ่มได้เลย
- เป็นโบนัส ผู้เขียนยังให้ลิงก์ทรานสคริปต์ที่ใช้ Claude Code และ shot-scraper เพิ่มภาพหน้าจอให้บทความนี้
3 ความคิดเห็น
แพตเทิร์น HTML
ดูน่าสนุกนะ
เจ๋งมาก