Một Codebase, Hai Thế Giới: Bài Học Tái Sử Dụng Code Để Xây Dựng Sản Phẩm

07 tháng 4, 2026·7 phút đọc

Bằng cách chia sẻ 70% component và tập trung vào hành vi thay vì nội dung, tác giả đã xây dựng thành công hai ứng dụng game bài khác biệt từ cùng một mã nguồn. Bài viết cung cấp những chiến lược thực tế về quản lý theme, config và tối ưu hóa portfolio sản phẩm cho các lập trình viên.

Một Codebase, Hai Thế Giới: Bài Học Tái Sử Dụng Code Để Xây Dựng Sản Phẩm

Khi bắt đầu xây dựng Party Challenges, tôi không hề có kế hoạch tung ra một sản phẩm thứ hai từ chính mã nguồn đó. Nhưng khoảng hai tuần vào dự án, tôi nhận ra một điều thú vị. Component thẻ bài (card component), bộ chọn bộ bài (deck selector), vòng lặp game, thiết lập PWA... không cái nào quan tâm đến nội dung được in trên mặt bài. Một thử thách "đố bạn" và một câu hỏi sâu sắc nhìn giống hệt nhau đối với một React component.

Vì vậy, tôi đã xây dựng Here We Ask dựa trên cùng một nền tảng đó. Cùng animation lật bài, cùng điều hướng bộ bài, cùng kiến trúc ưu tiên offline (offline-first). Nhưng là một sản phẩm hoàn toàn khác biệt. Dưới đây là những gì tôi học được khi tung ra hai sản phẩm từ một codebase, và lý do tại sao tôi nghĩ các lập trình viên độc lập (indie builders) nên thử cách tiếp cận này.

Lớp mã nguồn chung

Cả hai sản phẩm đều là các React SPA (Single Page Application) được xây dựng bằng Lovable - công cụ lập trình nhanh mà tôi sử dụng để tạo mẫu. Chúng chia sẻ khoảng 70% cây component của nhau:

  • Component thẻ bài với animation lật và cử chỉ vuốt (swipe gestures)
  • Bộ chọn bộ bài với bộ lọc danh mục
  • Chế độ chơi (Ghế nóng - Hot Seat, Có giới hạn thời gian - Timed, Cổ điển - Classic)
  • Service Worker PWA để chơi offline
  • Logic xoay vòng nội dung hàng ngày
  • Cổng trả phí (Premium gate) và quy trình thanh toán ($1,99/tháng cho cả hai)

Sự nhận xét then chốt ở đây: nếu bạn xây dựng các component xoay quanh hành vi thay vì nội dung, việc tái sử dụng sẽ trở nên tầm thường. Một component <GameCard> không cần biết liệu nó đang chứa nội dung là "Hãy to tiếng hát tin nhắn cuối cùng của bạn" hay "Đâu là một niềm tin mà bạn từng giữ vững 5 năm trước nhưng nay đã thay đổi?". Nó chỉ cần hiển thị văn bản, xử lý thao tác vuốt và theo dõi tiến trình.

Điểm khác biệt tạo nên thương hiệu

Phần thú vị không nằm ở code được chia sẻ, mà là ở nơi các sản phẩm buộc phải khác nhau.

Party Challenges rất ồn ào. Màu sắc rực rỡ, typography đậm, animation cảm giác như pháo hoa. Bộ bài "Date Night" (Hẹn hò) ở đây chứa những thử thách tán tỉnh và các hoạt động thể chất. Văn bản dùng những từ ngữ như "không có khoảnh khắc nhàm chán". Cảm giác chung là năng lượng của một tối thứ Sáu.

Here We Ask lại tĩnh lặng. Bảng màu nhẹ nhàng, nhiều khoảng trắng hơn, chuyển động chậm rãi. Bộ bài "Date Night" ở đây lại là những gợi ý để bộc lộ cảm xúc và kiểm tra mối quan hệ. Văn bản nói về "những kết nối ý nghĩa". Cảm giác như một sáng ngày Chủ nhật thư thái.

Cùng một component hiển thị cả hai. Lớp giao diện (theming layer) làm phần việc nặng nhọc. Tôi sử dụng một object cấu hình cho từng sản phẩm để kiểm soát mọi thứ:

// Ví dụ đơn giản hóa
const productConfig = {
  theme: 'party' | 'calm',
  cardAnimation: 'bounce' | 'fade',
  deckOrder: [...],
  premiumDecks: [...],
  dailyContentPool: 'challenges' | 'questions',
  copyVariant: 'energetic' | 'reflective'
}

Chỉ cần hoán đổi cấu hình, cảm giác của sản phẩm thay đổi hoàn toàn.

Bài học về định vị sản phẩm từ bộ bài "Date Night"

Đây là ví dụ yêu thích của tôi. Cả hai sản phẩm đều có bộ bài gọi là "Date Night". Trong Party Challenges, đó là những lá bài như "cho nhau ăn khi bị bịt mắt" hoặc "tái tạo buổi hẹn hò đầu tiên nhưng cố tình làm mọi thứ sai". Trong Here We Ask, đó là "có điều gì bạn chưa từng nói với tôi nhưng luôn muốn chia sẻ?" hoặc "một cách trung thực, bạn thấy chúng ta ở đâu trong 5 năm tới?".

Cùng tên tính năng. Cùng giao diện. Nhưng hoàn toàn khác biệt về cảm xúc.

Khi tôi cho mọi người xem cả hai, họ thường không nhận ra đó là cùng một codebase. Đó chính là mục tiêu. Công nghệ phải vô hình. Người dùng không quan tâm đến kiến trúc của bạn. Họ quan tâm xem sản phẩm có phù hợp với khoảnh khắc của họ hay không.

Toán học của danh mục sản phẩm

Đây là phần thực tế. Xây dựng sản phẩm thứ hai chỉ tốn khoảng 30% công sức so với sản phẩm đầu tiên. Phần lớn công sức đó dành cho việc tạo nội dung (viết hơn 1.000 câu hỏi so với hơn 1.000 thử thách) và công việc theme/viết bản quyền. Cơ sở hạ tầng, triển khai, thiết lập PWA, phân tích, mẫu SEO... tất cả đều được tái sử dụng.

Tôi điều hành một danh mục sản phẩm tại Inithouse. Ý tưởng thì đơn giản: xây dựng các công cụ nhỏ, tập trung và xem cái nào hiệu quả. Một số sử dụng AI, như Magical Song (bài hát AI cá nhân hóa) hoặc Pet Imagination (chân dung thú cưng AI). Số khác phụ thuộc vào nội dung, như Vibe Coderi. Mỗi cái là một thử nghiệm.

Các trò chơi bài đã dạy tôi rằng xây dựng danh mục sản phẩm không chỉ là tung ra các sản phẩm riêng biệt. Đó là việc tìm ra những xương sống chung giữa chúng. Mỗi component bạn xây dựng tốt một lần là một component bạn không bao giờ phải xây lại.

Bài học thực tế cho các nhà xây dựng sản phẩm

Bắt đầu với hành vi, không phải nội dung. Nếu cây component của bạn được tổ chức xung quanh những gì xảy ra (lật, vuốt, lọc, chặn) thay vì những gì nói (thử thách, câu hỏi, trích dẫn), bạn có thể thay đổi giao diện (reskin) nhanh hơn bạn nghĩ.

Cấu hình theme tốt hơn Feature Flags. Tôi đã thử dùng feature flags trước đó. Nó trở nên lộn xộn rất nhanh. Một object cấu hình chuyên dụng cho từng sản phẩm sạch sẽ hơn và dễ lý giải hơn. Bạn luôn biết mình đang xem sản phẩm nào trong code.

Nội dung là công việc thực sự. Phần kỹ thuật mất vài tuần. Phần nội dung mất vài tháng. Viết 1.000 thử thách tiệc tùng hay là một kỹ năng khác hoàn toàn với việc viết 1.000 câu mở đầu cuộc đối thoại hay. Đừng đánh giá phần này thấp.

Tung ra sản phẩm thứ hai trước khi hoàn thiện cái đầu tiên. Tôi có thể đã dành thêm một tháng để làm đẹp Party Challenges. Thay vào đó, tôi đã tung ra Here We Ask khi kiến trúc còn mới mẻ trong đầu mình. Cả hai sản phẩm đều được cải thiện nhanh hơn vì các bản sửa lỗi ở cái này thường áp dụng được cho cái kia.

Tiếp theo là gì?

Tôi đang xem xét mô hình này có mở rộng vượt ra ngoài các trò chơi bài hay không. Verdict Buddy (giải quyết xung đột bằng AI) và Watching Agents (nền tảng dự đoán AI) sử dụng các kiến trúc hoàn toàn khác nhau, nhưng một số mô hình cấp thấp hơn (móc SEO, thiết lập phân tích, cấu hình PWA) cứ xuất hiện mãi. Có thể đang ẩn giấu một bộ công cụ chung ở đó.

Nếu bạn đang xây dựng nhiều sản phẩm, hoặc đang nghĩ về việc đó, tôi rất muốn nghe cách bạn xử lý việc tái sử dụng code giữa chúng. Hãy để lại bình luận hoặc tìm tôi trên Dev.to.


Tôi là Jakub, người sáng lập Inithouse. Chúng tôi xây dựng một danh mục các sản phẩm web và AI nhỏ, kiểm tra ý tưởng nhanh và xem cái nào gây tiếng vang. Party Challenges và Here We Ask là hai trong số khoảng chục thử nghiệm hiện đang chạy.

Bài viết được tổng hợp và biên soạn bằng AI từ các nguồn tin tức công nghệ. Nội dung mang tính tham khảo. Xem bài gốc ↗