Skip to content
··3 phút đọc

Màn hình trắng giết niềm tin. Tôi có 31 cái.

Tôi tìm thấy 31 màn hình trắng trong SaaS — tất cả vì quên multi-tenancy không chỉ về truy cập dữ liệu, mà về context URL. Đây là cách Claude Code giúp tôi sửa tất cả trong một đêm.

Ngày 1 tháng 11, 8:47 AM. Tôi nhận email.

"Hey Chandler - Tôi click 'View' và nhận trang trắng. Tôi mất hết dữ liệu phỏng vấn rồi à?"

Bụng tôi chìm xuống. Trang trắng không phải bug. Chúng giết niềm tin.

Tôi mở dev console. Kiểm tra route. User agency, xem client "Acme Corp", click nút, và... URL đổi từ /clients/acme-corp/agents/agent-name/results/123 thành chỉ /agent-name/results/123.

Mất client context. React Router không tìm thấy route. Màn hình trắng.

"Được rồi, một bug," tôi nghĩ. "Sửa rồi tiếp."

Tôi nhờ Claude Code phân tích codebase tìm pattern tương tự, rồi đi sinh hoạt gia đình thứ Bảy. Chiều check lại. Claude Code tìm thấy pattern — và không đẹp.

Đến 7:42 PM, tôi sửa 14 bug. 7:48 PM, tìm thêm 8. 7:56 PM, tổng 31 cái.

Cùng gốc rễ. Cùng cách sửa. Tất cả vì tôi quên một điều khi xây multi-tenancy: navigation không chỉ về dữ liệu, mà về context.

Fix: Navigation Context-Aware

Thay vì useParams() trong mọi component, tôi tạo Context provider:

// contexts/ClientContext.tsx
export function ClientContextProvider({ children }) {
  const { clientSlug } = useParams();
  return (
    <ClientContext.Provider value={{ clientSlug: clientSlug || null }}>
      {children}
    </ClientContext.Provider>
  );
}

Và routing helper:

// hooks/useContextRoute.ts
export function useContextRoute() {
  const { clientSlug } = useClientContext();

  const buildRoute = (route) => {
    if (clientSlug) {
      return `/clients/${clientSlug}/${route}`;
    }
    return route;
  };

  return { buildRoute, clientSlug };
}

Một helper function. Context-aware. Hoạt động cho cả hai loại user.

Sprint ngày 1/11

7:42 PM - Đợt 1 (14 bug): 14 file thay đổi, +732 dòng thêm 7:48 PM - Đợt 2 (8 bug nữa): 1 file, +71 dòng 7:56 PM - Đợt cuối (9 bug nữa): 2 file, +46 dòng

Tổng: 17 file, 849 thêm, 197 xóa. ~6 giờ làm việc không liên tục với Claude Code.

Bài học (theo cách khó)

  1. Navigation multi-tenant khó hơn data isolation — hai cấu trúc URL hợp lệ cho cùng tính năng
  2. useParams() nói dối bạn — React Context không nói dối. Luôn khả dụng, luôn nhất quán
  3. Đếm mọi bug trước khi tuyên bố chiến thắng — tôi tưởng 14 bug, hóa ra 31
  4. Tìm cùng bug hai lần? Dừng lại và tạo pattern — sửa từng cái: tuần. Sửa hệ thống: 6 giờ
  5. Bug navigation là mối đe dọa tồn vong — user không quan tâm RLS policies. Họ quan tâm click "View Results" thấy kết quả. Khoảng cách giữa "hoạt động kỹ thuật" và "thực sự hoàn thiện" hiện lên lại khi tôi xây ứng dụng iOS native với AI.

Kết quả

Trước: 31 bug navigation, 5+ báo cáo/ngày, user agency nghi ngờ ổn định Sau: 0 bug navigation, 0 ticket support, tốc độ phát triển tăng mạnh

6 giờ sửa bug trả lại 10 lần giảm gánh nặng support và khôi phục niềm tin user.

Bug gây đau nhất bạn từng ship cho user thực — loại chỉ biết khi ai đó nói? Tôi thành thật muốn nghe.

Thân mến, Chandler

Series kiến trúc STRAŦUM: Cuộc khủng hoảng navigation này là phần hành trình multi-tenancy lớn hơn. Bắt đầu với xây multi-tenancy ngày 2, leo thang khi phải xây lại toàn bộ schema ngày 67, và kết thúc khi phát hiện database đúng nhưng chậm gấp 296 lần.

P.S. - User báo bug đầu tiên? Họ không mất dữ liệu phỏng vấn. Nó vẫn lưu trong database. Họ chỉ không thấy vì route hỏng. Khi tôi sửa lúc 7:42 PM, tất cả công việc vẫn còn đó. Sự nhẹ nhõm nhỏ đó làm 6 giờ đáng giá.

Đọc tiếp

Hành trình
Kết nối
Ngôn ngữ
Tùy chọn