Skip to content

Business Model Canvas của cộng đồng ​

Mỗi cộng đồng ở tokyo.conan.school có một mục Business Model Canvas: /c/:slug/bmc. Trong đó là mô hình kinh doanh của khoảng 10 thương hiệu có thật cùng ngành, vẽ trên khung chín ô chuẩn của Osterwalder, và một chế độ so sánh hai thương hiệu theo từng ô.

Dữ liệu nằm trong git, không nằm trong D1 ​

Nguồn sự thật là api.conan.school/content/bmc/<community>.json, cùng loại và cùng luật với content/brands/ (xem story-world):

  • Thương hiệu là CÓ THẬT ⇒ cấm bịa. Mỗi ô chỉ ghi thứ quan sát được từ ngoài và ổn định theo thời gian: bán cái gì, bán cho ai, thu tiền bằng đường nào.
  • Không số liệu tài chính, không giai thoại quản trị, không sự kiện biến động.
  • slug phải tồn tại trong content/brands/<community>.json cùng tên file.

Không có bảng D1, không có migration: file JSON được import thẳng vào worker (src/domains/ communities/bmc.ts), nên sửa nội dung là một PR, và CI deploy là xong.

Khung chuẩn, không xếp lại: và chín thẻ RỜI ​

┌───────────┬───────────┬───────────┬───────────┬───────────┐
│           │ Key       │           │ Customer  │           │
│ Key       │ Activities│ Value     │ Relations │ Customer  │
│ Partners  ├───────────┤ Props     ├───────────┤ Segments  │
│           │ Key       │           │ Channels  │           │
│           │ Resources │           │           │           │
├───────────┴───────────┼───────────┴───────────┴───────────┤
│ Cost Structure        │ Revenue Streams                   │
└───────────────────────┴───────────────────────────────────┘

Bố cục tự nó mang nghĩa: nửa trái là nơi chi phí sinh ra, nửa phải là nơi tiền đến, cột giữa nối hai bên. Xếp chín ô thành danh sách dọc là mất tầng nghĩa đó, màn hẹp thì cuộn ngang trong khung, không xếp lại.

Chín ô là chín thẻ rời có khoảng cách, không phải chín ngăn của một lưới kẻ: mỗi ô là một câu hỏi riêng về mô hình kinh doanh, và khoảng trắng nói điều đó rõ hơn một đường kẻ. Các mục trong thẻ không có dấu đầu dòng, chỉ ngăn nhau bằng một vạch mờ.

Màu: chín token trong theme.css, không đặt trong site ​

--color-bmc-partners … --color-bmc-revenue + --color-bmc-foreground nằm ở packages/design-system/theme.css, cùng họ với course-* và score-*. Đây là một taxonomy, không phải màu trang trí:

VùngNgả màuNghĩa
Đối tác · Hoạt động · Nguồn lựcnóng (tím đậm, cam, hổ phách)phía tiêu tiền
Quan hệ · Kênh · Nhóm kháchlạnh (xanh mòng két, xanh trời, xanh dương)phía mang tiền về
Giá trị mang lạixanh lá, đứng riêngchỗ hai phía gặp nhau
Chi phí / Doanh thutím / xanh mòng kétlặp lại đúng cặp đó ở hàng dưới

Đổi màu ở đây là đổi tầng nghĩa ấy, không chỉ đổi thẩm mỹ.

Lớp nền viết nguyên chuỗi trong BLOCKS (bg: "bg-bmc-partners"), không ghép `bg-bmc-${key}`: Tailwind quét mã bằng văn bản thuần, lớp chỉ tồn tại sau khi ghép lúc chạy thì không được sinh ra, thẻ mất nền, và mất im lặng, vì không có lỗi nào cả.

Tab BMC không có câu mô tả dưới tiêu đề: khung chín ô tự nói nó là cái gì.

Dấu hỏi ở góc mỗi thẻ ​

Mỗi thẻ có một nút Info ở góc trên phải, mở Popover giải thích ô đó. Ba phần, theo thứ tự câu hỏi → định nghĩa → câu hỏi thứ hai (ask, help, probe trong BLOCKS):

  1. ask, ô này trả lời câu hỏi nào. Người đang nhìn canvas cần biết điều đó trước, định nghĩa chỉ hữu ích sau khi đã biết nó hỏi gì.

  2. help, định nghĩa ngắn, kèm chỗ hay lẫn (Kênh khác Quan hệ; "mọi người" không phải một nhóm khách; người trả tiền không phải lúc nào cũng là người dùng).

  3. probe, câu hỏi soi vào chính doanh nghiệp của người đọc, đóng trong một khung riêng. ask giúp đọc canvas của người khác; probe là câu mang về bàn làm việc của mình. Thiếu nó thì popover chỉ là một cuốn từ điển, biết định nghĩa xong không biết làm gì tiếp.

    Đóng khung, không đổi màu chữ, và không nhãn: chữ màu thương hiệu đọc như một liên kết bấm được trong khi nó không bấm được, còn một câu hỏi đóng khung tự nó đã là lời mời dừng lại.

Cả ba đều là cặp [en, vi] nên nút EN/VI đổi được.

Là Popover bấm vào, không phải tooltip rê chuột hay thuộc tính title: trên điện thoại không có con trỏ để rê, và nội dung dài hơn một dòng.

Gác Pro nằm ở API: và nó gác Ô, không gác THƯƠNG HIỆU ​

Mô hình nếm thử (07.09.2026):

AiThấy gì
chưa Prohai thương hiệu đầu mở trọn chín ô; từ thương hiệu thứ ba mỗi cái một ô
Procả mười thương hiệu, đủ chín ô

Vì sao hai chứ không phải một: một cái là bản trưng bày (open: true) để thấy canvas hoàn chỉnh trông ra sao; cái thứ hai tồn tại vì so sánh cần hai vế, mở đúng một thương hiệu thì tính năng so sánh không có gì để demo, và một tính năng không demo được thì không bán được.

GET /api/communities/:slug/bmc trả:

TrườngNghĩa
data[]mọi thương hiệu; chưa mở đủ thì blocks chỉ chứa một ô kèm locked: true
free_blockkhoá của ô đang mở (null khi mở trọn)
free_full_brandsBMC_FREE_FULL_BRANDS = 2
free_blocks_per_brandBMC_FREE_BLOCKS_PER_BRAND = 1
can_compareluôn true, so sánh mở cho mọi người

Tám ô của thương hiệu khoá không đi ra khỏi worker. Vì thế so sánh tự giới hạn ở hai bản demo mà không cần thêm lớp gác nào: không có đủ ô thì không có gì để so. can_compare chỉ để giao diện biết vẽ gì.

Giao diện vẽ gì ​

Chọn thương hiệu bằng một nút xổ xuống, không phải một hàng mười nút: mười nút bày sẵn chiếm trọn một dòng màn hình và bắt mắt quét qua mười cái tên trước khi tới canvas, trong khi phần lớn thời gian người ta chỉ đang xem một thương hiệu.

Ở chế độ so sánh, thương hiệu chưa đủ chín ô hiện ổ khoá trong danh sách xổ và dẫn sang trang gói Pro, ở chế độ một thương hiệu thì không, vì xem một ô vẫn là xem được.

Tám ô chưa mở giữ đúng màu, đúng chỗ, đúng nhãn, chỉ mờ đi kèm nút "Mở với Pro". Dấu hỏi giải thích ô vẫn bấm được ở ô khoá, biết ô này hỏi gì mình là phần miễn phí.

Các ý trong thẻ cắt ở dòng thứ hai và không có tooltip: rê chuột qua canvas là rê qua ba chục dòng, một hộp đen bật lên ở mỗi dòng làm việc đọc canvas thành việc né tooltip. Ý bị cắt đọc đủ được ở bảng so sánh, nơi mỗi ý có cả một cột.

Ô nào mở: băm từ slug, KHÔNG random từng lượt ​

freeBlockOf(slug) băm FNV-1a rồi chia dư cho 9. Vế "cố định theo thương hiệu" là vế giữ cho paywall còn nghĩa: random mỗi lượt gọi thì tải lại trang vài lần là gom đủ chín ô, và cái gác biến thành một trò bất tiện chứ không phải một cái gác. Cố định theo slug thì tải lại bao nhiêu lần cũng vẫn đúng ô đó.

Đổi hàm băm là đổi ô đang mở của cả 180 thương hiệu cùng lúc, không sai, nhưng biết trước thì hơn.

Giao diện vẽ gì ​

Danh sách thương hiệu không có ổ khoá, bấm cái nào cũng mở được canvas. Tám ô chưa mở vẫn giữ đúng màu, đúng chỗ, đúng nhãn, chỉ mờ đi và có một nút "Mở với Pro": người xem thấy canvas còn bao nhiêu phần nữa và chúng là những phần nào. Dấu hỏi giải thích ô vẫn bấm được ở ô khoá

  • biết ô này hỏi gì mình là phần miễn phí, chỉ câu trả lời cho một thương hiệu cụ thể mới phải trả tiền.

Giao diện không tự suy quyền từ my_tier, và cũng không suy ô khoá từ free_block: ô nào không có trong blocks thì đó là ô chưa mở, một chỗ quyết, không phải hai.

Trạng thái nội dung (06.09.2026) ​

Đủ 18/18 cộng đồng, mỗi cộng đồng 10 thương hiệu, 180 canvas.

Một thương hiệu có mặt ở nhiều cộng đồng (Toyota ở finance, operations, ceo-executive…) thì canvas được chép nguyên sang file của cộng đồng đó, không tham chiếu chéo. Chép là cố ý: mỗi file tự đứng được, và nếu sau này một cộng đồng muốn nhìn cùng thương hiệu dưới góc khác thì sửa tại chỗ mà không đụng cộng đồng khác. Cái giá là sửa một thương hiệu dùng chung phải sửa ở từng file, kiểm bằng grep -l '"slug": "toyota"' content/bmc/*.json.

Thêm cộng đồng hay thương hiệu mới phải làm đủ hai vế: thêm/sửa file JSON và khai vào BY_COMMUNITY trong bmc.ts. Quên vế thứ hai thì tab hiện "chưa có canvas nào" trong khi file đã nằm trong repo, hỏng mà không có lỗi nào để lần ra.

Canvas gọn, chế độ toàn màn hình, vùng giải thích (27.09.2026) ​

Theo người soạn:

  • Canvas vừa khung nội dung, không thanh cuộn ngang (bỏ min-w-[76rem]; ô và chữ nhỏ lại, chữ không dưới 14px). Dưới 900px xếp một cột.
  • Bỏ nút (i) trong từng ô, lời giải thích chuyển xuống vùng giải thích dưới canvas: một dropdown chọn 1 trong 9 ô, bày câu hỏi của ô, lời giải thích, câu tự kiểm, và toàn bộ mục của thương hiệu (so sánh thì hai thương hiệu cạnh nhau).
  • Nút "Xem toàn màn hình": canvas phủ kín màn hình (Esc để thoát), không còn phần nào khác của trang. Gác Pro giữ nguyên ở API.

Tài liệu nội bộ nền tảng Conan School.