ข้ามไปยังเนื้อหา
เมนู
กลับไปหน้ารวมโปรเจกต์

โปรเจกต์

ohfork.dev

เว็บที่คุณกำลังดูอยู่นี่แหละ

SOMEHOW WORKSเปิดตัวแล้ว

เริ่ม · อัปเดต

  • ก็หน้านี้แหละเว็บไซต์นี้
หน้าแรกของ ohfork.dev ธีมมืด หัวข้อ “Oh fork. I built something again.” ข้อความ “A collection of questionable ideas, happy accidents, and things that somehow work.” ปุ่ม “Explore the chaos” กับ “View source” และโลโก้ส้อม

มันคืออะไร

สนามเด็กเล่นและพอร์ตโฟลิโอส่วนตัว รวมโปรเจกต์ การทดลอง และมุกต่างๆ ทั้งภาษาอังกฤษและไทย ดีไซน์เนี้ยบแบบนิตยสาร ส่วนมุกตลกแบบ dev ขอแทรกไว้ตามขอบ

ทำไมถึงสร้าง

ไม่อยากได้พอร์ตโฟลิโอทางการที่เรียงแค่รูปโปรเจกต์กับ tech stack อยากได้เว็บที่คนเข้ามาแล้วจำได้ทั้งผลงานและตัวคนทำ

ลองใช้ได้ไหม

ใช้อยู่นี่ไง

ฉบับเต็ม

โจทย์ลิงก์ไปยังหัวข้อนี้

ดูดีระดับ design studio แต่พูดจาแบบ dev ที่มีอารมณ์ขัน เอกสาร concept ให้ตัวเลขไว้เลยว่า ดีไซน์เนี้ยบแบบมืออาชีพ 80% มุก dev ที่ไม่ทันตั้งตัวอีก 20% มุกเป็นของแถม ไม่ต้องเก็ตมุกก็ใช้เว็บได้

ทำไมถึงสร้างลิงก์ไปยังหัวข้อนี้

ไม่อยากได้พอร์ตโฟลิโอทางการที่เรียงแค่รูปโปรเจกต์กับ tech stack อยากได้เว็บที่คนเข้ามาแล้วจำได้ทั้งผลงานและตัวคนทำ

การตัดสินใจที่ทำให้เว็บเป็นแบบนี้ลิงก์ไปยังหัวข้อนี้

  • self-host และไม่เปิด port ขาเข้า เว็บรันเป็น Docker container บนเซิร์ฟเวอร์ที่บ้าน ออกสู่อินเทอร์เน็ตผ่าน Cloudflare Tunnel ซึ่งเป็นการเชื่อมต่อขาออกอย่างเดียว เซิร์ฟเวอร์เลยไม่ต้องเปิด port ไหนเลย merge เข้า main เมื่อไหร่ก็ deploy เอง
  • static เป็นค่าเริ่มต้น Next.js (App Router) prerender ทุกหน้า รวมถึงหน้าโปรเจกต์แต่ละตัวทั้งสองภาษา JavaScript ฝั่ง client มีแค่ตรงที่ต้องโต้ตอบจริงๆ
  • อังกฤษและไทยแบบตั้งใจ ภาษาอังกฤษอยู่ที่ / ภาษาไทยอยู่ที่ /th ภาษาไทยเขียนแบบที่ dev ไทยพูดกันจริง ไม่แปลคำต่อคำ และไม่บังคับ redirect คนที่ใช้เบราว์เซอร์ภาษาไทย ส่วนมุกของแบรนด์อย่าง Oh fork. หรือ WORKS ON MY MACHINE คงเป็นภาษาอังกฤษไว้ เพราะแปลมุกเมื่อไหร่ มุกก็ตาย
  • build คอยบังคับให้ซื่อสัตย์ ทุกโปรเจกต์มีสถานะจริง (shipped, in progress, experiment, archived) กับ label ขำๆ ที่ใส่หรือไม่ใส่ก็ได้ แต่มุกห้ามขัดกับความจริง ถ้าขัด การตรวจ content จะทำให้ build พังทันที
export const FLAVOR_STATUSES = {
  "somehow-works": ["shipped", "wip", "experiment"],
  "works-on-my-machine": ["shipped", "wip"],
  "wip-forever": ["wip"],
} as const satisfies Record<StatusFlavor, readonly ProjectStatus[]>;
  • ของ private ก็ต้อง private ถ้าลิงก์ไปยัง repo ที่อยู่ในรายชื่อ private build ก็พังเหมือนกัน อะไรที่ยังขาดจะถูกมาร์กว่า TODO(owner) และขึ้นบนหน้าเว็บเป็นกรอบเส้นประพร้อมป้าย PLACEHOLDER จะได้หลุดขึ้น production แบบเงียบๆ ไม่ได้
  • มุกปิดได้ ที่อยู่ใน roadmap คือ Recruiter Mode ที่กดสวิตช์เดียวแล้วมุกหายหมด และ Easter egg ที่ต้องตั้งใจเล่นถึงจะเจอ โหลดเมื่อจำเป็น เคารพการตั้งค่าลดการเคลื่อนไหว และไม่ขวางทางใครที่แค่อยากดูโปรเจกต์

เรื่องที่ยาก (หรือฮา) กว่าที่คิดลิงก์ไปยังหัวข้อนี้

  • concept, roadmap และคำสั่งสำหรับ coding agent เสร็จก่อนจะมีเว็บด้วยซ้ำ commit แรกไม่มีโค้ดสักบรรทัด
  • พอใช้ Cache Components ของ Next หน้า "not found" ที่เรนเดอร์ตอนมีคนขอกลายเป็นหน้า error ว่างเปล่า ตอนนี้เลยส่งที่อยู่โปรเจกต์ที่ไม่มีอยู่จริงไปหน้า 404 ก่อนเริ่มเรนเดอร์ /projects/typo จึงได้หน้า 404 ฉบับเต็มที่ยังช่วยหาทางกลับได้
  • ภาษาไทยมีสระกับวรรณยุกต์ซ้อนอยู่ทั้งบนและล่างบรรทัด หน้าภาษาไทยเลยต้องเพิ่มระยะบรรทัดทุกจุดไม่ให้ตัวอักษรโดนตัด
  • footer จะขึ้นว่า on a Friday. Pray for me. ก็ต่อเมื่อ build เกิดขึ้นวันศุกร์จริงๆ ตามเวลากรุงเทพฯ
  • หน้านี้อยู่ในโชว์เคสของตัวเอง และปุ่มเดโมก็บอกแค่ว่า "ก็หน้านี้แหละ" แทนที่จะลิงก์วนกลับมาที่เดิม