โ† Semua pembelajaran / Astro Nol โ†’ Portal Berita
Fase 11 ยท Performa & Capstone

Capstone: portal berita berbayar, ujung ke ujung

Semua yang dibahas di sebelas fase sebelumnya bertemu di sini. Kalau kamu bisa menyelesaikan ini, kamu siap memigrasikan portal yang sesungguhnya.

Sumber asli docs.astro.build Resmi Rangkuman ~10 menit baca

Intisari

  • Bangun portal berita berbayar lengkap: baca, paywall, langganan, redaksi, deploy.
  • Tiap kriteria penerimaan bisa diverifikasi dengan perintah, bukan dengan melihat.
  • Kerjakan berurutan; tiap tahap bergantung pada yang sebelumnya.
  • Yang paling penting bukan fiturnya, melainkan angka: cache hit ratio, p95, dan nol kebocoran.
  • Setelah selesai, kamu punya rujukan yang bisa dipakai saat memigrasikan portal aslinya.

Yang dibangun

Portal berita dengan:

  Publik
    /                        beranda, artikel terbaru per kategori
    /berita                  daftar berpaginasi
    /berita/[kategori]       per kategori
    /berita/[slug]           artikel โ€” sebagian premium
    /perusahaan              tabel data, sortir & filter
    /perusahaan/[kode]       profil + grafik harga
    /pencarian               pencarian artikel

  Member
    /masuk /daftar /lupa-sandi
    /akun                    profil, langganan, riwayat tagihan
    /langganan               pilih paket โ†’ Midtrans Snap

  Redaksi
    /admin/artikel           daftar, buat, sunting, terbitkan
    /admin/media             unggah gambar

  Sistem
    /api/midtrans-webhook    verifikasi tanda tangan, idempoten
    /api/artikel.json        API publik
    /sitemap-berita.xml      Google News
    /sitemap-[hal].xml       arsip
    /robots.txt

Tahap

TahapIsinyaFase
1Skema MySQL + seed 2.000 artikel dengan panjang bervariasi2, 11
2src/lib/: db, artikel, kategori, perusahaan0, 2
3Halaman publik + layout + SEO1, 9
4Header cache + Cache-Tag1, 8
5Auth: daftar, masuk, sesi, lupa sandi5
6Paywall dengan server island + kuota terukur1, 5
7Midtrans: checkout, webhook, langganan6
8Island Vue: tabel perusahaan, grafik4
9Panel redaksi + purge cache saat terbit5, 8
10Keamanan: CSP, sanitasi, CSRF, header7
11Docker + ECS + CI/CD10
12Cloudflare: Cache Rules, WAF, kunci origin8
13Observability + uji beban10, 11

Kriteria penerimaan

Kebenaran

U=https://portal-capstone.contoh.id

# Artikel gratis tampil penuh
curl -s $U/berita/artikel-gratis | grep -c "PARAGRAF_TERAKHIR"          # = 1

# Artikel premium: isi TIDAK ADA tanpa sesi
curl -s $U/berita/artikel-premium | grep -c "PARAGRAF_TERAKHIR"         # = 0

# Dengan sesi member berlangganan: ADA
curl -s $U/_server-islands/KonteksPembaca?... \
  -H "Cookie: __Host-sesi=$SESI_AKTIF" | grep -c "PARAGRAF_TERAKHIR"    # = 1

# API JSON juga tidak membocorkan
curl -s $U/api/artikel/artikel-premium.json | grep -c "PARAGRAF_TERAKHIR"  # = 0

# URL lama dialihkan 301
curl -s -o /dev/null -w '%{http_code}\n' $U/news/detail/1               # = 301

Cache

# Halaman artikel ter-cache
curl -sI $U/berita/artikel-gratis | grep -i cf-cache-status             # HIT (kedua kali)

# Tidak ada Set-Cookie di halaman publik
curl -sI $U/berita/artikel-gratis | grep -ci set-cookie                 # = 0

# Parameter pelacakan tidak membuat entri baru
curl -sI "$U/berita/artikel-gratis?utm_source=fb" | grep -i cf-cache-status  # HIT

# Server island tidak pernah di-cache
curl -sI $U/_server-islands/KonteksPembaca | grep -i cache-control      # private, no-store

# Jalur akun BYPASS
curl -sI $U/akun | grep -i cf-cache-status                              # BYPASS

# Purge tag bekerja
# ubah judul di DB โ†’ masih judul lama โ†’ purge โ†’ judul baru

Pembayaran

# Tanda tangan salah ditolak
curl -s -o /dev/null -w '%{http_code}\n' -X POST $U/api/midtrans-webhook \
  -H 'Content-Type: application/json' -d '{"signature_key":"salah",...}'   # = 403

# Tanda tangan benar diterima, langganan aktif
# Kirim ulang notifikasi yang SAMA 3ร— โ†’ langganan_sampai maju SEKALI
# settlement lalu pending โ†’ status tetap aktif
# gross_amount sebagai angka, bukan string โ†’ 403

Keamanan

# CSRF: POST dari asal asing ditolak
curl -s -o /dev/null -w '%{http_code}\n' -X POST $U/api/bookmark \
  -H 'Origin: https://jahat.id' -d '{}'                                 # = 403

# Enumerasi akun: pesan & waktu sama untuk email ada dan tidak ada
# XSS: artikel berisi <script> tidak mengeksekusinya
# SQLi: payload di ?q= tidak memakan 5 detik
# Header keamanan ada di halaman on-demand, prerender, dan aset
# Origin tidak bisa dihubungi langsung
curl -m 5 -H "Host: portal-capstone.contoh.id" https://$IP_ORIGIN/ -k    # timeout/403

# Server key tidak ada di bundel klien
grep -rl "Mid-server-" dist/client/                                      # kosong

Performa

MetrikTargetCara ukur
Cache hit ratio> 90%Cloudflare Analytics, 24 jam
p95 render origin< 150 msServer-Timing / ALB
p95 server island< 50 msMetrik k6
JS halaman artikel< 45 KB gzipSkrip anggaran di CI
LCP< 2,5 dtkData lapangan web-vitals
CLS< 0,1Sama
Uji beban 2ร— puncakNol 5xxk6
Kueri per halaman artikelโ‰ค 4Penghitung kueri

Operasional

# Deploy tanpa 5xx: jalankan k6 sambil deploy
k6 run uji/beban.js & ./deploy.sh; wait                                 # 5xx = 0

# Rollback deploy
aws ecs update-service --task-definition <revisi-lama>                  # < 2 menit

# Rollback platform
# nonaktifkan Origin Rule                                                # < 60 detik

# Cadangan bisa dipulihkan
# restore-db-instance-to-point-in-time โ†’ verifikasi jumlah baris

# Migrasi jalan sekali meski service punya 12 task
# Tugas terjadwal jalan sekali meski dipicu bersamaan

Yang paling sering gagal

GagalKembali ke
Halaman artikel tidak ter-cacheAda Set-Cookie atau sesi dibaca di halaman โ€” Fase 1, 8
Isi premium bocor di HTMLIsi diambil sebelum hak dicek โ€” Fase 5
Webhook ditolak terusgross_amount dikonversi โ€” Fase 6
Server island error setelah deployASTRO_KEY tidak tetap โ€” Fase 1
502 acakkeepAliveTimeout < ALB โ€” Fase 10
Deploy menghasilkan 5xxGraceful shutdown atau stopTimeout โ€” Fase 10
Task mati tanpa logOOM โ€” max-old-space-size โ€” Fase 10
Health check gagal terusHOST bukan 0.0.0.0 โ€” Fase 10
Member ter-logout acakSesi di memori proses โ€” Fase 5
Iklan hilang setelah navigasiastro:page-load โ€” Fase 4

Kalau kamu tersandung salah satunya, itu bukan kegagalan โ€” itu tujuan latihannya. Sepuluh baris di tabel ini adalah kesalahan yang jauh lebih baik ditemukan di proyek capstone daripada di portal yang melayani 1,25 juta request per jam.

Setelah selesai

LangkahIsinya
Tulis dokumen keputusanEnam keputusan besarmu, dengan sinyal tinjau ulang
Tulis runbookUntuk sepuluh gejala di tabel di atas
Ukur baselineCache hit, p95, biaya โ€” untuk dibandingkan nanti
Petakan ke portal aslinyaBagian mana yang berbeda, dan kenapa
Mulai Fase 9 di portal asliStrangler, dimulai dari halaman statis

Perbedaan terbesar antara capstone dan portal aslimu bukan teknis โ€” melainkan data. Portal aslimu punya 200 ribu artikel dengan HTML dari tiga generasi editor, charset yang tidak konsisten, puluhan ribu URL terindeks, dan member yang sudah membayar. Fase 9 seluruhnya tentang itu, dan itu bagian yang tidak bisa dilatih di proyek bersih. Kerjakan capstone untuk menguasai mekanismenya; kerjakan inventarisasi Fase 9 untuk mengetahui apa yang sebenarnya kamu hadapi.

Latihan terakhir: selesaikan capstone-nya, lalu jalankan seluruh perintah verifikasi di halaman ini secara berurutan dan catat hasilnya. Setiap satu yang tidak sesuai target menunjuk ke fase tertentu untuk dibaca ulang. Kalau semuanya hijau, kamu punya rujukan yang bekerja โ€” dan portal aslimu tinggal mengikuti jalur yang sama, satu Origin Rule pada satu waktu.

Rangkuman ini sengaja dipangkas ke bagian yang dipakai di roadmap. Buka sumber aslinya saat kamu butuh detail lengkap atau referensi parameter.