Back to all posts

Cách tôi tự động hóa toàn bộ quy trình sản xuất blog

Cách tôi tự động hóa toàn bộ quy trình sản xuất blog

Tôi là Ming. Bên cạnh thiết kế sản phẩm tại vm0, vận hành nội dung cũng là một phần công việc của tôi, và hóa ra nó phức tạp hơn tôi nghĩ: thiết kế quy trình, minh họa, sản xuất hình ảnh, làm việc với CMS, dịch thuật. Đây là cách tôi dần hoàn thiện mọi thứ.


Nội dung là một phần công việc của tôi ở đây

Phần lớn thời gian trong ngày của tôi tại vm0 được chia giữa thiết kế sản phẩm và codebase Next.js. Nhưng vận hành nội dung cũng là trách nhiệm của tôi, và khi bắt đầu, tôi mới nhận ra để có một blog hiệu quả cần rất nhiều thứ. Bạn cần xuất bản đều đặn, nghiên cứu từ khóa thực sự, hình ảnh nhất quán với thương hiệu, mô tả meta ổn, và dịch sang bốn ngôn ngữ mà chúng tôi hỗ trợ.

Khi tôi bắt đầu làm nghiêm túc, mỗi bài viết tốn gần như cả ngày. Việc viết chỉ là một phần nhỏ. Phần lớn thời gian dành cho các công đoạn sản xuất quanh việc viết: tìm từ khóa phù hợp, tạo ảnh bìa, điền đúng trường trong CMS, lặp lại cho từng ngôn ngữ.

Vì vậy tôi đã dần chuyển càng nhiều phần trong quy trình đó sang Lucas, một agent AI marketing tôi xây dựng trên Zero dựa trên công việc hàng ngày của mình. Lucas được cấu hình là "Marketing manager" và phạm vi là mọi thứ liên quan đến marketing: sản xuất blog là phần hoàn thiện nhất hiện tại, và Lucas tiếp tục phát triển khi tôi bổ sung kỹ năng và connector mới.

Hiện tại Lucas có quyền truy cập vào Strapi headless CMS, tài khoản Ahrefs, Slack nhóm, web chat, một kỹ năng nội bộ draw để tạo minh họa nhất quán thương hiệu, cùng kỹ năng tiêu chuẩn copywriting cho các thao tác viết.

Dưới đây tôi sẽ trình bày cách tự động hóa blog bằng AI này hoạt động thực tế: Lucas nhận một prompt mơ hồ, phân tích thành chủ đề và từ khóa, soạn nháp bài viết, vẽ ảnh bìa, dịch tự nhiên sang bốn ngôn ngữ và đưa bản nháp vào CMS. Sau đó tôi sẽ nói về quá trình xây dựng và những gì tôi cố ý để con người xử lý (vẫn chủ yếu là tôi).


Tôi dùng Lucas như thế nào: web app và Slack

Tôi chủ yếu làm việc với Lucas qua web chat của vm0. Đây là giao diện tập trung, nơi tôi cùng Lucas lên dàn ý, soạn nháp, chỉnh sửa ảnh bìa và biên tập. Chuỗi hội thoại dài, nhiều ngữ cảnh, kiểu trao đổi qua lại mà chat channel sẽ rất bất tiện.

Lucas cũng được kết nối với Slack nhóm, như một điểm vào chung. Tôi gửi prompt nhanh từ điện thoại, và các thành viên khác cũng có thể ping Lucas. Ai đến lượt viết blog cũng khởi động bài viết theo cách này. Cùng một agent, cùng ngữ cảnh trên cả hai giao diện.


Một prompt điển hình trông như thế nào

Prompt của tôi gửi cho Lucas thường rất ngắn. Tối đa ba câu. Một ví dụ tiêu biểu:

Lucas, viết hướng dẫn tổ chức họp tuần hiệu quả: đề cập cấu trúc cuộc họp, lỗi thường gặp và cách giữ đội ngũ từ xa gắn kết. Phong cách hướng dẫn, tối ưu SEO, kết thúc bằng CTA dùng Zero. Chỉ cần link nháp, không xuất bản.

Đó là toàn bộ yêu cầu. Một tin nhắn. Không dàn ý, không danh sách từ khóa, không brief thiết kế, không giới hạn độ dài. Lucas tự xử lý phần còn lại.

Tôi mất một thời gian mới định hình được format này. Ban đầu tôi viết brief rất dài vì nghĩ agent cần mọi thứ chi tiết, rồi nhận ra phần lớn ngữ cảnh nên nằm trong hướng dẫn và kỹ năng mặc định của agent, không phải từng prompt. Prompt chỉ là kích hoạt; cấu hình còn lại mới quan trọng.


Lucas phân tích chủ đề và từ khóa như thế nào

Bước đầu tiên của Lucas là trích xuất cấu trúc từ prompt mơ hồ. Với yêu cầu như trên, ghi chú làm việc của Lucas sẽ như sau:

  • Chủ đề: tổ chức họp tuần hiệu quả
  • Định dạng: hướng dẫn → các bước đánh số, ví dụ cụ thể, ngôn ngữ "làm thế này"
  • Đối tượng ngầm định: trưởng nhóm, quản lý từ xa, founder
  • Các phần bắt buộc: cấu trúc họp, lỗi thường gặp, gắn kết đội ngũ từ xa
  • CTA: hướng người đọc đến Zero
  • Ràng buộc: chỉ URL nháp, không xuất bản

Sau đó Lucas chọn từ khóa. Đây là phần tôi ít có trực giác nhất khi mới bắt đầu, nên tôi xây cho Lucas một quy trình mỗi khi tôi yêu cầu làm từ khóa. Đây không phải kỹ năng tự động, chỉ là chuỗi thao tác tôi tin tưởng giao cho Lucas:

  1. Lấy danh sách từ Ahrefs. Lucas gọi API Ahrefs với cụm chủ đề, trả về các biến thể long-tail cùng lượng tìm kiếm hàng tháng, độ khó từ khóa (KD), chủ đề cha và ý định tìm kiếm.
  2. Lọc theo độ khó. Tôi đặt quy tắc cứng: KD < 30. vm0 là domain mới, độ uy tín còn thấp, nên chưa phù hợp với từ khóa KD cao. Long-tail là lựa chọn tốt lúc đầu.
  3. Đối chiếu với index Strapi. Lucas lấy tất cả slug đã xuất bản từ CMS qua Strapi REST API và loại bỏ từ khóa đã dùng. Tránh trùng lặp nội dung.
  4. So khớp ý định với sản phẩm. Ý định từ khóa phải phù hợp với thư viện use case của chúng tôi. "Cách tổ chức họp tuần hiệu quả" → vận hành / quản lý nhóm → phù hợp. "Best ramen in Tokyo" → không phù hợp, dù lượng tìm kiếm cao.
  5. Chọn một từ khóa. Từ danh sách đã lọc, Lucas chọn phương án có lượng tìm kiếm cao nhất và dùng làm trục chính cho bài viết. Ví dụ: remote weekly meeting best practices.

Về SEO on-page, Lucas áp dụng quy tắc đơn giản: từ khóa mục tiêu trong tiêu đề, ít nhất một H2, và trong 100 từ đầu tiên. Từ đồng nghĩa và cụm liên quan được lồng ghép tự nhiên. Liên kết nội bộ đến hai hoặc ba bài liên quan nếu phù hợp. Sau đó: viết tự nhiên, không nhồi nhét từ khóa.

Cấu trúc bài viết (sáu hoặc bảy H2, mỗi bước có callout "Tip:", CTA ở cuối) dựa trên template hướng dẫn tôi xây dựng qua nhiều bài.


Ảnh bìa được vẽ như thế nào

Ảnh bìa là phần tôi quan tâm nhất trong sản xuất blog, một phần vì tôi là designer, một phần vì đó là thứ độc giả nhìn thấy đầu tiên. Nó cũng là ảnh Open Graph khi chia sẻ bài lên X hoặc LinkedIn, và giúp blog trông như một tạp chí thay vì một dãy ảnh stock.

Ảnh stock không phù hợp với phong cách tôi muốn, còn thuê vẽ từng minh họa sẽ khiến chi phí sản xuất mỗi bài quá cao. Vì vậy tôi xây kỹ năng Zero tên draw. Đó là script Python 200 dòng thực hiện năm bước:

  1. Nhận hai đầu vào: ẩn dụ (chủ đề để vẽ) và màu sắc (tên thân thiện và mã hex).
  2. Đưa vào template prompt cố định, khóa chặt bố cục: nền xám ấm #eeeeee, mảng màu nước ở giữa canvas với màu đã chọn, nét vẽ tay bằng mực phía trên, logo vm0 trong suốt ở (25, 25) góc trên trái.
  3. Gửi prompt đã ghép đến model fal.ai nano-banana-pro tại 16:9.
  4. Tải về PNG. Chuẩn hóa mọi pixel gần trắng về đúng #eeeeee để nền không bị lệch. Nâng cấp lên 1600×900. Alpha-composite logo vm0 trong suốt lên trên.
  5. Tải kết quả lên CDN của vm0 và in ra URL.

Một lần gọi điển hình như sau:

python draw.py \
  --metaphor "a tilted hourglass with sand draining into a small open notebook, a sparkle near the rim" \
  --color-name "dusty rose" \
  --color-hex "#e08b96" \
  --upload

Chỉ hai đầu vào, phần còn lại của thương hiệu luôn nhất quán. Tôi thường chọn màu phù hợp với chủ đề bài viết. Coral hoặc sage cho bài hướng dẫn ấm áp, xanh hoặc lavender cho bài kỹ thuật, vàng mustard cho thông báo. Một vài màu lặp lại dần biến blog thành bảng màu nhận diện.

Điều tôi rút ra là điểm mấu chốt không nằm ở model, mà ở template. Nếu để model tự chọn bố cục, bảng màu, layout thì mỗi ảnh bìa lại thành một thương hiệu khác nhau. Khóa chặt các yếu tố đó và chỉ cho phép chọn ẩn dụ giúp giữ phong cách nhất quán giữa các bài.

Có một kỹ năng anh em tên illustration dùng cho minh họa nhỏ trong bài (các hình vẽ nhỏ giữa các phần như bạn thấy ở bài này). Cùng ý tưởng: phong cách cố định, chỉ thay đổi ẩn dụ và màu sắc. Chỉ khác là tối ưu cho ảnh vuông 1024×1024 thay vì ảnh bìa 16:9.

Một lưu ý nhỏ về SEO hình ảnh: cùng một ảnh bìa được dùng làm asset Open Graph và Twitter Card, nên chia sẻ mạng xã hội sẽ hiển thị đúng. Strapi tự động tạo bốn phiên bản kích thước khác nhau khi upload (thumbnail, small, medium, large), nhưng tôi chưa kết nối phần thân bài để tải các phiên bản này qua srcset. Đó là một TODO nhỏ ở front-end. Minh họa chèn trong bài sẽ có alt text mô tả khi Lucas nhúng vào markdown; trường alternativeText của ảnh bìa trong Strapi tôi vẫn muốn bổ sung thêm.


Bài viết được soạn như thế nào

Khi chủ đề, từ khóa và ảnh bìa đã chốt, việc soạn nháp chủ yếu là thao tác máy móc. Lucas:

  1. Lên dàn ý trước. Sáu hoặc bảy H2, mỗi H2 có nhiệm vụ rõ: đặt vấn đề, hướng dẫn từng bước, callout "Tip:", tóm tắt, CTA.
  2. Mở rộng từng H2 thành đoạn văn bằng kỹ năng copywriting. Giọng văn (câu ngắn, ví dụ cụ thể, dùng ngôi thứ hai khi phù hợp, đôi khi hài hước nhẹ) lấy từ quy tắc tôi lưu trong hướng dẫn mặc định của Lucas, không phải từ kỹ năng viết.
  3. Thêm callout "Tip:" thực tế dưới mỗi bước. Hữu ích cho bài hướng dẫn vì đa số độc giả chỉ lướt, callout giúp họ nắm ý chính trong bài dài.
  4. Viết trường description của bài. Strapi giới hạn 80 ký tự, nên phải ngắn và tự nhiên như người viết. Dùng làm phụ đề bài và mô tả OG/Twitter card.
  5. Kết thúc bằng CTA nêu tên sản phẩm và liên kết workspace miễn phí.

Bản nháp đầu tiên thường trả về sau hai, ba phút kể từ prompt. Tôi đọc, yêu cầu chỉnh giọng văn nếu chưa ổn, và Lucas lặp lại cho đến khi đạt. Bản nháp đầu hiếm khi xuất bản được ngay. Thường đã khá ổn nhưng vẫn cần chỉnh, và đó là phần tôi dành nhiều thời gian review nhất.


Bản nháp được đưa vào Strapi như thế nào

Chúng tôi dùng Strapi làm headless CMS. Content type articles có trường cover (media), author và category (liên kết), locale (string), và dynamic zone blocks chứa phần thân bài.

Quy trình đồng bộ CMS của Lucas:

  1. POST ảnh bìa PNG lên /api/upload. Lưu lại documentId trả về.
  2. POST lên /api/articles?status=draft với tiêu đề, mô tả (≤80 ký tự; Strapi kiểm tra), slug, locale, các liên kết cover/author/category dưới dạng ID số, và một block shared.rich-text chứa markdown body.
  3. Lưu ý: bỏ qua publishedAt. Strapi coi null là trạng thái nháp.
  4. Trả về URL preview theo pattern nháp của vm0: https://www.vm0.ai/{locale}/blog/posts/{slug}?status=draft.

Lưu ý với Strapi v5: public REST API có thể ghi đè publishedAt trên một số content type, nghĩa là "nháp" tạo qua API có thể tự động xuất bản. Cách khắc phục là migration nhỏ trên DB để loại bỏ trường này khi ghi nháp.

Chiến lược slug cũng quan trọng cho SEO. Chúng tôi dùng một slug chuẩn cho cả bốn ngôn ngữ thay vì dịch. Độc giả trên /de/blog/posts/remote-weekly-meeting-best-practices sẽ thấy cấu trúc URL giống như trên /en, và backlink không bị phân mảnh giữa các URL dịch. Việc xuất thẻ hreflang từ các liên kết locale là một TODO nhỏ ở front-end. Hiện tại chưa triển khai.


Dịch i18n hoạt động như thế nào

vm0 hỗ trợ bốn ngôn ngữ: tiếng Anh, Đức, Nhật, Tây Ban Nha. Chúng tôi không dùng Google Translate cho bài viết. Cách rẻ làm mất giọng văn; cách đúng là chuyển ngữ tự nhiên.

Lucas tạo bản nháp EN trước, lấy documentId trả về, rồi thực hiện ba lệnh PUT /api/articles/{documentId}?locale=de tiếp theo (và ?locale=ja, ?locale=es) với payload đã dịch tự nhiên. Strapi coi đó là các biến thể locale của cùng một tài liệu gốc, giúp bốn bản luôn liên kết trong admin và trên front-end khi chuyển ngôn ngữ.

Quy tắc dịch tôi đặt ra, chủ yếu rút từ kinh nghiệm sửa lỗi:

  • Không dịch thuật ngữ kỹ thuật đã là từ mượn tiếng Anh trong ngôn ngữ đích. "API," "CMS," "agent," và "prompt" giữ nguyên trong JA và DE. Dịch sang bản địa nghe không tự nhiên.
  • Chuyển ngữ thành ngữ tự nhiên. Dịch sát nghĩa "kills your Friday" sang tiếng Đức sẽ vô nghĩa; dùng phép ẩn dụ bản địa sẽ hợp lý hơn.
  • Điều chỉnh CTA theo từng ngôn ngữ. Câu mệnh lệnh nghe mạnh ở DE, nên tôi làm nhẹ lại; bản JA thường chuyển thành lời mời lịch sự.
  • Điều chỉnh tiêu đề cho phù hợp độ dài. Tiêu đề tiếng Đức thường dài hơn tiếng Anh khoảng 30% ký tự. Tiêu đề tiếng Nhật thường ngắn hơn. Lucas giữ tiêu đề dưới giới hạn 60 ký tự của SERP cho từng ngôn ngữ.

Xuất bản đa ngôn ngữ từng là phần tốn thời gian nhất trong quy trình. Giờ chỉ còn là bước cuối cùng trong một lần chạy agent.


Những gì không tự động hóa

Một phần ngắn nhưng quan trọng. Không phải mọi thứ trong quy trình này đều tự động, và đó là chủ ý:

  • Chọn chủ đề ở cấp chiến lược. Lucas chọn từ khóa trong chủ đề, nhưng chủ đề do tôi quyết định, thường dựa vào ra mắt sản phẩm, trao đổi với khách hàng hoặc thay đổi roadmap.
  • Biên tập cuối cùng. Tôi đọc mọi bản nháp trước khi xuất bản. Đặc biệt là bản EN. Giọng văn, độ chính xác về kỹ thuật, liên hệ với bối cảnh sản phẩm đều cần con người kiểm tra.
  • Đánh giá bản địa cho ngôn ngữ tôi không thạo. Tôi không đọc tiếng Đức thành thạo. Bản nháp DE sẽ gửi cho người bản xứ duyệt lần cuối trước khi xuất bản.
  • Quảng bá. Đăng lên X, gửi cho subscriber, chia sẻ trong cộng đồng hiện vẫn làm thủ công.

Mục tiêu không phải loại bỏ tôi khỏi quy trình. Mà là loại bỏ tôi khỏi những phần không thực sự cần đến tôi.


Tôi đến với quy trình này như thế nào

Tôi không ngồi xuống một cuối tuần để thiết kế quy trình này. Nó tích lũy dần, từng bài một, từ việc nhận ra bước nào tốn thời gian nhất.

Điều tôi nhận ra: phần đáng tự động hóa không phải là phần sáng tạo. Đó là phần kết nối: lấy từ khóa, render ảnh bìa, upload, phân bản locale, định dạng URL preview. Khi tôi theo dõi kỹ, tôi dành nhiều thời gian cho logistics hơn là viết thực sự.

Vì vậy tôi dần chuyển logistics sang cho agent. Model lo phần viết; agent xử lý việc di chuyển dữ liệu. Tôi vẫn là người quyết định viết gì, viết thế nào, chỉ không còn phải ghép nối các phần thủ công nữa.

Với tôi, tự động hóa nội dung thực tế không phải là "AI viết blog." Mà là "AI làm mọi thứ quanh việc viết, để tôi có thời gian thực sự đọc lại bài viết."


Nếu bạn muốn thử điều tương tự

Nếu bạn cũng đang đội nhiều mũ, trong đó có nội dung, phần lớn quy trình này có thể tái tạo:

  • Một nền tảng agent cho phép bạn gán vai trò và kỹ năng cố định cho agent (chúng tôi dùng Zero, nơi Lucas hoạt động).
  • Connector đến các công cụ bạn đang dùng: CMS, công cụ nghiên cứu từ khóa, trình tạo ảnh, Slack.
  • Một bộ kỹ năng nhỏ phù hợp thương hiệu (trường hợp của chúng tôi là draw cho ảnh bìa và copywriting cho giọng văn).
  • Hướng dẫn mặc định mang theo ngữ cảnh, để prompt luôn ngắn gọn.

Bắt đầu workspace Zero miễn phí →

Hoặc nếu bạn muốn xem thêm các quy trình agent trước khi đăng ký, thư viện use case của chúng tôi có 19 quy trình tự động hóa sẵn sàng cho kỹ thuật, sản phẩm, marketing và vận hành.

Nếu bạn muốn clone Lucas: tạo một agent, gán vai trò Marketing manager, kết nối Strapi (hoặc CMS của bạn) + Ahrefs + công cụ tạo ảnh, thêm kỹ năng draw dựa trên của bạn, và kỹ năng copywriting ghi lại giọng thương hiệu. Lucas sẽ tự xử lý phần còn lại từ prompt đầu tiên.

Stay in the loop

// Get the latest insights on AI teammates and collaboration.