We just wrapped up a performance pass on the site, and the results speak for themselves.
What changed
- Static-first architecture — mcky.space is built with Astro (server output) and Alpine.js for the small bits of interactivity. No React, no Next.js. Static pages ship zero client JS; only the theme toggle and sidebar use Alpine.
- Self-hosted fonts — JetBrains Mono is served as a self-hosted WOFF2 variable font with
font-display: swap. No Google Fonts request, no layout shift. - Immutable caching — fonts and
_astroassets getCache-Control: public, max-age=31536000, immutablevia vercel.json. - Security + cache headers — X-Content-Type-Options, X-Frame-Options, Referrer-Policy, and a Content-Security-Policy are set on every route.
- Sanitized rendering — blog markdown is rendered with
marked+ Prism and sanitized with DOMPurify before it hits the DOM. - Prebuilt blog index — posts are compiled from markdown to TypeScript at build time, so there is no runtime filesystem or database access.
Why
The site started life as a heavier SPA-style app. Stripping it back to Astro + Alpine removed an entire client framework from the critical path. Pages that are just content (home, about, projects) are pure HTML now.
Key wins
- TypeScript compiles clean — zero errors, zero warnings
- No runtime database on the main site — it is fully static
- Long-lived cache headers on hashed assets
- Content-Security-Policy in place to contain any future third-party script
The site feels lighter. Not that it was heavy before, but now it moves the way a terminal-inspired site should — fast, clean, no flashing.
เพิ่งจบ performance pass บนเว็บไซต์ ตัวเลขบอกทุกอย่าง
อะไรเปลี่ยนไปบ้าง
- Static-first architecture — mcky.space สร้างด้วย Astro (server output) และ Alpine.js สำหรับส่วนที่ต้องมี interactivity เล็กๆ น้อยๆ ไม่มี React, ไม่มี Next.js หน้า static ship zero client JS; มีแค่ theme toggle กับ sidebar ที่ใช้ Alpine
- Self-hosted fonts — JetBrains Mono เสิร์ฟเป็น WOFF2 variable font ที่ self-host พร้อม
font-display: swapไม่มีการ request ไป Google Fonts, ไม่มี layout shift - Immutable caching — ฟอนต์และ
_astroassets ได้Cache-Control: public, max-age=31536000, immutableผ่าน vercel.json - Security + cache headers — X-Content-Type-Options, X-Frame-Options, Referrer-Policy และ Content-Security-Policy ถูก set ทุก route
- Sanitized rendering — blog markdown render ด้วย
marked+ Prism และ sanitize ด้วย DOMPurify ก่อนถึง DOM - Prebuilt blog index — posts ถูก compile จาก markdown ไป TypeScript ตอน build time ไม่มีการ access filesystem หรือ database ตอน runtime
ทำไม
เว็บไซต์เริ่มชีวิตเป็น SPA-style app ที่หนักกว่า การถอยกลับมาเป็น Astro + Alpine ถอด client framework ออกจาก critical path ทั้งก้อน หน้าที่เป็นเนื้อหาล้วนๆ (home, about, projects) กลายเป็น pure HTML
Key wins
- TypeScript compile ผ่านสะอาด — zero errors, zero warnings
- ไม่มี runtime database บน main site — static ล้วน
- cache headers อายุยืนบน hashed assets
- Content-Security-Policy คุมไม่ให้ third-party script ไหนแทรกได้
site รู้สึกเบาขึ้น ไม่ได้หนักมาก่อน แต่ตอนนี้มันเคลื่อนแบบ site ที่ได้แรงบันดาลใจจาก terminal ควรเป็น — เร็ว, สะอาด, ไม่กระพริบ