Blank Screens Kill Trust。我有31個。
我喺我嘅SaaS入面搵到31個blank screens——全部因為我忘記咗multi-tenancy唔止係data access,佢仲係URL context。以下係Claude Code點幫我一晚fix晒嘅故事。
11月1日,朝早8:47。我收到封email。
「Hey Chandler——我㩒咗『View』然後得到blank page。我係咪整冇咗我所有interview data?」
我個胃沉咗落去。Blank pages唔係bugs。佢哋係trust killers。
我打開dev console。Check咗個route。Agency user,睇緊client「Acme Corp」,㩒咗個button,然後...URL由/clients/acme-corp/agents/agent-name/results/123變咗做/agent-name/results/123。
Lost咗client context。React Router搵唔到個route。Blank screen。
「Okay,嗰個係一個bug,」我諗。「我fix咗佢然後move on。」
我setup Claude Code分析codebase搵similar patterns,然後同家人過咗個Saturday。Lunch。做嘢。小朋友。正常嘅嘢。
到下晝遲啲,我check返。Claude Code搵到個pattern——而且唔係好睇。
到7:42 PM,我fix咗14個bugs。到7:48 PM,搵多8個。到7:56 PM,total去到31個。
全部同一個root cause。全部同一個fix。全部因為我build multi-tenancy嘅時候忘記咗一件事:navigation唔止係data,佢係context。
---
到底有幾差?
等我老實講呢31個bugs actually意味住咩:
For users:
- Agency users撞到blank screens(睇起嚟broken,唔止係buggy)
- Mid-session lost workflow progress
- 「呢個platform夠唔夠stable for我哋嘅clients?」
- 每個blank screen = closer to取消trial
For我:
- 每日5+個bug reports(全部navigation-related)
- 每個individually debug 2-3個鐘
- Ship唔到新features(太忙firefighting)
- 真正嘅恐懼:「如果我break咗其他嘢而我唔知呢?」
Existential question: 如果我連navigation都搞唔掂,點解有人應該trust STRAŦUM handle佢哋clients嘅marketing strategy?
Blank screens kill trust比任何嘢都快。
---
一切嘅開端
等我show你exactly發生咗咩。
User flow(應該work嘅):
1. 去/clients/acme-corp/agents/analysis
2. 㩒「Start Session」
3. Complete analysis
4. 㩒「View Results」
5. 喺/clients/acme-corp/agents/analysis/results/123見到results
Actually發生咗咩:
1. ✅ /clients/acme-corp/agents/analysis(good)
2. ✅ Start session(working)
3. ✅ Complete analysis(data saved)
4. ❌ **㩒「View Results」→ BLANK PAGE**
5. ❌ URL變咗做/analysis/results/123(lost client context)
React Router搵/analysis/results/123嘅route。For agency users唔存在。Render nothing。
User見到:Blank white screen。冇error message。冇loading spinner。只係...nothing。
---
我(其實Claude Code)開始Dig嘅時候搵到咩
以下係broken code嘅樣:
```typescript
// AgentPage.tsx (SANITIZED - the broken pattern)
import { useParams, useNavigate } from 'react-router-dom';
export function AgentPage() {
const { clientSlug } = useParams<{ clientSlug: string }>();
const navigate = useNavigate();
const handleViewResults = (sessionId: string) => {
// Problem: Hardcoded route, no client context
navigate(`/agent-name/results/${sessionId}`);
};
return (
// ... component
);
}
```
見到個問題嗎?
我由URL extract咗clientSlug。我用佢嚟fetch data。但當我navigate嘅時候,我完全忘記咗佢。
Agency routes長咁:/clients/acme-corp/agents/agent-name
SME routes長咁:/agent-name
我hardcode咗SME pattern。Agency users = broken。
---
發現:我有31個呢啲
2:15 PM。我fix咗第一個bug。Committed。感覺唔錯。
3:42 PM。喺另一個agent搵到另一個。同一個pattern。Fix咗。
4:18 PM。另一個agent。一樣嘅嘢。
5:30 PM。我停低咗盯住個screen成10分鐘。
每個agent page都有同一個bug。 每個navigate嘅nested component。每個有「Go to...」button嘅shared UI element。
我可以逐個fix然後花2日。或者我可以搵到pattern然後systematically fix晒。
我揀咗systematic。
---
Fix:Context-Aware Navigation
唔係喺每個component用useParams(),我叫Claude Code create一個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 }) {
// Extract clientSlug ONCE at the layout level
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;
}
```
然後我wrap咗agency routes:
```typescript
// App.tsx
<Route path="/clients/:clientSlug/*" element={
<ClientContextProvider>
<ClientLayout />
</ClientContextProvider>
}>
<Route path="agents/analysis" element={<AnalysisAgent />} />
<Route path="agents/strategy" element={<StrategyAgent />} />
{/* ... all client-scoped routes */}
</Route>
```
而家入面每個component都可以透過context access clientSlug,唔係params。
Routing helper(因為打同一個if/else 20次會悶):
```typescript
// hooks/useContextRoute.ts
import { useClientContext } from '@/contexts/ClientContext';
export function useContextRoute() {
const { clientSlug } = useClientContext();
const buildRoute = (route: string) => {
if (clientSlug) {
// Agency route: /clients/acme-corp/agents/...
const cleanRoute = route.startsWith('/') ? route.slice(1) : route;
return `/clients/${clientSlug}/${cleanRoute}`;
}
// SME route: /agent-name/...
return route;
};
return { buildRoute, clientSlug };
}
```
用法(clean好多):
```typescript
// AgentPage.tsx (SANITIZED - the fixed pattern)
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) => {
// This works for BOTH SME and Agency users
navigate(buildRoute(`agents/analysis/results/${sessionId}`));
};
return (
// ... component
);
}
```
一個helper function。Context-aware。For兩種user types都work。
---
Systematic Fix:一日,31個Files
有咗pattern之後,佢變成mechanical嘅。
2025年11月1日——Sprint
下晝(2 PM - 7 PM)——Finding同categorizing:
- 發現個pattern across所有agent pages
- Build咗Context provider同routing helper
- 喺第一個agent test咗approach
晚上(7:00 PM - 8:00 PM)——Systematic fix:
7:42 PM——第一波(14個bugs):
```
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——第二波(多8個bugs):
```
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——最後一波(多9個bugs):
```
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
```
我跑遍每個agent flow。SME user。Agency user。㩒每個button。冇blank pages。
Total damage: 17個files changed,849 insertions,197 deletions。
投入時間: 大約6個鐘non continuous work有Claude Code(2 PM discovery → 8 PM final commit)。
節省時間: 可能30+個鐘嘅individual bug fixes同user support。
---
我(Hard Way)學到嘅嘢
1. Multi-tenant navigation比data isolation更難
你可以用org_id filter data。嗰個係easy part。
但navigation?你有同一個feature嘅兩個valid URL structures:
```
SME: /agent-name/session/123
Agency: /clients/acme-corp/agents/agent-name/session/123
```
每個navigate()call都需要知用邊個pattern。搞錯一次,users就見到blank pages。
2. useParams()會騙你
```typescript
const { clientSlug } = useParams();
```
呢個work...直到route change。然後clientSlug變成undefined,你嘅下一個navigation就break。
React Context唔會騙你。佢always available,always consistent。
3. Claim victory之前count每個bug
我以為有14個bugs。然後搵多8個。然後多9個。
Lesson: Grep你成個codebase,唔只係你以為有bugs嘅files。
4. 當你搵到同一個bug兩次,停落嚟create一個pattern
Individual fixing: 31個bugs = 可能一個禮拜
Systematic fixing: 搵pattern → Create helper → Fix所有instances = 6個鐘
我5:30 PM花嘅10分鐘盯住screen省咗我幾日。
5. Navigation bugs係existential threats
我哋obsess over state management、data fetching、API optimization。
但broken navigation = blank screens = 「呢個platform係broken嘅。」
Users唔care你嘅RLS policies或者你嘅multi-tenant architecture。佢哋care㩒「View Results」會show results。呢個「technically works」同「actually finished」之間嘅gap喺我用AI build一個native iOS app嘅時候再次出現——Claude Code generate scaffold好快,但令users trust一個product嘅polish?嗰個係只有人類先deliver到嘅40%。
---
Pattern(For你嘅Multi-Tenant App)
如果你喺度build有hierarchical URLs嘅multi-tenant SaaS:
✅ Step 1: 喺layout level create一個Context provider
```typescript
<ClientContextProvider>
{/* All tenant-scoped routes */}
</ClientContextProvider>
```
✅ Step 2: Build一個routing helper
```typescript
const { buildRoute } = useContextRoute();
navigate(buildRoute('agents/analysis/session/123'));
```
✅ Step 3: 永遠唔好hardcode routes
```typescript
// ❌ BAD
navigate('/analysis/session/123');
// ✅ GOOD
navigate(buildRoute('agents/analysis/session/123'));
```
✅ Step 4: Grep所有navigation calls
```bash
# Find every navigate() call
grep -r "navigate(" src/ > navigation_audit.txt
# Find hardcoded routes
grep -r "navigate('/" src/ | grep -v "buildRoute"
```
✅ Step 5: 用所有user types test
SME flow。Agency flow。每個button。每個link。冇blank pages。
---
結果
11月1日之前:
- 31個navigation bugs潛伏緊
- 每日5+個bug reports
- Agency users質疑platform stability
- 我:驚到唔敢ship新features
11月1日之後:
- 0個navigation bugs
- 0個navigation-related support tickets
- 為未來development建立咗pattern
- 我:有信心ship新agent routes
Development velocity:
- 加新routes:5分鐘(以前係30分鐘 +「會唔會break?」)
- Bug reports:0(以前每日5+)
- User trust:Restored(「Platform而家feel stable喇」)
我花喺fix呢啲bugs嘅6個鐘回報咗10×——減少support burden同restored user confidence。
---
點解我分享呢個
Multi-tenant navigation唔sexy。冇人會好似慶祝「shipped new feature」咁慶祝「6個鐘fix咗31個bugs」。
但如果你同我一樣喺度build multi-tenant SaaS,好似https://stratum.chandlernguyen.com/——一個for agencies嘅AI marketing platform——你會撞到呢個。可能唔係31個bugs。可能只係5個。但你會撞到。
當你撞到嘅時候,記住:
1. Context > Params for navigation state
2. Systematic > Individual fixes
3. Grep你成個codebase(你會搵到比你想嘅更多)
4. Claim victory之前用所有user types test
如果你發現自己盯住blank screen wondering你嘅context去咗邊,know that我亦喺同一個situation。:)
你ship過俾real users最painful嘅bug係咩——嗰種你只係因為有人話你知先發現嘅?我真心想聽。
祝好,
Chandler
STRAŦUM architecture series: 呢個navigation crisis係更大嘅multi-tenancy journey嘅一部分。佢由第2日build multi-tenancy開始,escalate到我要第67日rebuild成個schema,然後conclude於我發現database係correct但296x太慢。
---
仲喺coding,仲喺learning,仲喺以31個為一組咁搵bugs。
喺https://stratum.chandlernguyen.com/request-invitation申請alpha access
---
P.S. ——報告第一個bug嘅user?佢冇整冇佢嘅interview data。Data save咗喺database。佢只係因為broken route而睇唔到。當我7:42 PM fix咗嘅時候,佢所有嘅work都仲喺度。嗰個小小嘅relief令6個鐘worth it。
---





