Blank Screen Membunuh Kepercayaan. Saya Punya 31.
Saya menemukan 31 blank screen di SaaS saya — semuanya karena saya lupa multi-tenancy bukan hanya soal akses data, tapi soal konteks URL. Begini cara Claude Code membantu saya memperbaiki semuanya dalam satu malam.
1 November, 8:47 AM. Saya dapat emailnya.
"Hey Chandler - saya klik 'View' dan dapat halaman kosong. Apakah saya kehilangan semua data interview saya?"
Perut saya terasa jatuh. Halaman kosong bukan bug. Mereka pembunuh kepercayaan.
Saya buka dev console. Cek route-nya. Pengguna agensi, melihat klien "Acme Corp", klik tombol, dan... URL berubah dari `/clients/acme-corp/agents/agent-name/results/123` menjadi hanya `/agent-name/results/123`.
Kehilangan konteks klien. React Router tidak bisa menemukan route. Blank screen.
"Oke, itu satu bug," pikir saya. "Saya perbaiki dan lanjut."
Saya setup Claude Code untuk menganalisis codebase mencari pola serupa, lalu menjalani hari Sabtu dengan keluarga. Makan siang. Urusan. Anak-anak. Biasa.
Sore hari, saya cek kembali. Claude Code sudah menemukan polanya — dan tidak cantik.
Pukul 7:42 PM, saya sudah memperbaiki 14 bug. Pukul 7:48 PM, ditemukan 8 lagi. Pukul 7:56 PM, hitungannya mencapai 31 total.
Semua root cause yang sama. Semua perbaikan yang sama. Semua karena saya lupa satu hal ketika membangun multi-tenancy: navigasi bukan hanya soal data, tapi soal konteks.
---
Seberapa Parah Sebenarnya?
Biar saya jujur soal apa arti 31 bug ini:
Bagi pengguna:
- Pengguna agensi kena blank screen (terlihat rusak, bukan buggy)
- Kehilangan progres workflow di tengah sesi
- "Apakah platform ini cukup stabil untuk klien kami?"
- Setiap blank screen = satu langkah lebih dekat ke pembatalan trial
Bagi saya:
- 5+ laporan bug per hari (semuanya terkait navigasi)
- 2-3 jam debugging masing-masing secara individual
- Tidak bisa ship fitur baru (terlalu sibuk memadamkan api)
- Ketakutan genuine: "Bagaimana kalau saya merusak hal lain dan tidak tahu?"
Pertanyaan eksistensial: Kalau saya bahkan tidak bisa membuat navigasi berfungsi, kenapa orang harus mempercayai STRAŦUM dengan strategi marketing klien mereka?
Blank screen membunuh kepercayaan lebih cepat dari apa pun.
---
Bug yang Memulai Segalanya
Biar saya tunjukkan persis apa yang terjadi.
Flow pengguna (yang seharusnya bekerja):
1. Pergi ke `/clients/acme-corp/agents/analysis`
2. Klik "Start Session"
3. Selesaikan analisis
4. Klik "View Results"
5. Lihat hasil di `/clients/acme-corp/agents/analysis/results/123`
Yang sebenarnya terjadi:
1. ✅ `/clients/acme-corp/agents/analysis` (bagus)
2. ✅ Start session (berfungsi)
3. ✅ Selesaikan analisis (data tersimpan)
4. ❌ Klik "View Results" → HALAMAN KOSONG
5. ❌ URL berubah ke `/analysis/results/123` (kehilangan konteks klien)
React Router mencari route di `/analysis/results/123`. Tidak ada untuk pengguna agensi. Render kosong.
Pengguna melihat: Layar putih kosong. Tidak ada pesan error. Tidak ada loading spinner. Hanya... kosong.
---
Yang Saya (Sebenarnya Claude Code) Temukan Saat Mulai Menggali
Ini tampilan kode yang rusak:
```typescript
// AgentPage.tsx (DISANITASI - pola yang rusak)
import { useParams, useNavigate } from 'react-router-dom';
export function AgentPage() {
const { clientSlug } = useParams<{ clientSlug: string }>();
const navigate = useNavigate();
const handleViewResults = (sessionId: string) => {
// Masalah: Route hardcoded, tanpa konteks klien
navigate(`/agent-name/results/${sessionId}`);
};
return (
// ... komponen
);
}
```
Lihat masalahnya?
Saya mengekstrak `clientSlug` dari URL. Saya menggunakannya untuk fetch data. Tapi ketika saya navigasi, saya sepenuhnya melupakannya.
Route agensi terlihat seperti ini: `/clients/acme-corp/agents/agent-name`
Route SME terlihat seperti ini: `/agent-name`
Saya meng-hardcode pola SME. Pengguna agensi = rusak.
---
Realisasi: Saya Punya 31 dari Ini
2:15 PM. Saya perbaiki bug pertama. Commit. Merasa bagus.
3:42 PM. Ditemukan lagi di agent berbeda. Pola yang sama. Diperbaiki.
4:18 PM. Agent lain. Hal yang sama.
5:30 PM. Saya berhenti dan menatap layar selama 10 menit penuh.
Setiap halaman agent punya bug yang sama. Setiap komponen nested yang melakukan navigasi. Setiap elemen UI bersama dengan tombol "Go to...".
Saya bisa memperbaiki satu per satu dan menghabiskan 2 hari. Atau saya bisa menemukan polanya dan memperbaiki semuanya secara sistematis.
Saya memilih sistematis.
---
Perbaikannya: Navigasi Context-Aware
Alih-alih `useParams()` di setiap komponen, saya meminta Claude Code membuat Context provider:
```typescript
// contexts/ClientContext.tsx
import { createContext, useContext } from 'react';
import { useParams } from 'react-router-dom';
interface ClientContextValue {
clientSlug: string | null;
}
const ClientContext = createContext<ClientContextValue | null>(null);
export function ClientContextProvider({ children }: { children: React.ReactNode }) {
// Ekstrak clientSlug SEKALI di level layout
const { clientSlug } = useParams<{ clientSlug: string }>();
return (
<ClientContext.Provider value={{ clientSlug: clientSlug || null }}>
{children}
</ClientContext.Provider>
);
}
export function useClientContext() {
const context = useContext(ClientContext);
if (!context) {
throw new Error('useClientContext must be used within ClientContextProvider');
}
return context;
}
```
Lalu saya membungkus route agensi:
```typescript
// App.tsx
<Route path="/clients/:clientSlug/*" element={
<ClientContextProvider>
<ClientLayout />
</ClientContextProvider>
}>
<Route path="agents/analysis" element={<AnalysisAgent />} />
<Route path="agents/strategy" element={<StrategyAgent />} />
{/* ... semua route client-scoped */}
</Route>
```
Sekarang setiap komponen di dalamnya punya akses ke `clientSlug` via context, bukan params.
Routing helper (karena mengetik if/else yang sama 20 kali jadi membosankan):
```typescript
// hooks/useContextRoute.ts
import { useClientContext } from '@/contexts/ClientContext';
export function useContextRoute() {
const { clientSlug } = useClientContext();
const buildRoute = (route: string) => {
if (clientSlug) {
// Route agensi: /clients/acme-corp/agents/...
const cleanRoute = route.startsWith('/') ? route.slice(1) : route;
return `/clients/${clientSlug}/${cleanRoute}`;
}
// Route SME: /agent-name/...
return route;
};
return { buildRoute, clientSlug };
}
```
Penggunaan (jauh lebih bersih):
```typescript
// AgentPage.tsx (DISANITASI - pola yang diperbaiki)
import { useClientContext } from '@/contexts/ClientContext';
import { useNavigate } from 'react-router-dom';
import { useContextRoute } from '@/hooks/useContextRoute';
export function AgentPage() {
const { clientSlug } = useClientContext();
const { buildRoute } = useContextRoute();
const navigate = useNavigate();
const handleViewResults = (sessionId: string) => {
// Ini bekerja untuk KEDUA pengguna SME dan Agensi
navigate(buildRoute(`agents/analysis/results/${sessionId}`));
};
return (
// ... komponen
);
}
```
Satu helper function. Context-aware. Bekerja untuk kedua tipe pengguna.
---
Perbaikan Sistematis: Satu Hari, 31 File
Setelah saya punya polanya, jadi mekanis.
1 November 2025 - Sprint
Sore (2 PM - 7 PM) - Menemukan dan mengategorikan:
- Menemukan pola di semua halaman agent
- Bangun Context provider dan routing helper
- Test pendekatan di agent pertama
Malam (7:00 PM - 8:00 PM) - Perbaikan sistematis:
7:42 PM - Gelombang pertama (14 bug):
```
fix(multi-tenant): fix 14 navigation bugs and refactor all agents to useClientContext()
Frontend Changes (8 files):
- Refactored 6 agents to use useClientContext() hook
- Fixed 14 navigation bugs that lost client context across multiple agents
Backend Changes (5 files):
- Added client_id parameter to all save operations
- Updated base classes to extract client_id properly
Files changed: 14
Insertions: +732
Deletions: -164
```
7:48 PM - Gelombang kedua (8 bug lagi):
```
fix(multi-tenant): fix 8 navigation bugs in strategy page
- Fixed 8 navigation buttons that lost client context
- Total bugs fixed: 22 (14 + 8)
Files changed: 1
Insertions: +71
Deletions: -23
```
7:56 PM - Gelombang terakhir (9 bug lagi):
```
fix(multi-tenant): fix 9 navigation bugs in interview and tool pages
- Fixed remaining navigation issues in nested components
- Total bugs fixed: 31 bugs across entire application
Files changed: 2
Insertions: +46
Deletions: -10
```
Saya menelusuri setiap flow agent. Pengguna SME. Pengguna agensi. Klik setiap tombol. Tidak ada halaman kosong.
Total kerusakan: 17 file berubah, 849 penambahan, 197 penghapusan.
Waktu yang diinvestasikan: Sekitar 6 jam kerja non-kontinu dengan Claude Code (2 PM penemuan → 8 PM commit terakhir).
Waktu yang dihemat: Mungkin 30+ jam perbaikan bug individual dan dukungan pengguna.
---
Yang Saya Pelajari (Dengan Cara Sulit)
1. Navigasi multi-tenant lebih sulit dari isolasi data
Kamu bisa filter data dengan `org_id`. Itu bagian mudahnya.
Tapi navigasi? Kamu punya dua struktur URL yang valid untuk fitur yang sama:
```
SME: /agent-name/session/123
Agensi: /clients/acme-corp/agents/agent-name/session/123
```
Setiap panggilan `navigate()` perlu tahu pola mana yang digunakan. Salah sekali, dan pengguna melihat halaman kosong.
2. useParams() berbohong padamu
```typescript
const { clientSlug } = useParams();
```
Ini bekerja... sampai route berubah. Lalu `clientSlug` jadi `undefined`, dan navigasi berikutnya rusak.
React Context tidak berbohong. Selalu tersedia, selalu konsisten.
3. Hitung setiap bug sebelum mengklaim kemenangan
Saya pikir saya punya 14 bug. Lalu ditemukan 8 lagi. Lalu 9 lagi.
Pelajaran: Grep seluruh codebase-mu, bukan hanya file yang kamu pikir punya bug.
4. Ketika kamu menemukan bug yang sama dua kali, berhenti dan buat pola
Perbaikan individual: 31 bug = mungkin seminggu
Perbaikan sistematis: Temukan pola → Buat helper → Perbaiki semua instance = 6 jam
10 menit yang saya habiskan menatap layar jam 5:30 PM menghemat saya berhari-hari.
5. Bug navigasi adalah ancaman eksistensial
Kita terobsesi dengan state management, data fetching, optimisasi API.
Tapi navigasi rusak = blank screen = "Platform ini rusak."
Pengguna tidak peduli dengan RLS policy-mu atau arsitektur multi-tenantmu. Mereka peduli bahwa mengklik "View Results" menampilkan hasil. Gap yang sama antara "secara teknis berfungsi" dan "benar-benar selesai" muncul lagi ketika saya membangun aplikasi iOS native dengan AI — Claude Code generate scaffold cepat, tapi polish yang membuat pengguna mempercayai produk? Itu 40% yang hanya manusia yang bisa deliver.
---
Polanya (Untuk Aplikasi Multi-Tenant-mu)
Kalau kamu membangun SaaS multi-tenant dengan URL hierarkis:
✅ Langkah 1: Buat Context provider di level layout
✅ Langkah 2: Bangun routing helper
✅ Langkah 3: Jangan pernah hardcode route
✅ Langkah 4: Grep untuk SEMUA panggilan navigasi
✅ Langkah 5: Test dengan semua tipe pengguna
SME flow. Agensi flow. Setiap tombol. Setiap link. Tidak ada halaman kosong.
---
Hasilnya
Sebelum 1 November:
- 31 bug navigasi mengintai
- 5+ laporan bug per hari
- Pengguna agensi mempertanyakan stabilitas platform
- Saya: Takut untuk ship fitur baru
Sesudah 1 November:
- 0 bug navigasi
- 0 tiket support terkait navigasi
- Pola yang ditetapkan untuk development masa depan
- Saya: Percaya diri shipping route agent baru
6 jam yang saya habiskan memperbaiki bug ini terbayar 10× dalam berkurangnya beban support dan kepercayaan pengguna yang dipulihkan.
---
Kenapa Saya Berbagi Ini
Navigasi multi-tenant tidak seksi. Tidak ada yang merayakan "memperbaiki 31 bug dalam 6 jam" seperti merayakan "ship fitur baru."
Tapi kalau kamu membangun SaaS multi-tenant seperti saya dengan https://stratum.chandlernguyen.com/ — platform marketing AI untuk agensi — kamu akan kena ini. Mungkin bukan 31 bug. Mungkin hanya 5. Tapi kamu akan kena.
Ketika kamu kena, ingat:
1. Context > Params untuk state navigasi
2. Sistematis > Individual perbaikan
3. Grep seluruh codebase (kamu akan menemukan lebih dari yang kamu kira)
4. Test dengan semua tipe pengguna sebelum mengklaim kemenangan
Dan kalau kamu menemukan dirimu menatap blank screen bertanya-tanya ke mana konteksmu pergi, ketahuilah bahwa saya juga di situasi yang sama. :)
Apa bug paling menyakitkan yang pernah kamu ship ke pengguna nyata — jenis di mana kamu baru tahu karena seseorang memberitahumu? Saya sungguh ingin dengar.
Salam,
Chandler
Seri arsitektur STRAŦUM: Krisis navigasi ini bagian dari perjalanan multi-tenancy yang lebih besar. Dimulai dengan membangun multi-tenancy di Hari 2, meningkat ketika saya harus membangun ulang seluruh schema di Hari 67, dan berakhir ketika saya menemukan database saya benar tapi 296x terlalu lambat.
---
Masih coding, masih belajar, masih menemukan bug dalam kelompok 31.
Minta akses alpha di https://stratum.chandlernguyen.com/request-invitation
---
P.S. - Pengguna yang melaporkan bug pertama itu? Mereka tidak kehilangan data interview. Data tersimpan di database. Mereka hanya tidak bisa melihatnya karena route yang rusak. Ketika saya memperbaikinya jam 7:42 PM, semua pekerjaan mereka masih ada. Kelegaan kecil itu membuat 6 jam jadi worth it.
---





