v0 prompt to build a blog with a CMS
Instead of bolting on a headless CMS, this prompt has v0 build the CMS into the app: a markdown admin with live preview, draft and publish states, and public routes that revalidate on save. You end up with a complete blog you own end to end, no external service or webhook wiring.
Last updated
Build a blog with a self-hosted admin instead of an external CMS. Public side: an index at /blog listing posts newest first with title, one-line excerpt, and a date formatted on the server to avoid hydration mismatch, plus a detail route at /blog/[slug] rendering the post body from markdown with heading anchors and styled code blocks. Data model: a posts table in {{database}} with id, slug, title, excerpt, body_markdown, status (draft or published), and published_at. Admin side: /admin lists every post with a status Badge, and /admin/edit/[id] is a two-pane editor, markdown textarea on the left, live preview on the right, with save draft and publish buttons calling server actions. Slugs generate from the title on create, stay editable afterward, and a uniqueness check appends a suffix on collision rather than failing the save. Behaviors: draft posts return notFound() on the public route, publishing sets published_at once and never overwrites it on later edits, and revalidatePath runs for both the index and the post after any save so public pages update. Empty states: the public index with zero published posts shows a plain nothing published yet card, and the admin list shows a create your first post button. Error state: a failed save keeps the editor content intact and shows an error Toast, never a redirect that loses work. Styling: a readable measure near 65 characters, serif headings allowed, shadcn/ui confined to the admin. Acceptance: create, publish, and read a post end to end inside the v0 preview.Customize it
Runs in your browser. Nothing you type here is sent anywhere.
Build a blog with a self-hosted admin instead of an external CMS. Public side: an index at /blog listing posts newest first with title, one-line excerpt, and a date formatted on the server to avoid hydration mismatch, plus a detail route at /blog/[slug] rendering the post body from markdown with heading anchors and styled code blocks. Data model: a posts table in PostgreSQL with id, slug, title, excerpt, body_markdown, status (draft or published), and published_at. Admin side: /admin lists every post with a status Badge, and /admin/edit/[id] is a two-pane editor, markdown textarea on the left, live preview on the right, with save draft and publish buttons calling server actions. Slugs generate from the title on create, stay editable afterward, and a uniqueness check appends a suffix on collision rather than failing the save. Behaviors: draft posts return notFound() on the public route, publishing sets published_at once and never overwrites it on later edits, and revalidatePath runs for both the index and the post after any save so public pages update. Empty states: the public index with zero published posts shows a plain nothing published yet card, and the admin list shows a create your first post button. Error state: a failed save keeps the editor content intact and shows an error Toast, never a redirect that loses work. Styling: a readable measure near 65 characters, serif headings allowed, shadcn/ui confined to the admin. Acceptance: create, publish, and read a post end to end inside the v0 preview.
Same task in other tools
Questions about this prompt
Why build an admin instead of connecting a headless CMS?
Inside v0 the admin is just more generated UI, so it costs one prompt instead of API keys and webhook plumbing, and the draft, preview, and publish logic is server actions you can read. If you outgrow it, keep the public routes and swap the data layer.
How do I add tags or multiple authors?
Ask for them as follow-ups once the core flow works: a tags table with a join to posts and a filter row on /blog, or an authors table joined into the post header. Adding both at once tends to balloon the first generation.
I publish an edit but the public page shows stale content. What is wrong?
Revalidation was dropped somewhere. The prompt requires revalidatePath for both /blog and the post route after every save, so if edits stop propagating, ask v0 to confirm both calls exist in the save action rather than only one.