1 Bộ Code, 7 Sản Phẩm — Cách Mình Chạy Cả Hệ Sinh Thái Bằng Laravel

1 bộ codebase Laravel chạy toàn bộ hệ sinh thái web, 1 người vận hành — câu chuyện từ quản lý các project riêng lẻ đến xây dựng một hệ thống dùng chung tự động.
1 Bộ Code, 7 Sản Phẩm — Cách Mình Chạy Cả Hệ Sinh Thái Bằng Laravel

bộ codebase Laravel chạy toàn bộ hệ sinh thái web, 1 người vận hành — câu chuyện từ quản lý các project riêng lẻ đến xây dựng một hệ thống dùng chung tự động.

Nhiều sản phẩm web. 1 người hệ thống — là mình. Không team kỹ thuật, không co-founder code, không outsource.

Mình làm mọi thứ với một mục tiêu cốt lõi: giành lại khối thời gian hữu hạn mỗi ngày. Mình thà dùng thời gian rảnh đó để đưa gia đình đi ăn, ngồi cốc bia chém gió với anh em, hay thảnh thơi vác cần đi câu cá... thay vì cắm mặt vào code đi code lại cùng một đoạn logic vô tri.

Chính sự "tiếc rẻ thời gian" đó đã buộc mình phải tìm cách xây hệ thống thay vì cặm cụi xây từng sản phẩm riêng lẻ. Kết quả là 1 bộ codebase Laravel duy nhất đang chạy cả hệ sinh thái web của mình — SmailPro, YChecker, Smser, CardGener, UGener, StoreGmail, và my.sonjj.com — từ 1 chỗ duy nhất.

Bài này là câu chuyện đằng sau hệ thống đó. Tại sao nó ra đời. Nó hoạt động như thế nào. Và nếu bạn đang quản lý nhiều site rời rạc và cảm thấy mệt... khả năng cao bạn đang ở đúng chỗ mình từng ở.

01 ecosystem collage

Khi mỗi website là một nổi đau đầu riêng

Trước khi có cái hệ thống này, mỗi sản phẩm của mình là một project Laravel riêng. SmailPro 1 repo. YChecker 1 repo. Smser 1 repo. Mỗi cái có database riêng, auth riêng, codebase riêng.

Lúc mới build thì không sao — mỗi project còn nhỏ, tập trung được. Nhưng khi bắt đầu vận hành song song 3, 4, rồi 5 sản phẩm thì vấn đề bắt đầu chồng chất — theo một cách rất khó chịu.

Cập nhật 1 thứ nhỏ — ví dụ thêm nút đăng nhập Google — mình phải apply ở SmailPro, rồi copy sang YChecker, rồi Smser, rồi tiếp. 7 lần commit. 7 lần deploy. 7 cơ hội để quên mất hoặc làm sai ở đâu đó mà không biết.

User cũng bị mắc kẹt giữa các products. Ai đã đăng ký SmailPro rồi muốn dùng thử YChecker phải tạo tài khoản mới từ đầu. Họ không biết 2 cái này cùng của 1 chủ. Và mình cũng không có cách nào kết nối 2 user đó lại, không có cách nào nói với họ rằng "bạn đã có account rồi, dùng chung email đi".

Điểm bùng phát thực sự là 1 buổi tối mình ngồi fix bug. Fix xong ở YChecker, check lại code, nhớ ra SmailPro cũng có y hệt cái lỗi đó. Vào fix. Xong thì nhớ Smser cũng vậy. Vào fix tiếp.

Giữa lần fix thứ ba trong tối hôm đó, mình dừng lại và nhận ra: mình đang làm y chang cái việc này lần thứ ba rồi.

Và câu hỏi tự nhiên xuất hiện: có cách nào làm 1 lần thay vì 7 lần không?

1 bộ codebase, nhiều sản phẩm — quyết định thay đổi cuộc chơi

Hình dung thế này: thay vì chạy nhiều quán ăn riêng lẻ với các nhà bếp độc lập, mình xây duy nhất 1 nhà bếp trung tâm, rồi các website chỉ là những "cửa hàng" kết nối vào đó. Nâng cấp nhà bếp → tất cả các quán đều được hưởng ngay. Không cần mất công dọn dẹp từng chỗ một.

Đó là cách bộ Laravel multi-tenant hoạt động với hệ sinh thái của mình. 1 codebase duy nhất — mỗi domain được nhận dạng tự động và serve đúng nội dung, đúng config của sản phẩm đó. SmailPro.com, YChecker.com, Smser.net — mỗi cái trông khác nhau với user, nhưng cùng chạy từ một "cỗ máy" bên dưới.

02 code base

Phần quan trọng hơn là shared authenticationthanh toán tập trung (integrated billing). User đăng ký SmailPro một lần → có thể dùng YChecker, UGener, CardGener mà không cần tạo lại tài khoản. 1 tài khoản, toàn hệ sinh thái.

Việc tích hợp thanh toán cũng vậy. Thay vì rải rác mỗi web một luồng check payment, mình chỉ cần tích hợp Paddle đúng một lần duy nhất vào codebase. Quản lý subscription, xử lý webhook, refund... tất cả quy về một mối, lo thanh toán cho toàn bộ app con.

Và điều này giúp các sản phẩm thực sự hỗ trợ lẫn nhau. User SmailPro cần verify email? YChecker nhảy vào luôn. User đăng nhập bên này mua gói Premium, thì các dịch vụ khác trong ecosystem cũng tự hiểu. Mọi thứ vận hành trơn tru vì tệp user không bị cắt vụn.

Kết quả của luồng này:

  • Update 1 lần → tất cả sites nhận ngay lập tức
  • Fix bug 1 chỗ → xử gọn lỗi toàn hệ thống
  • Tích hợp tính năng mới (như cổng thanh toán) làm 1 lần dùng mãi mãi

Mặt trái của sự "tất cả trong một"

Tất nhiên, cái gì có ưu cũng sẽ có nhược. Kỹ thuật này tuyệt đối không phải là "thần dược" cho mọi loại dự án. Bản chất nó sinh ra để giúp việc quản lý những site nhỏ, các tool online đơn giản dùng chung tệp user được nhẹ nhàng hơn.

Sẽ là thảm hoạ hoặc đi vào lòng đất nếu bạn áp dụng nó sai mục đích:

  • Làm blog cá nhân / website giới thiệu đơn giản: Áp dụng hệ sinh thái này chẳng khác nào "cầm dao mổ trâu đi giết gà" vì bộ code setup quá cồng kềnh. Làm blog cứ tẻ tẻ bằng Ghost hoặc WordPress cho nhàn rỗi.
  • Làm hệ thống Enterprise / Startup quy mô lớn: Khi các ứng dụng có core logic quá phức tạp và hoàn toàn tách biệt nghiệp vụ, việc bắt chúng nằm chung trên 1 codebase sẽ biến mọi thứ thành một "nồi lẩu spaghetti". Khi đó, sửa cái này dễ làm sập cái kia. Điểm mù cực kỳ lớn.

Hệ thống này chỉ thực sự phát huy tối đa sức mạnh khi mục tiêu của bạn là xây dựng một chuỗi mini SaaS, các bộ tool trực tuyến (SmailPro, Smser...) — dồn mọi tài nguyên về một chỗ để dễ kiểm soát mà không tự vắt kiệt bản thân.

Ghost không chỉ là blog — đây là nơi mình điều hành cả hệ sinh thái

Hầu hết mọi người biết Ghost là blogging platform. Mình cũng dùng Ghost như vậy lúc đầu — viết bài, publish, xong. Nhưng sau một thời gian mày mò, mình nhận ra Ghost có thể làm được nhiều hơn thế rất nhiều.

Member dashboard cho cả hệ sinh thái. Ghost có native member management — mình dùng đó như CRM trung tâm. Toàn bộ member từ SmailPro, YChecker, Smser và các sản phẩm khác đều hiện ra trong 1 chỗ. Không cần mua thêm tool CRM riêng, không cần Mailchimp hay HubSpot.

03 ghost dashboard

Email marketing built-in. Gửi newsletter đến toàn bộ users? Chỉ cần compose trong Ghost rồi nhấn "Send". Mailgun lo phần còn lại. Không cần setup thêm bất cứ thứ gì.

Writer management. Khi có người viết bài cho sonjj.com, họ làm việc trực tiếp trong Ghost — draft, submit, mình review và approve ngay tại đó. Không cần giải thích tool mới, không cần tạo workspace riêng, không cần cấp quyền phức tạp.

Nhưng phần ăn tiền nhất là sync 2 chiều giữa Ghost ↔ Laravel. Cụ thể: ai đăng ký tài khoản ở bất kỳ sản phẩm nào trong hệ sinh thái → tự động trở thành Ghost member → tự động được đưa vào danh sách nhận newsletter. Ngược lại cũng vậy: ai subscribe newsletter trực tiếp qua sonjj.com → tự động có tài khoản trong hệ thống, có thể dùng sản phẩm ngay.

Cái sync 2 chiều này là thứ mình chưa thấy ai viết về. Không phải vì nó khó — mà vì không nhiều người vừa có Ghost vừa có Laravel vừa muốn kết nối chúng lại. Phần kỹ thuật chi tiết sẽ có trong bài riêng trong series premium.

Những thứ hệ thống tự chạy để tôi không phải động tay

Hôm qua mình ngủ 8 tiếng. Sáng dậy, tất cả các website vẫn đang miệt mài phục vụ user. Lần cuối mình phải mở 5 7 cái terminal ra để deploy từng server riêng... chắc là từ thời đồ đá nào rồi chứ mình không nhớ nổi.

Mỗi khi có user mới đăng ký — email welcome tự kích hoạt. Các pipeline vận hành kiểu này được n8n lo hết. Cứ thế lẳng lặng chạy mà tiết kiệm cho mình tới khối giờ đồng hồ mỗi tháng.

Chi phí server cũng giảm đáng kể. Thay vì cứ mỗi dự án cõng một núi tool và hạ tầng riêng rẽ, toàn bộ mọi thứ đặt trên Vultr và chạy chung nguồn lực.

Để mà so sánh, nhiều solo founder phải khóc ròng vì lỡ duy trì 3-4 web app riêng lẻ tốn kém. Mình ôm một loạt các web tiện ích nhưng chi phí hàng tháng khá dễ chịu. Mà sướng nhất là có thêm "đứa con" nào tiếp theo, mình chỉ việc nhét nó vào chung cái gầm tủ này — cost cho infra gần như không đổi.

Tự động hoá hệ thống không phải để "ôm" được nhiều việc hơn. Nó là để cuối tuần bạn có thể thảnh thơi gập máy đi nhậu, đi câu cá hay chơi với con mà không lo nơm nớp sợ server hỏng.

Tiếp theo trong series này

Bài này chỉ là bức tranh tổng quan — mục đích là để bạn hiểu cái hệ thống này trông như thế nào. Phần kỹ thuật thực sự — cách mình setup từng mảnh — mình đang ghi lại thành series riêng:

  1. Setup Laravel Multi-Tenant từ A→Z — từ codebase trắng đến domain detection, tenant isolation, shared auth
  2. Ghost + Mailgun + Sync Member 2 chiều — tại sao Ghost, cách kết nối với Laravel, nhét data vào nhau kiểu gì
  3. Automation layer với n8n — tiết kiệm cả mớ thời gian hàng tháng ra làm sao
  4. Infrastructure & Server Setup — cách giữ cho chi phí tối thiểu mà mọi thứ vẫn mượt mát

Mình không hứa hẹn timeline cụ thể — nhưng đang ghi lại từng bước và sẽ chia sẻ tiếp. Nếu bạn muốn nhận thông báo khi bài mới ra, đăng ký newsletter là đủ. Không spam. Không bán hàng.

Đăng ký nhận bài mới — Newsletter sonjj.com

Bạn không cần là thiên tài, bạn chỉ cần biết "tiếc" thời gian

Cái hệ thống này không được xây bởi một dev pro.

Nó được xây bởi một người cực kỳ quý trọng thời gian — người mà vào một buổi tối, ngồi fix cùng 1 bug đến lần thứ ba ở các web khác nhau và chợt bất giác tự hỏi: "Có cách nào làm đúng 1 lần thay vì cặm cụi fix ở đủ 7 nơi không?"

Câu hỏi đó, nếu bạn cứ hỏi đủ nhiều lần, dần dần sẽ đẻ ra một hệ thống. Không phải vì bạn giỏi hơn người khác — mà vì bạn nhận ra ngoài kia còn bao nhiêu thứ vui vẻ đáng để làm hơn là việc thức đêm bảo trì mã nguồn lặp lại.

Nếu bạn đang vận hành nhiều sản phẩm và cảm thấy mệt với bảo trì — series này viết cho bạn. Không phải để flex. Để chia sẻ cái gì đã thực sự làm được, từ người đang chạy nó hàng ngày.

Bài tiếp theo: Setup Laravel Multi-Tenant từ A→Z.

Email sent. Check your inbox!

No spam, no sharing to third party. Only you and me.