# Viết PRD trước khi build app bằng AI

[Jordan Urbs](https://homus.dev/speakers/jordan-urbs) · [Jordan Urbs](https://homus.dev/orgs/jordan-urbs)

> Cách nhờ Claude viết một PRD có tech stack, feature và database schema, rồi đưa cùng PRD đó cho Bolt và Claude Code build và deploy một blog Astro.

Topics: Product Spec, Coding Agents, Workflow

Canonical: https://homus.dev/talks/build-better-apps-with-ai-using-this-one-simple-document-prd-guide

## 1. Vibe coding không có tài liệu thì sớm muộn cũng hỏng

Jordan mở đầu: vibe coding thì hay, cho tới lúc nó không còn hay nữa. Theo anh (video đăng ngày 28/06/2025), nếu bạn không có tài liệu để đưa cho AI co-pilot của mình, bạn sẽ rất vất vả, mọi thứ sẽ tệ đi, và có khi bạn chỉ muốn bỏ cuộc. Kiểu "ôi, có gì đó sai nghiêm trọng rồi". Anh nói chắc chắn bạn sẽ phải làm lại từ đầu ít nhất một lần.

Trong video này, anh muốn chỉ ra lời giải cho vấn đề rất nhiều người gặp này: đơn giản là tạo một product requirements document, gọi tắt là PRD. Theo Jordan (video đăng ngày 28/06/2025), đây là một quy trình đơn giản và không tốn nhiều thời gian. Bạn chỉ cần nghiên cứu một chút để chuẩn bị cho chính mình và cho AI về thứ bạn muốn build, và chỉ riêng việc đưa một PRD cho AI co-pilot thôi là kết quả đã tốt hơn rất nhiều.

![Chữ PRD lớn phủ lên màn hình Claude, góc trái là Jordan nói trước camera](https://homus.dev/photos/MZjW7mlRgdw-0023.jpg)

Chữ "PRD" hiện lớn trên màn hình Claude (bản Claude Sonnet 4 ở ô chọn model, video đăng ngày 28/06/2025), ngay trước khi Jordan bắt đầu viết prompt.

Anh nói (video đăng ngày 28/06/2025) chuyện này không phụ thuộc vào công cụ: dù bạn dùng Bolt, Lovable, Replit, Cursor, Claude Code hay một plugin nào đó của Visual Studio Code, cứ đưa PRD cho AI co-pilot là bạn sẽ có kết quả tốt hơn nhiều.

## 2. Mở Claude và câu đầu tiên của prompt PRD

Việc đầu tiên Jordan làm là mở Claude. Anh dùng Sonnet, vì theo anh (video đăng ngày 28/06/2025) Claude đơn giản là tốt hơn, anh thích tính cách của nó hơn. Anh nói bạn dùng gì cũng được, đây chỉ là thứ anh dùng.

Trong demo (video đăng ngày 28/06/2025), câu mở đầu của anh là: giúp tôi tạo một product requirements document. "Dễ thôi, đúng không?", anh nói. Tiếp theo là "đây là thứ chúng ta đang build". Anh tự hỏi mình sẽ build gì, rồi chọn: một blog chạy bằng Astro, SEO friendly (anh nói "SEO optimized", "search engine optimized", rồi "SEO friendly"), có thiết kế hiện đại, gọn gàng, với tông màu tối và sắc tím (purple undertone).

Đó là phần tổng quan cơ bản, thứ đầu tiên anh viết. Theo Jordan (video đăng ngày 28/06/2025), với anh đây thường là một quá trình tự nhiên: anh sẽ quay lại và chỉnh nó sau.

![Ô chat Claude với lời chào Good morning, Jordan và prompt PRD đang gõ dở, model Claude Sonnet 4](https://homus.dev/photos/MZjW7mlRgdw-0403.jpg)

Prompt PRD trong ô chat của Claude, model Claude Sonnet 4: phần tổng quan, tech stack và danh sách feature đã gõ xong, câu về AI co-pilot đang gõ dở (demo trong video đăng ngày 28/06/2025).

Phần đầu của prompt trên màn hình:

```
Help me create a Product Requirements Document. Here's what we're building:

An Astro-powered blog that is SEO friendly. It has a sleek, modern design, with a dark color scheme and a purple undertone.
```

## 3. Tech stack: Astro, Netlify và PocketBase

Điều tiếp theo anh nói với Claude là tech stack mà anh biết chắc sẽ dùng: Astro (cái này đã rõ), Netlify để deploy, và ban đầu anh nói Supabase cho backend. Rồi anh đổi ý: theo Jordan (video đăng ngày 28/06/2025), anh không thật sự khuyên dùng Supabase làm backend cho một blog, nên anh sẽ dùng PocketBase.

Theo Jordan (video đăng ngày 28/06/2025), PocketBase là một backend rất cơ bản và mã nguồn mở. Nó không có nhiều feature như Supabase, nhưng giữ mọi thứ gọn và dễ hơn. Anh nói nó có trên GitHub và cài đặt rất dễ; trang của nó là pocketbase.io. Nhưng anh nói chuyện đó không quan trọng lắm: điều anh muốn nói chỉ là anh muốn dùng PocketBase cho backend.

Đến đây Claude đã biết mình đang làm gì (demo trong video đăng ngày 28/06/2025). Tech stack là Astro, Netlify và PocketBase: cái này là framework, cái này để deploy, cái kia là backend. "Về cơ bản vậy là xong, đúng không?", anh nói.

Ba phần của tech stack trong prompt PRD, theo cách Jordan gọi từng phần trong video đăng ngày 28/06/2025: framework, deploy và backend; Supabase bị thay bằng PocketBase.

## 4. Danh sách feature và câu "không cần team milestone"

"Còn gì nữa?", anh hỏi, rồi viết: đây là những feature tôi muốn có. Một admin dashboard để tạo bài viết mới và user mới ("chắc là tôi muốn thêm user mới, đúng không?"). Một form đăng ký newsletter ở cuối trang. Archives. Tag, category và permalink chuẩn cho SEO. SEO metadata trên mỗi bài blog. "Chắc vậy là đủ, đúng không?"

Anh nói (video đăng ngày 28/06/2025) nếu bạn làm một directory thì cũng tương tự: một directory chạy bằng Astro, SEO friendly, thiết kế hiện đại gọn gàng, gì cũng được. Bạn có lẽ vẫn dùng Astro và Netlify; có thể vẫn dùng PocketBase, hoặc dùng Supabase cũng được. Rồi bạn liệt kê các feature muốn có. Theo Jordan (video đăng ngày 28/06/2025), đó gần như là toàn bộ những phần "đắt giá" bạn cần nói với Claude để nó làm PRD.

Điều cuối anh thích thêm vào là: tôi sẽ build cái này cùng một AI co-pilot, nên tôi không cần team milestone hay thứ gì kiểu vậy. Lý do, theo anh (video đăng ngày 28/06/2025): nó thích làm mọi thứ thật chuyên nghiệp, như thể bạn là một startup ở Silicon Valley làm việc đúng sách vở. "Nhưng chúng ta chỉ là những vibe coder nghiệp dư ở đây, nên muốn làm gì thì làm."

Và còn một câu cuối nữa: hãy hỏi tôi nếu có câu hỏi nào cần làm rõ, rồi tiếp tục viết PRD. Theo Jordan (video đăng ngày 28/06/2025), câu này cho bạn thêm một lớp kiểm tra: mình đã bỏ sót gì, mình cần biết gì.

Phần tiếp theo của prompt, trên màn hình và theo lời anh đọc:

```
The tech stack I know I will use is: Astro, Netlify for deployment, and Pocketbase for the backend.

These are the features I want to include:
• an admin dashboard for creating new posts and new users
• a newsletter subscription form at the bottom
• archives
• tags, categories and proper permalinks for SEO
• SEO metadata on each blog post

I will be building this with an AI co-pilot, so I don't need any team milestones or anything like that.
```

Câu cuối, theo lời anh: "Ask me if you have any questions for clarification and continue to write the PRD."

## 5. Bảo AI hỏi lại để làm rõ

Claude trả về vài câu hỏi, và có vẻ nó cũng đang viết PRD luôn. Theo Jordan (video đăng ngày 28/06/2025), đây là một điểm khác giữa Sonnet và, ví dụ, Gemini: Sonnet cứ thế làm. Nó có câu hỏi cho anh, nhưng vẫn làm trước, rồi sẽ sửa sau.

Anh nói (video đăng ngày 28/06/2025) các model như Gemini làm anh rất khó chịu, vì hai lý do. Một là nó muốn anh tự làm một đống việc, trong khi anh đang dùng AI co-pilot chính là để nó làm những việc đó. Hai là nó cứ hỏi "bạn có muốn tôi làm việc này cho bạn không?". Sonnet thì cứ làm luôn, và theo anh đó là lý do anh rất thích Claude.

Các câu hỏi của Claude trên màn hình (demo trong video đăng ngày 28/06/2025): admin dashboard có cần soạn thảo rich text (WYSIWYG) không, hay anh quen dùng markdown; khi nói "tạo user mới" thì đó là thêm admin, hay có các vai trò khác nhau (admin, editor, contributor); newsletter muốn tích hợp dịch vụ nào (Mailchimp, ConvertKit…) hay xử lý qua PocketBase; archive xếp theo ngày (tháng/năm), theo category hay cả hai; có ý tưởng design hoặc UI framework nào muốn dùng cùng tông tối/tím không; và có yêu cầu SEO nào ngoài metadata không (sitemap, robots.txt, schema markup).

![Claude hỏi sáu câu làm rõ, ô trả lời của Jordan liệt kê sáu đáp án; bên phải là bản PRD đang hình thành](https://homus.dev/photos/MZjW7mlRgdw-0603.jpg)

Jordan trả lời sáu câu của Claude bằng sáu dòng: Markdown is perfect; These are editors/contributors; ConvertKit; both; No; sitemap generation, schema markup, and robots. Bên phải, bản PRD đã có tới mục 10 "Assumptions and Constraints" (demo trong video đăng ngày 28/06/2025).

Anh trả lời từng câu: markdown là ổn; đây là editor và contributor. "Tốt, đây chính là phần làm rõ mà ta cần", anh nói. Theo Jordan (video đăng ngày 28/06/2025), đó là lý do khi học cách code bằng hội thoại (anh gọi là conversation-driven coding), ta cần thường xuyên hỏi "mọi thứ tôi nói có rõ không?", vì nếu không, nó sẽ cứ thế chạy và có lẽ sẽ không làm tốt.

Các câu còn lại: ConvertKit cho newsletter; archive theo cả hai cách; về design và UI framework thì không; về SEO thì sitemap generation, schema markup và robots. "Boom." Trong lúc anh trả lời, Claude đã tạo gần xong PRD, và giờ chỉ đang chỉnh vài chỗ (demo trong video đăng ngày 28/06/2025).

## 6. Đọc lướt bản PRD và ghi chú để sửa

Đợi Claude viết xong, Jordan cuộn nhanh qua bản PRD để chỉ những phần quan trọng nhất. Có executive summary với các mục tiêu. Có tech stack, và theo anh (demo trong video đăng ngày 28/06/2025) nó còn chi tiết hơn những gì anh đưa ban đầu: anh nói đó là lý do việc tạo PRD quan trọng đến vậy. Có architecture. Có các core feature, navigation, cách mọi thứ vận hành khi sắp xếp nội dung, với permalink, với SEO: robots, sitemap, schema markup, thẻ Twitter card. "Tuyệt."

Đến mục email capture với ConvertKit, anh thấy mình không thật sự cần ConvertKit API, chỉ cần form ID (theo Jordan, video đăng ngày 28/06/2025). Cách anh làm: hễ có ghi chú, anh viết ngay vào ô chat, rồi cuối cùng gửi cả danh sách để Claude sửa một lượt.

Tới mục tạo và quản lý bài viết cho admin dashboard, anh nói thật: nếu thật sự muốn làm một blog lúc này (video đăng ngày 28/06/2025), có lẽ anh không cần editor và contributor; nếu không thì anh đã dùng Ghost hay một nền tảng blog thật sự. "Nhưng build thì vui."

Tag, category, visual design, ổn. Có lẽ nên ghi rõ dùng font sans-serif hay serif; anh chọn: tôi muốn font serif. Page load speed, SEO requirements (demo trong video đăng ngày 28/06/2025).

![Ba ghi chú Jordan gửi cho Claude và bản PRD Astro Blog đang cập nhật](https://homus.dev/photos/MZjW7mlRgdw-0903.jpg)

Danh sách ghi chú Jordan gửi một lượt; bên phải là "Astro Blog - Product Requirements Document" đang được cập nhật, với mục Newsletter Subscription chỉ dùng form ID của ConvertKit, "No backend API integration required" (demo trong video đăng ngày 28/06/2025).

Danh sách ghi chú anh gửi, trên màn hình:

```
we do not actually need the ConvertKit API, just the form ID and convertkit takes care of it
I want a serif font
please mock up the database schema
```

## 7. Database schema: phần quan trọng nhất

"Đây là phần quan trọng nhất, các bạn ạ", Jordan nói về mục data models: đây là chỗ tạo ra database schema. Nhìn kỹ thì có vẻ Claude chưa làm database schema (demo trong video đăng ngày 28/06/2025), nên anh thêm vào danh sách ghi chú: hãy mock up database schema.

Theo Jordan (video đăng ngày 28/06/2025), database schema là cách để bạn giữ mọi thứ nhất quán. Nếu bạn chuyển từ Bolt sang Cursor hay bất cứ công cụ nào, bạn cần một nguồn sự thật duy nhất (single source of truth) để AI biết database hoạt động thế nào. Nếu không, nó chỉ dựng frontend theo kiểu đoán, rồi backend không khớp, và sửa chuyện đó thật sự rất mệt. "Có khi bạn đã gặp rồi. Tôi thì gặp rồi."

Anh lướt nốt phần còn lại: deployment requirements, ổn. Third-party integrations: không cần API, đã nói rồi; nhưng cần file `.env`, PocketBase, backup procedures, future enhancements. "Chưa quan trọng lắm lúc này" (video đăng ngày 28/06/2025). Rồi anh gửi danh sách ghi chú: không cần ConvertKit API, muốn font serif, hãy mock up database schema.

Giờ đã có một PRD kèm database schema. "Tôi nghĩ cái này thật sự quan trọng. Thật sự quan trọng", anh nói (video đăng ngày 28/06/2025). Theo anh, PRD của bạn có thể trông khác, tuỳ cách AI của bạn viết; điểm chính là ngay từ đầu bạn sẽ chưa tính ra được nhiều thứ, và nhiều chỗ bạn cũng không cần tính kỹ lúc này, nhưng bạn nên xem qua nó.

![PRD phiên bản 14 với bảng SQL post_categories cho quan hệ many-to-many giữa bài viết và category](https://homus.dev/photos/MZjW7mlRgdw-0943.jpg)

Bản PRD lên Version 14 sau loạt ghi chú: mục 7.6 "Post-Category Relations (Many-to-Many)" có câu lệnh SQL tạo bảng `post_categories` với hai foreign key tới bài viết và category, tiếp theo là mục 7.7 "Pocketbase Rules Configuration" (demo trong video đăng ngày 28/06/2025).

## 8. Hỏi lại chỗ chưa hiểu: quan hệ many-to-many

Ví dụ là phần user roles, và ở trên có phần quan hệ giữa bài viết và category. Theo Jordan (video đăng ngày 28/06/2025), nếu bạn không hiểu một chỗ nào, cứ hỏi: "cái này nghĩa là gì?". Đó là cách ta học trong lúc build.

Trong demo (video đăng ngày 28/06/2025), Claude giải thích vấn đề của quan hệ many-to-many trong bối cảnh category: một bài có thể thuộc nhiều category, một category chứa nhiều bài, và ta không thể đơn giản lưu vào database một bài viết kèm nhiều category, nên phải làm cả cơ chế many-to-many với một junction table. "Vậy đó."

![Claude giải thích Why We Can't Store This Simply với ví dụ categories lưu thành một chuỗi](https://homus.dev/photos/MZjW7mlRgdw-1003.jpg)

Câu trả lời của Claude: mục "Why We Can't Store This Simply" với ví dụ lưu `categories: "tech,web-dev,ai"` ngay trong bảng bài viết, và bốn vấn đề của cách đó: khó query, dữ liệu trùng lặp và thiếu nhất quán, không lưu được thông tin về quan hệ, lọc chậm (demo trong video đăng ngày 28/06/2025).

Theo anh (video đăng ngày 28/06/2025), trong lúc học như vậy, bạn có thể nghĩ: có lẽ mình không cần cái đó, hoặc có lẽ mình chưa hiểu cái đó. Và rồi bạn có thể tinh chỉnh PRD thêm nữa.

## 9. Đưa cùng một PRD cho Bolt và Claude Code

Jordan lưu PRD thành file markdown. Rồi, "cho vui", anh đưa nó vào cả Bolt lẫn Claude Code, thứ anh nói gần đây rất mê (video đăng ngày 28/06/2025), để xem bên nào làm tốt hơn và nhanh hơn.

Bên Bolt, anh đính kèm file PRD và gõ: "Build this blog, follow the specs in the PRD". Bên kia, anh đã mở sẵn folder của project PRD; Claude Code hỏi anh có tin các file trong folder này không, và anh chọn đồng ý (demo trong video đăng ngày 28/06/2025).

Sau đó anh bấm Shift-Tab để chuyển vòng qua các chế độ cho tới khi bật plan mode, rồi gõ: build the blog as specified in, kèm tên file PRD (trong cây thư mục sau này file mang tên `astro-blog-prd.md`; demo trong video đăng ngày 28/06/2025).

![Terminal Claude Code với lệnh Build the blog as specified in đang gõ và dòng plan mode on; bên trái là khung preview trống của Bolt](https://homus.dev/photos/MZjW7mlRgdw-1103.jpg)

Bên phải là Claude Code trong terminal: "Build the blog as specified in" đang gõ, bên dưới là "plan mode on (shift+tab to cycle)". Bên trái, khung preview của Bolt vẫn ghi "Your preview will appear here" (demo trong video đăng ngày 28/06/2025).

Theo Jordan (video đăng ngày 28/06/2025), Claude Code chạy hoàn toàn trong terminal.

## 10. Plan, to-do list và quyền chạy lệnh

Bên này, Claude, theo anh đoán (video đăng ngày 28/06/2025) có lẽ đang dùng Opus, lập xong toàn bộ plan rất nhanh. Anh cho chạy tiếp. Trong lúc đó Bolt cứ thế build; Jordan đọc câu mở đầu của Bolt: dựa trên PRD đầy đủ này, nó sẽ tạo một blog hiện đại chạy bằng Astro (demo trong video đăng ngày 28/06/2025).

Anh nói rõ điểm mấu chốt của demo: trong video này anh sẽ không tập trung nhiều vào phần tích hợp PocketBase, vì có thể mất thời gian, mà vào phần deploy. Theo Jordan (video đăng ngày 28/06/2025), nếu một trong hai bên deploy được Astro ngay từ đầu lên Netlify thì thật tuyệt, vì Astro hình như lúc nào cũng gây nhiều rắc rối. Anh kể Bolt tự nhận là tương thích với Astro, và anh từng deploy thành công lên Netlify, nhưng không phải không có vấn đề. Anh muốn xem Claude Code có làm được mà không gặp vấn đề gì không.

Anh chuyển qua lại giữa hai bên. Anh duyệt plan, và Claude Code có cả một danh sách việc cần làm; nó cập nhật to-do list trong lúc build (demo trong video đăng ngày 28/06/2025). Theo anh (video đăng ngày 28/06/2025), thỉnh thoảng nó sẽ hỏi bạn, giống như Cursor, nên bạn sẽ muốn cấp quyền cho nó chạy một số lệnh trong folder bạn đang build. Anh nói anh thích việc nó dùng một động từ ngẫu nhiên nào đó khi báo nó đang làm gì.

Cùng một PRD chạy song song trên hai làn trong demo (video đăng ngày 28/06/2025): Bolt build và deploy bằng một nút, còn bản Claude Code đi qua plan mode, to-do list, rồi lên GitHub để Netlify import.

Giờ Claude Code muốn tạo project Astro bằng script cài đặt qua Node; trên màn hình là lệnh `npm create astro@latest astro-blog -- --template blog --typescript strict --install`. Anh đồng ý cho chạy (demo trong video đăng ngày 28/06/2025). "Cũng sẽ thú vị khi xem bên nào nhanh hơn, nhỉ?" Anh hẹn quay lại sau ít phút.

## 11. Bolt build xong và deploy thẳng lên Netlify

Cả hai đã build xong. Jordan xem Bolt trước: một blog nhỏ, tông tím tối, và anh nói anh thích style của nó (demo trong video đăng ngày 28/06/2025). Anh bấm thử vào một mục: "Ồ, hình như nó chưa tạo bài viết. Không sao."

Điều quan trọng ở đây là xem nó deploy thế nào. Anh bấm Deploy, và theo anh (video đăng ngày 28/06/2025) Bolt deploy thẳng lên Netlify.

![Bản blog Bolt đã deploy với tiêu đề Insights & Innovation và ba bài Latest Posts](https://homus.dev/photos/MZjW7mlRgdw-1503.jpg)

Bản Bolt sau khi deploy lên Netlify: trang chủ "Insights & Innovation", menu Home, Categories, Tags, Archive, Admin, và ba thẻ bài viết mẫu (demo trong video đăng ngày 28/06/2025).

Bolt deploy xong. "Hay đấy." Anh chỉ ra (video đăng ngày 28/06/2025): vì dùng Astro với static site generation, ta có thể xem page source và thấy toàn bộ HTML thật; còn theo anh, ở một project Next.js thì bạn không thấy HTML vì tất cả được render phía client. Anh nói việc dùng static site generation ở đây hơi buồn cười, vì blog chưa có trang nào khác; có các trang category, và permalink trên thanh địa chỉ có cấu trúc tốt.

"Vậy Bolt, tôi phải nói là làm khá tốt, nhỉ?" (demo trong video đăng ngày 28/06/2025). Anh kiểm tra xem nó có làm admin panel không: có. "Wow. Nó làm được nhiều thật. Nhiều thứ chỉ với hai prompt", rồi tự sửa: ba, nếu tính cả lần deploy. Theo anh, đây là một cách khá thú vị và khá dễ để làm một blog.

## 12. Bản Claude Code: import vào Netlify và hỏi cấu hình

Trong lúc Bolt deploy, Jordan mở Netlify ở cửa sổ bên cạnh và chọn import một project có sẵn từ GitHub: đây là project của Claude Code. Anh đã tạo một repo mới và đẩy code lên; anh nhớ mang máng tên là PRD gì đó, rồi đặt tên project trên Netlify là PRD Claude Code. Theo anh (video đăng ngày 28/06/2025), chỗ này sẽ thú vị vì nó là Astro.

Để đỡ mất thời gian, anh hỏi thẳng Claude Code (demo trong video đăng ngày 28/06/2025). Câu hỏi trên màn hình:

```
on netlify, what is the base directory, build command, and publish directory for deployment?
```

Theo Jordan (video đăng ngày 28/06/2025), nếu bạn có một project Next.js thì thường mấy ô này tự điền đúng; nhưng không hiểu sao Astro lại khó hơn.

![Trang Build settings của Netlify với Base directory astro-blog, bên phải là câu trả lời của Claude Code về cấu hình Netlify](https://homus.dev/photos/MZjW7mlRgdw-1543.jpg)

Bên trái, ô Base directory trên Netlify đã điền `astro-blog`. Bên phải, Claude Code trả lời: Base Directory `astro-blog`, Build Command `npm run build`, Publish Directory `astro-blog/dist`, kèm một cấu hình thay thế và danh sách biến môi trường cần đặt (demo trong video đăng ngày 28/06/2025).

Anh xem phải điền gì. Trong demo (video đăng ngày 28/06/2025), anh chưa có biến môi trường nào, và anh mong chuyện đó không gây vấn đề lớn. Anh điền base directory và các ô còn lại theo câu trả lời, rồi nói "sao cũng được": anh sẽ không đặt biến môi trường nào cả, cứ xem chuyện gì xảy ra. Theo anh, Netlify sẽ báo nếu không build được vì thiếu biến môi trường, nhưng anh không nghĩ đó là vấn đề, trừ khi nó cần cái site URL.

## 13. Hai lần deploy thất bại

Jordan đọc tiếp câu trả lời của Claude Code trên màn hình: file `netlify.toml` ở root project đã có sẵn các thiết lập tối ưu cho header, caching và redirect, sẽ được áp dụng tự động khi deploy. "Hay đấy." Nhưng lần deploy thất bại (demo trong video đăng ngày 28/06/2025).

Lỗi là thiếu `package.json`. Anh tự hỏi có lẽ không phải thư mục astro-blog, rồi đổi theo cấu hình thay thế, đơn giản hơn: build command `npm run build`, publish directory là `dist`. Anh kiểm tra file netlify.toml nằm ở đâu: trong astro-blog. Mọi thứ đều nằm trong astro-blog, nên lẽ ra phải ổn. Deploy lại: vẫn thất bại (demo trong video đăng ngày 28/06/2025).

Anh nói anh không muốn đổ lỗi cho Claude Code ở đây, vì cấu trúc repo hơi lạ: folder PRD của anh là Git repo, còn astro-blog mới là thư mục thật sự để deploy, và theo Jordan (video đăng ngày 28/06/2025) cách sắp xếp đó thường gây vấn đề. Theo anh, tạo Git repo ngay bên trong astro-blog chắc chắn sẽ đơn giản hơn, nhưng đã đi tới đây rồi, và học thêm cách làm mới thì lúc nào cũng vui.

![Deploy log của Netlify với chẩn đoán thiếu react-router-dom, bên phải Claude Code sửa netlify.toml và đổi cách cài Tailwind](https://homus.dev/photos/MZjW7mlRgdw-1723.jpg)

Deploy log trên Netlify chẩn đoán lỗi build do thiếu dependency `react-router-dom`. Bên phải, Claude Code cập nhật `netlify.toml` (NODE_VERSION từ "18" lên "20") và xin chạy lệnh gỡ Tailwind v4 để dùng tích hợp Tailwind của Astro (demo trong video đăng ngày 28/06/2025).

Rồi anh nhận ra (demo trong video đăng ngày 28/06/2025) có vẻ lỗi chẳng liên quan gì tới cấu trúc folder: chỗ đó ổn cả, đây là lỗi dependency. "Vậy chắc Bolt thắng rồi."

## 14. Dời file về root và deploy lại

Theo Jordan (video đăng ngày 28/06/2025), một điều anh thích ở Claude Code là nó rất "agentic": nó chỉ xin phép khi dùng một số chức năng nhạy cảm trên máy, còn lại tự làm hết. Anh giải thích đó là vì chế độ auto-accept edits đang bật, và bạn có thể bấm Shift-Tab để chuyển chế độ nếu vì lý do nào đó không muốn vậy.

Anh quay về cửa sổ terminal kia, gõ `git add` rồi `git commit` với message "fix deploy", push lên GitHub, và Netlify tự động deploy lại. "Tiếc nhỉ" (demo trong video đăng ngày 28/06/2025).

Trong lúc đó Claude Code đang dời các file về root của repo: theo anh, đó mới là vấn đề. "Claude Code đang làm đúng cái tôi định tự làm bằng tay" (demo trong video đăng ngày 28/06/2025). Anh bấm mũi tên lên, gửi lại lệnh, rồi xem các lần deploy.

Anh nhận ra mình cần đổi cấu trúc thư mục trong thiết lập: base directory để trống, build command là `npm run build`, publish vẫn là `dist`. Thử lại: "Boom. Publish được rồi" (demo trong video đăng ngày 28/06/2025).

![Bản blog Claude Code đã deploy với tiêu đề Welcome to Astro Blog, bên phải Claude Code báo đã dời file về root](https://homus.dev/photos/MZjW7mlRgdw-1903.jpg)

Bản Claude Code đã lên Netlify: "Welcome to Astro Blog, A modern, SEO-optimized blog platform built with Astro". Bên phải, Claude Code tóm tắt cấu hình mới (Base Directory để trống, Build Command `npm run build`, Publish Directory `dist`) và những gì đã đổi: dời toàn bộ file từ `astro-blog/` về root repo, bỏ thư mục con gây xung đột Git submodule (demo trong video đăng ngày 28/06/2025).

## 15. Kết quả: Bolt thắng ván này

Anh mở bản Claude Code ra xem (demo trong video đăng ngày 28/06/2025): ở mức nào đó nó có dùng serif và sans-serif. Những trang đó thì chưa có, giống bên Bolt. Có permalink cho blog, category, tag. Nó không có nhiều trang bằng; trang About thì đã có.

![Hai bản blog đặt cạnh nhau: bản Bolt Insights & Innovation bên trái, bản Claude Code với trang Blog bên phải](https://homus.dev/photos/MZjW7mlRgdw-1943.jpg)

Hai bản đặt cạnh nhau: bên trái bản Bolt với "Insights & Innovation" và các thẻ Latest Posts, bên phải bản Claude Code với trang Blog và bài mẫu "Markdown Style Guide" (demo trong video đăng ngày 28/06/2025).

Theo Jordan (video đăng ngày 28/06/2025), nhìn chung thì chưa thể biết thật sự cho tới khi tích hợp database và test kỹ. Nhưng tổng thể, anh nói Bolt làm tốt hơn: Bolt làm được nhiều hơn trong thời gian ngắn hơn.

Dù vậy, anh có một linh cảm, "chỉ là linh cảm" mà hôm nay anh không có thời gian đi sâu: anh nghĩ phần database sẽ dễ implement hơn với Claude Code (video đăng ngày 28/06/2025).

Anh mong video hữu ích. Anh biết mục đích là làm một PRD, và video đã đi xa hơn thế một chút, nhưng anh mong nó mở mang thêm, và có thể khiến người xem thấy có cảm hứng, có động lực để thử Claude Code (video đăng ngày 28/06/2025).

## 16. Chi phí mỗi tháng và lời kết

Theo Jordan (video đăng ngày 28/06/2025), Claude Code thật sự rất tuyệt, và bạn còn tiết kiệm được tiền so với Cursor. Anh kể anh đang ngày càng rời xa Cursor: anh dùng một công cụ code khác chạy bằng API của Claude, và anh dùng Claude Code.

Anh nói (video đăng ngày 28/06/2025) có khi anh sẽ nâng lên Claude Max, "hay tên gì đó", mà anh nghĩ là 100 đô một tháng. Với Claude Code ở mức 20 đô một tháng anh đã làm được rất nhiều việc rồi, trong khi với Cursor thì anh bị lên tới khoảng 200, 250 đô một tháng. "Điên thật."

Ba mức chi phí mỗi tháng mà Jordan kể trong video đăng ngày 28/06/2025: Claude Code ở mức 20 đô, Claude Max mà anh nghĩ là 100 đô, và hoá đơn Cursor khoảng 200, 250 đô.

Nhưng như video này cho thấy, theo anh (video đăng ngày 28/06/2025), Bolt cũng có thể là một công cụ đáng giữ trong bộ công cụ của bạn.

Jordan tự nhận mình là một non-coder (theo lời anh trong video đăng ngày 28/06/2025). Anh cảm ơn mọi người đã xem.

## Nguồn và liên kết

- Tên gốc: Build Better Apps with AI Using This One Simple Document (PRD Guide)
- Sự kiện: [YouTube](https://homus.dev/events/youtube)
- Video gốc: [https://www.youtube.com/watch?v=MZjW7mlRgdw](https://www.youtube.com/watch?v=MZjW7mlRgdw)

- Kênh YouTube Jordan Urbs (Jordan Urbs): [youtube.com/channel/UCJpdOdMVkatTJ2Ue_tLqMpA](https://www.youtube.com/channel/UCJpdOdMVkatTJ2Ue_tLqMpA)

- PocketBase, backend mã nguồn mở Jordan chọn cho blog; trang chủ tự giới thiệu là "Open Source backend in 1 file" (đọc ngày 08/11/2026): [pocketbase.io](https://pocketbase.io)

- Astro, framework của blog trong demo (đọc ngày 08/11/2026): [astro.build](https://astro.build)

- Bolt, công cụ build app trên trình duyệt dùng trong phần so sánh (đọc ngày 08/11/2026): [bolt.new](https://bolt.new)

- Tài liệu Claude Code, phần Overview (đọc ngày 08/11/2026): [code.claude.com/docs/en/overview](https://code.claude.com/docs/en/overview)

- Netlify, nơi hai bản blog được deploy (đọc ngày 08/11/2026): [netlify.com](https://www.netlify.com)

Nguồn: https://homus.dev/talks/build-better-apps-with-ai-using-this-one-simple-document-prd-guide · cập nhật 2026-11-08
