Portfolio Website
Website pribadi yang menyatukan profile, project case study, blog, contact form, dan AI chat. Sebagian besar halaman dibuat statis dengan Astro, sedangkan fitur yang membutuhkan server berjalan melalui endpoint terpisah.
- Role
- Saya menentukan arah project, design visual, struktur halaman, dan content. AI banyak membantu implementasi teknis; saya mengarahkan prosesnya lalu memeriksa hasil melalui source review, test, dan build.
- Timeline
- 22 Juni 2026–sekarang. Dimulai dari website portfolio sederhana, lalu berkembang dengan case study, blog, contact form, AI chat, dan migrasi dari Next.js ke Astro.
Stack
- Astro 7
- TypeScript
- Tailwind CSS
- GSAP ScrollTrigger
- Astro Content Collections
- MDX + Zod
- Upstash Redis
- Resend
- OpenAI-compatible API
Problem
Saya membuat website ini sebagai media untuk memperkenalkan diri, membagikan tulisan, dan menjelaskan project yang pernah saya kerjakan. Sebelumnya, setiap project hanya tampil sebagai card berisi judul, deskripsi singkat, tech stack, dan link.
Format card cukup untuk memberi gambaran awal, tetapi tidak menyediakan ruang untuk membahas alasan project dibuat, proses pengembangan, keputusan teknis, hasil, dan kekurangannya. Saya membutuhkan halaman khusus agar setiap project dapat dijelaskan tanpa memadatkan semuanya ke homepage.
Website ini juga perlu menyediakan tempat untuk tulisan dan cara menghubungi saya. Karena itu, scope-nya berkembang menjadi homepage, blog, project case study, contact form, dan AI chat yang menjawab pertanyaan tentang saya.
Approach
Saya menentukan design visual, struktur halaman, dan content yang ingin ditampilkan. AI banyak membantu implementasi teknis. Peran saya lebih banyak mengarahkan hasil yang diinginkan, meninjau code, dan memeriksa apakah setiap bagian bekerja sesuai design.
Homepage dibagi menjadi beberapa section: hero, profile, tech stack, project, blog, dan contact. Ilustrasi pegunungan menjadi latar hero, sedangkan warna Nord dipakai di seluruh website. Chapter scrolling, reveal animation, spotlight, dan project filter ditambahkan untuk memberi interaksi tanpa mengubah halaman menjadi aplikasi yang sepenuhnya berjalan di browser.
Content project dan blog disimpan sebagai MDX. Frontmatter menampung data yang perlu tampil konsisten pada card, metadata, dan header halaman. Body MDX digunakan untuk tulisan yang lebih panjang. Content Collections memeriksa field wajib, slug, URL, image, dan struktur heading sebelum build.
Setiap project case study menggunakan urutan Problem, Approach,
Architecture, Outcome, dan Lessons. Urutan ini juga diperiksa oleh content
guard agar setiap halaman memiliki struktur dasar yang sama. Isi di dalamnya
tetap disesuaikan dengan cerita masing-masing project.
Website ini awalnya dibuat dengan Next.js. Ketika fokusnya semakin banyak pada content statis, saya memindahkannya ke Astro untuk mengurangi JavaScript yang dikirim ke browser. AI membantu sebagian besar proses migrasi, sedangkan saya mengarahkan perubahan dan memeriksa hasilnya melalui test, build, serta ukuran bundle.
Architecture
src/content/
+-- blog/*.mdx ----------> Content Collections --> /blog/[slug]
|
+-- projects/*.mdx ------> Content Collections --> /projects/[slug]
|
+------------> homepage project cards
Astro
+-- Static pages: layouts, sections, metadata, MDX rendering
+-- Browser interactions: navigation, filters, contact, motion, chat shell
+-- Server endpoints:
+-- /api/chat -----> Upstash --> OpenAI-compatible API --> SSE
+-- /api/contact --> Upstash --> validation --> Resend
Astro menangani routing, layout, metadata, dan prerendering. Content Collections membaca blog dan project dari filesystem, memvalidasi frontmatter dengan Zod, lalu menghasilkan static path. MDX dirender saat build menggunakan GitHub-flavored Markdown dan syntax highlighting. Homepage hanya membaca metadata yang dibutuhkan project card.
Bagian visual menggunakan Tailwind CSS dengan palet Nord. GSAP ScrollTrigger dimuat di homepage untuk reveal dan parallax, sedangkan marquee berjalan dengan CSS. Navigation, project filter, spotlight, contact form, dan chat shell menggunakan vanilla TypeScript. Pengaturan reduced motion menghentikan animasi berulang dan mengurangi transition yang tidak diperlukan.
Contact form dan AI chat menggunakan endpoint Astro karena keduanya membutuhkan secret. Upstash menerapkan rate limit dengan identitas IP yang di-hash dan namespace per environment. Contact endpoint memvalidasi input sebelum mengirim email melalui Resend. Chat endpoint meneruskan stream dari OpenAI-compatible API ke browser melalui SSE.
Request ke endpoint memiliki batas ukuran dan timeout. Error yang dikirim ke browser tidak menyertakan detail internal. Code untuk streaming chat juga baru dimuat setelah pengguna mengirim pesan pertama.
Outcome
Website dapat diakses di aguswira.dev, sedangkan source code tersedia di GitHub.
Homepage sekarang memuat profile, tech stack, project, blog, contact form, dan AI chat. Setiap project memiliki case study sendiri, dan tulisan tersedia dalam route blog terpisah. Semua halaman content memiliki canonical URL, social metadata, structured data, dan satu H1.
| Route | Rendering | JavaScript eager (gzip) |
|---|---|---|
/ | Static | sekitar 47 kB |
/blog/[slug] | Static | sekitar 0,9 kB |
/projects/[slug] | Static | sekitar 0,9 kB |
/api/* | Vercel serverless | — |
Runtime React, Framer Motion, Lenis, dan canvas dari versi lama sudah dihapus. Halaman blog dan project hanya memuat script navbar global, sedangkan homepage memuat JavaScript untuk interaksi yang terlihat di halaman.
Vitest memeriksa content schema, validasi API, rate-limit key, timeout, abort, provider, dan SSE parser. Playwright mencakup keyboard flow, reduced motion, accessibility, contact form, dan streaming chat pada viewport desktop serta mobile tanpa memanggil provider live.
Lessons
Portfolio ini membutuhkan lebih dari design homepage. Saya juga perlu menyusun content untuk menjelaskan setiap project, melengkapi metadata tiap route, dan menangani keamanan fitur server pada website yang sebagian besar statis.
Saya juga belajar bahwa menggunakan AI untuk implementasi tetap membutuhkan arah dan pemeriksaan. Saya menentukan design serta struktur content, lalu meninjau hasil implementasi melalui source code, test, build, dan pengukuran bundle. Output AI tidak langsung dianggap selesai hanya karena tampilannya sudah sesuai.
Astro cocok untuk project ini karena sebagian besar route berisi content yang dapat dibuat saat build. JavaScript tetap digunakan pada bagian yang memang membutuhkan interaksi, sedangkan contact dan chat dipisahkan sebagai endpoint server.