6 คะแนน โดย GN⁺ 2025-05-04 | 5 ความคิดเห็น | แชร์ทาง WhatsApp
  • ตั้งเป้าทำบล็อกส่วนตัวเป็นหน้าเว็บแบบสแตติกบน โดเมนที่มีอยู่แล้ว โดยมุ่งสู่การทำให้ใช้งานได้ขั้นต่ำที่รองรับทั้งการเพิ่มคอนเทนต์และ SEO พื้นฐาน
  • การทำจริงเรียบง่ายต่อเนื่องด้วย template.html ขนาดเล็ก, markdown2, render.py ที่ขอให้ O1 ช่วยสร้าง, และการ เขียนบทความด้วย Markdown
  • เทมเพลตใช้เพียง HTML/CSS พื้นฐาน เช่น system-ui, ความกว้างสูงสุด 70ch, color-scheme: light dark, viewport, UTF-8
  • render.py จะแปลง ./posts/{post}/eng.md เป็น HTML ปรับพาธรูปภาพ แล้วสร้าง ./blog/{post}.html และ index.html
  • แสดงให้เห็นว่าสามารถสร้างบล็อกที่ดูแลได้ด้วยเพียง การเรนเดอร์แบบสแตติก และการโฮสต์ โดยไม่ต้องใช้ Jekyll, Ghost หรือ WordPress

ข้อกำหนดของบล็อกขั้นต่ำและโครงสร้างที่ใช้จริง

  • จุดตั้งต้นมีข้อกำหนดอยู่ 4 ข้อ
    • ใช้ โดเมน ที่เป็นเจ้าของอยู่แล้ว
    • เป็นไปตามมาตรฐานเว็บสมัยใหม่และมี SEO ที่ใช้ได้
    • เพิ่มคอนเทนต์ใหม่ได้ง่ายมาก
    • ทุกหน้าต้อง บิลด์แบบสแตติก
  • ขั้นตอนการทำจริงนั้นเรียบง่าย
    • เขียน template.html ขนาดเล็ก
    • รัน pip install markdown2
    • ขอให้ O1 สร้างสคริปต์ render.py
    • เขียนบทความ จากนั้นเรนเดอร์และโฮสต์
  • ไม่ได้ใช้เอนจินบล็อกสำเร็จรูปอย่าง Jekyll, Ghost หรือ WordPress

เทมเพลตและสคริปต์เรนเดอร์

  • template.html มีเพียงโครงสร้างเอกสาร HTML พื้นฐานและ CSS ขั้นต่ำ
    • กำหนดชุดสีสว่าง/มืดด้วย color-scheme: light dark
    • สไตล์เนื้อหาตั้งค่าเป็น system-ui, sans-serif, ความกว้างสูงสุด 70ch, ความสูงบรรทัด 1.5, ขนาดตัวอักษร 1.25em
    • ใช้ลิงก์กลับหน้าแรกที่มี id="head-link" และตัวแทนตำแหน่ง {{ content }}
  • render.py ใช้ markdown2 แปลงบทความ Markdown เป็น HTML
    • ไดเรกทอรีอินพุตคือ ./posts และเอาต์พุตคือ ./blog
    • แต่ละบทความอ่านจาก ./posts/{post_directory}/eng.md
    • ใช้หัวข้อ # แรกเป็นชื่อบทความ
    • แปลง Markdown ด้วยออปชัน fenced-code-blocks, header-ids
    • เปลี่ยนพาธรูปภาพจาก <img src=" ให้ยึดตาม /posts/{post_code}/
    • แทนที่ {{ content }} ในเทมเพลตด้วย HTML ที่แปลงแล้ว และเปลี่ยนสตริงชื่อเรื่องเป็นชื่อบทความ
  • หน้าอินเด็กซ์ก็ถูกสร้างจากสคริปต์เดียวกัน
    • แปลง greetings.md เป็น HTML ก่อน
    • อ่านชื่อบทความแต่ละรายการแล้วเพิ่มลิสต์ลิงก์ไปยัง /blog/{post_code}.html
    • บันทึกผลลัพธ์สุดท้ายเป็น index.html
  • บทความถูกเขียนด้วยมือเมื่อ 2025-03-31

5 ความคิดเห็น

 
ifmkl 2025-05-07

ตอนนี้ผมก็จัดการบล็อกของตัวเองแบบเดียวกับด้านบนเลยครับ ผมสร้างและใช้งาน SSG ที่ตอบโจทย์ความต้องการส่วนตัวของตัวเอง โดยเพิ่มฟังก์ชันคัสตอมทีละอย่างเพื่อให้ใช้ความสามารถอย่างรูปภาพ thumbnail, หมวดหมู่ และแท็กได้ด้วย รูปภาพที่แนบมาก็ถูกแปลงเป็น webp โดยอัตโนมัติแล้วอ้างอิงใช้งาน ทำให้ความเร็วในการเรนเดอร์น่าพอใจมากครับ

 
winterjung 2025-05-07

โอ้ ฟีเจอร์แบบคัสตอมพวกนั้นคุณค่อย ๆ เขียนโค้ดเพิ่มเองโดยตรงใช่ไหมครับ? ผมเองก็คิดจะทำแบบ DIY อยู่เสมอเหมือนกัน แต่ก็มักลังเลเพราะฟังก์ชันการขยายความสามารถและปลั๊กอินที่เฟรมเวิร์กบล็อกแบบ SSG ที่เคยใช้งานอยู่มีมาให้นี่แหละครับ

 
ifmkl 2025-05-07

ถ้าตัดความโลภออกไปได้ แค่ตัดความอยากได้อยากมีออกไป ที่เหลือก็ไม่ได้ยากอะไรมาก จริง ๆ แล้วถ้าขอให้ AI เขียนโค้ดให้ ssg ก็เขียนให้ได้หมด และถ้าขอให้เพิ่มฟีเจอร์ ก็เพิ่มให้ได้หมดเหมือนกัน 555

 
ndrgrd 2025-05-04

ถ้าเลือกแค่ฟอนต์ที่สวย ๆ มันก็ดูน่าอ่านขึ้นมาเลยครับ

 
GN⁺ 2025-05-04
ความคิดเห็นบน Hacker News
  • นึกถึงแผนภูมิในบทความบล็อกนี้: https://molodtsov.me/2023/02/how-to-start-your-blog-in-2023/
    พอตกลงไปในหล่มของ static site generator (SSG) ก็ใช้เวลาส่วนใหญ่ไปกับการเขียนถึงและง่วนกับ ตัว SSG เอง แทนที่จะเขียนสิ่งที่เดิมทีอยากเขียนหรือทำสิ่งที่ตั้งใจจะทำ
    สุดท้ายก็ทิ้ง SSG แล้วติดตั้ง WordPress จากนั้นก็เลิกกังวล ซึ่งรู้สึกเหมือนได้ปลดแอกมาก
    ถ้าเป้าหมายคือการง่วนปรับแต่งและเขียนถึงกระบวนการนั้นก็ไม่เป็นไร และสำหรับคนที่การง่วนปรับแต่งไม่ขัดขวางการเขียนก็ไม่เป็นไรเช่นกัน แต่สำหรับผมไม่ใช่แบบนั้น
    สิ่งสุดท้ายที่ต้องการในจังหวะที่กำลังจะเขียน คือข้ออ้างให้ผัดวันประกันพรุ่ง

    • WordPress ในปี 2025 มีคุณลักษณะเสี่ยงสองอย่างอยู่ด้วยกัน
      WordPress และปลั๊กอินทั้งหมดอาจถูกเจาะได้หากไม่อัปเดตให้เป็นเวอร์ชันล่าสุด และ BDFL ก็เป็นคนที่สามารถปิดกั้นการส่งมอบอัปเดตความปลอดภัยหรือการเข้าถึงเพื่อรับอัปเดตได้ด้วยเหตุผลส่วนตัวเล็กน้อย
      เว็บไซต์แบบสแตติกไม่มีช่องโหว่ด้านความปลอดภัยให้ต้องแพตช์ ดังนั้นแม้โปรเจกต์ SSG จะล่มสลายไปเพราะปัญหาของผู้ดูแลก็ไม่ได้เป็นเรื่องใหญ่นัก แต่ใน WordPress เรื่องนี้สำคัญมาก
    • ผมก็คล้ายกัน เริ่มจาก DokuWiki เมื่อนานมาแล้ว แล้วตัดสินใจลองใช้ GitHub Pages หลังจากย้ายทุกอย่างไปแล้วก็ต้องการการค้นหา เลยใส่ Google Custom Search เข้าไป
      ต้องมีวิธีให้ผู้เยี่ยมชมทิ้งคอมเมนต์ได้ จึงเพิ่ม Disqus เข้าไป และสุดท้ายก็กลายเป็นของปนเปที่มีหลายบริการกับ JavaScript จำนวนมากปะปนกัน
      หลายปีก่อน ผมอยากกลับมาถือครองข้อมูลของตัวเองโดยตรงและไม่พึ่งพาบริการภายนอก จึง export คอมเมนต์จาก Disqus แล้วลองปรับแต่ง Serendipity ก่อนจะลงตัวกับ WordPress
      มันนำเข้าคอมเมนต์และหน้า Markdown ได้ และยังมีปลั๊กอินที่เผยแพร่ทุกอย่างไปยัง Fediverse ให้ด้วย
      พอทำให้ทำงานบน SQLite และเปิด auto-update ไว้ ก็แทบไม่ต้องบำรุงรักษาเลย
    • นี่เป็นสแปมบล็อกหรือเปล่า? :) URL คือ https://rakhim.org/honestly-undefined/19/
    • เห็นด้วย แต่คิดว่า ใน 95% ของกรณี WordPress นั้นเกินจำเป็น
      ต้องบำรุงรักษามากเกินไปเพื่อฟีเจอร์ที่มีโอกาสสูงว่าจะไม่ได้ใช้ หากไม่อัปเดตให้เป็นเวอร์ชันล่าสุด ก็อาจกลายเป็นส่วนหนึ่งของบอตเน็ตได้
      สำหรับบล็อกส่วนใหญ่ static site generator ก็เพียงพอแล้ว และต่อให้ต้องบำรุงรักษา ผมก็ทำเมื่อถึงเวลาที่ผมต้องการได้
    • ค่อนข้างพอใจกับ nikola: https://getnikola.com/
      สิ่งที่ต้องการจริง ๆ คือคำสั่งเดียวสำหรับเผยแพร่ และวิธีลากรูปภาพลงในบทความได้ง่าย ๆ ซึ่งอย่างแรกทำได้ดี ส่วนอย่างหลังทำได้ผ่านฟีเจอร์เผยแพร่ของ Jupyter Notebook
      สิ่งที่ไม่ต้องการเลยคือวิธีที่ทำให้ “การส่ง HTML ไปยังไคลเอนต์” มีภาระอย่างฐานข้อมูลเข้ามาเกี่ยวข้อง
  • ดี แต่รู้สึกว่าถ้าจะเรียกว่าบล็อก ต้องมีฟีเจอร์เล็ก ๆ เพิ่มอีกสองอย่าง
    อย่างแรก ต้องเรียงบทความตามวันที่ ให้บทความล่าสุดมาก่อน และแสดงวันที่ไว้ที่ใดที่หนึ่ง หากต้องการคงโครงสร้างขั้นต่ำไว้ ก็ใช้เมทาดาทาของไฟล์บทความ เช่น เวลาในการสร้างไฟล์ก็ได้
    อย่างที่สอง แน่นอนว่าต้องมี RSS feed น่าจะสร้างฟีดง่าย ๆ ที่มีแค่ลิงก์กับชื่อเรื่องได้ไม่ยาก โดยใช้สคริปต์เดิมกับเทมเพลต RSS ขั้นต่ำ

    • RSS เป็นสิ่งที่ดี แต่ผมคิดว่าไม่ควรเป็นเงื่อนไขบังคับเพื่อให้ได้รับการยอมรับว่าเป็นบล็อก
      การถูก “ติดตาม” ไม่ได้ดีเสมอไป และอาจสร้างแรงกดดันให้ต้องเอาใจผู้อ่าน ซึ่งเป็นปัจจัยเดียวกับที่ทำให้โซเชียลมีเดียแย่
    • มีเหตุผล
      ข้อ 1 ผมเอนเอียงไปทางการสร้างไฟล์ที่มีเมทาดาทาในรูปแบบอย่าง TOML โดยอัตโนมัติ
      ข้อ 2 RSS จะเพิ่มแน่นอน แต่ขึ้นอยู่กับข้อ 1 :-)
  • ผมชอบเว็บไซต์อิสระมาโดยตลอด และเว็บไซต์ของผมเองก็เริ่มต้นคล้าย ๆ กันเมื่อราว 25 ปีก่อน
    ตอนนั้นเทคโนโลยีที่เหมาะสมซึ่งผมรู้จักมีแค่ Classic ASP เลยทำแบบเรียบง่ายที่สุดด้วย ASP ล้วน ๆ
    ตอนนี้กลายเป็นไซต์ที่สร้างแบบ static ด้วย Common Lisp และคิดว่าการตั้งค่านี้น่าจะอยู่ยาว: https://github.com/susam/susam.net/blob/main/site.lisp
    การเริ่มจากชุดหน้าเว็บเรียบง่ายเป็นวิธีที่ดีในการสร้างเว็บไซต์แบบ minimum viable แต่เมื่อเวลาผ่านไปก็เริ่มต้องการฟีเจอร์อย่าง RSS feed, รายการบล็อกเรียงตามวันที่, ดัชนีตามแท็ก, การรองรับคอนเทนต์ที่ไม่ใช่บล็อก เช่น เครื่องมือ·เกม·เดโม และคอมเมนต์แบบไม่พึ่งพา third-party
    ทุกครั้งที่ความต้องการเพิ่มขึ้น ซอร์สก็โตตาม จากโค้ดไม่กี่ร้อยบรรทัด ตอนนี้กลายเป็น Common Lisp ราว 1300 บรรทัดแล้ว
    ถึงอย่างนั้นก็ยังอยากรักษาให้อยู่ในระดับที่สามารถเก็บภาพรวมของโค้ดทั้งหมดไว้ในหัวได้ และถ้ามีบั๊กก็ไล่เหตุผลและแก้ได้ภายใน 10 นาที
    ช่วงนี้มีแรงยั่วยวนให้อยากเพิ่ม blogroll ที่แสดงรายการบทความจากบล็อกเกอร์ที่ชอบ อาจใช้แทน feed reader ได้ด้วย แต่จะระวังไม่ให้มันโตไปเป็นของที่อ่านอีเมลได้ด้วย

    • ผมเดินเส้นทางแทบเหมือนกัน
      ซอร์สโค้ดอยู่ที่นี่: https://github.com/brilee/modern-descartes-v2/blob/master/ma...
      มี RSS feed, รายการบล็อกเรียงตามวันที่, ระบบแท็ก และ local development server ที่ watch ไฟล์แล้ว recompile ให้
    • เส้นทางของผมก็คล้ายกัน และจริง ๆ ลองวนทำมาหลายรอบแล้ว
      เวอร์ชันปัจจุบันคงไว้เป็น สคริปต์ Python ไม่ถึง 1000 บรรทัด: https://github.com/llimllib/obsidian_notes/blob/c93b9b5c46fe...
    • ใช่เลย ความสามารถในการตัดสินใจว่า “อยากสร้างอุปกรณ์นี้” แล้วลงมือโค้ดเองได้ ดีกว่า WYSIWYG ไหน ๆ
      ผมทำหน้าที่แตกแขนงออกมาอย่างชุดบทความ, ดัชนี, slideshow และยังทำรูปแบบแท็กสำหรับคนกับวิดีโอเกมด้วย
      รูปลักษณ์และความรู้สึกของ widget ทั่วไปอย่างแกลเลอรี thumbnail หรือกล่องคำอ้างอิงก็สามารถควบคุมได้ทั้งหมด
    • ผมสร้างฟีเจอร์ Flock ใน Lamb ซึ่งเป็นฟีเจอร์สำหรับ syndicate feed เข้าบล็อกของผม ทำขึ้นมาเป็นทางเลือกแบบ multi-user เป็นหลัก: https://github.com/svandragt/lamb
      อาจใช้เป็นแหล่งอ้างอิงระดับสูงได้
    • RSS กับวันที่น่าจะจำเป็นแน่นอน
      ต่อไปอาจอยาก embed shader กับเว็บเกมด้วย หวังว่าความซับซ้อนจะไม่บานปลายเกินไป
  • อยากให้เบราว์เซอร์รองรับ text/markdown และ text/gemini แบบ native
    ถ้าเบราว์เซอร์ render PDF ได้ การใส่ formatter ง่าย ๆ สำหรับคอนเทนต์ Markdown/Gemini กับ stylesheet ที่ผู้ใช้กำหนดเองได้ก็น่าจะไม่ได้ยากขนาดนั้น
    ตอนนี้ยังเขียนบล็อกแบบ text/plain ได้ แต่ไม่ใช่ hypertext จริง ๆ และเสียเปรียบด้าน SEO บางทีอาจใช้ link header ทำเวทมนตร์บางอย่างได้ก็ได้
    การรองรับรูปแบบอื่นจะช่วยลดกำแพงในการเผยแพร่อย่างสะอาด และคืนการควบคุมให้ผู้ใช้

    • การ render Markdown แบบ native ในเบราว์เซอร์ น่าเสียดายที่ดูเป็นไปได้น้อย
      ก่อนอื่นเบราว์เซอร์ต่าง ๆ ต้องตกลงกันให้ได้ว่าจะใช้ Markdown variant และ extension แบบไหน เพราะ Markdown แทบจะเหมือน CSV ของโลกฟอร์แมตข้อความ คือทุกคนใช้กันคนละแบบ
      ถ้าทำให้ minimal เกินไปก็จะมีคนบ่นว่าไร้ประโยชน์ แต่ถ้าเลือก extension ก็จะมีคนบ่นว่าบวมเกินไป
      ต่อให้พยายามคุยอย่างรอบคอบถึงข้อดีข้อเสียทั้งระยะสั้นและระยะยาว ก็อาจถูกปิดด้วยคำพูดว่า “อย่าให้ความสมบูรณ์แบบเป็นศัตรูของสิ่งที่ดี”
      ต่อให้ตกลงชุดฟีเจอร์บางอย่างกันได้ ก็ยังน่าสงสัยว่ามันคุ้มค่าจริงหรือไม่
      การอ่าน PDF โดยตรงในเบราว์เซอร์เป็นเรื่องที่พบได้บ่อยพอสมควร แต่ประโยชน์ของการอ่าน Markdown โดยตรงน่าจะไปถึงแค่นักพัฒนาซอฟต์แวร์บางส่วนทั่วโลกกับคนแปลก ๆ อีกสักห้าคนเท่านั้น
      ดังนั้นถ้าชั่วชีวิตนี้ไม่ได้เห็น browser-native Markdown rendering ก็คงไม่แปลกใจ
    • การ render PDF ของเบราว์เซอร์ทำด้วย JavaScript หรืออย่างน้อยครั้งหนึ่งเคยเป็นแบบนั้น
      ยังมีไลบรารีสำหรับ XSLT ที่ใช้ได้เมื่อต้องการเวอร์ชันใหม่กว่าการรองรับ native ของเบราว์เซอร์ และก็มีไลบรารีสำหรับฟอร์แมตต่าง ๆ อย่าง jpegxl ด้วย
    • Gemini มีฟอร์แมตของตัวเองด้วยเหรอ?
  • ถ้าเป็น html_content = html_content.replace('Minimum viable blog', title) แปลว่าทุกครั้งที่มีสตริง Minimum viable blog ในบทความ มันจะถูกเปลี่ยนเป็นชื่อบทความปัจจุบันใช่ไหม? นี่เป็นบั๊กไม่ใช่เหรอ?

    • ใช่ จับได้ดีมาก
      โค้ดในบทความเป็น draft แรกที่ O1 สร้างขึ้นมา และสตริงนี้ถูกแทนที่ด้วย {{ title }} แล้ว
  • ผมทดลองกับ บล็อกแบบมินิมัล มาราว 15 ปี และมีเคล็ดลับที่ได้เรียนรู้อยู่บ้าง
    แค่ const title = lines.match(/# (.+)/)[1] ก็พอแล้ว จึงหลีกเลี่ยง frontmatter ได้
    บล็อกของผมไม่เคยมีบทความเยอะจนต้องใช้ pagination, แท็ก, category หรือการจัดเรียง
    JSX ถ้าใช้แฮ็กชวนสงสัยแบบ https://immaculata.dev/guides/enabling-jsx.html ก็ใช้เป็น string builder ฝั่ง server ล้วน ๆ ได้ค่อนข้างดี
    ตอนนี้ GitHub Pages ก็ใช้ขั้นตอน build ใด ๆ แทน Jekyll ได้ง่ายขึ้นด้วยของอย่าง https://immaculata.dev/guides/using-gh-pages.html
    highlight.js แทบจะเป็นราชาแห่ง code syntax highlighting ที่ง่ายมาก แค่เพิ่มสามบรรทัดใน HTML ก็พอ ส่วน shiki นั้นสวยแต่ช้า

  • ใช้เฟรมเวิร์กบล็อกแบบสแตติกมาตรฐานอย่าง Hugo/Zola + Cloudflare Pages ก็ง่าย
    บล็อกของผมก็เป็นชุดขั้นต่ำที่เล็กกว่า 100KB และตรงตามเกณฑ์ทั้งหมดที่ผู้เขียนต้นฉบับไล่ไว้
    ใช้ธีม Hugo Blog Awesome, ทำตามแนวทาง 512kb, ตรวจสอบขนาดหน้าแล้ว และตัดรูปภาพกับ JS ที่ไม่จำเป็นออก จริง ๆ แล้วก็ไม่ได้มีเยอะตั้งแต่แรก
    อ้างอิง: https://512kb.club, https://radar.cloudflare.com/scan

  • เคยทำ “MVB” อยู่พักหนึ่ง ของผมเรียบง่ายกว่านี้อีก
    แค่วางหน้า HTML หน้าเดียว เขียนบทความเป็นไฟล์ .txt แล้วอัปเดตหน้าแรกด้วยมือ
    แม้จะค่อนข้างเยิ่นเย้อ แต่ผมว่าก็ยังง่ายกว่าการรับมือกับ เว็บสมัยใหม่
    หลังจากนั้นย้ายไปทำแบบประณีตขึ้น ตอนนี้ใช้ Astro กับเว็บไซต์ส่วนตัวและบล็อก ซึ่งยอดเยี่ยมจริง ๆ
    Astro อ้างบนหน้าแลนดิ้งว่าเป็นแพลตฟอร์มที่ดีที่สุดสำหรับ “ไซต์ที่เน้นคอนเทนต์” และหลังจากใช้มา 6 เดือนก็เห็นด้วย
    มันให้แนวปฏิบัติที่ชัดเจนและทำตามง่ายสำหรับแทบทุกอย่างที่จำเป็นในการทำบล็อก และตัดส่วนที่ไม่จำเป็นออก

    • Astro สุดยอดจริง ๆ ไม่รู้ทำไมถึงไม่เป็นที่นิยมกว่านี้
    • สงสัยว่าใช้ธีมของคนอื่น หรือทำเอง
  • ลองทดลองใช้ Bun JS กับวิธีเขียน HTML ในสตริง JavaScript กับบางไซต์
    Bun มีแฟล็ก —hot ที่สร้าง HTML แบบสแตติกใหม่เมื่อมีการเปลี่ยนแปลง
    IntelliJ IDE ตรวจจับคอมเมนต์ // language=html เหนือสตริง แล้วจัดฟอร์แมต HTML ข้างในและทำ syntax highlighting ให้ด้วย
    ถ้าใช้ฟังก์ชัน JavaScript ล้วนแทนภาษาเทมเพลต ก็เขียนลอจิกที่ต้องการเองได้โดยไม่ต้องไปค้นหาว่าในภาษาเทมเพลตต้องทำอย่างไร

  • เบื่อเว็บไซต์ที่ใหญ่เทอะทะจนโหลดนาน เลยใช้แนวทางคล้ายกันมากกับบล็อกของผม: https://blog.borrego.dev
    ซอร์ส: https://github.com/agubelu/blog

    • ชอบมากและดูดีเลย บนมือถือหน้าตาเป็นอย่างไรบ้าง?