AI tools like Vercel's v0 and Claude Code can help you spin up projects faster than ever. But from my experience in vibe coding, I've learned they're not magic bullets—you still need to know what you're building, understand your data, the problems you are trying to solve, and the tech stack you are using to have good output. (And yes—you still need to know how to code.) Especially with these tools.
These tools are powerful, but they're also prone to hallucinations and mistakes. The better you understand your project's architecture and how these tools work, the more effective you'll be.
In this post, I'll share a high-level overview of my process. There's a lot to unpack, so I'll follow up with deeper dives and answer questions in future posts.
Let's get the SEO stuff out of the way. ( I promise I will be quick )
What is Vibe Coding?
Vibe coding is a chill, creative development session where you use AI tools to prototype and build applications in a flow state.
Instead of the traditional, step-by-step coding from scratch, you describe what you want in natural language and let the AI generate the code, guiding it iteratively.
The “vibe” comes from maintaining momentum and curiosity—trying things out quickly without getting bogged down in setup or syntax issues.
You might start with a blank project, turn on some music, and then feed prompts to an AI assistant to scaffold your app’s UI and functionality.
( I am going to go with this definition )
There's a new kind of coding I call "vibe coding", where you fully give in to the vibes, embrace exponentials, and forget that the code even exists. Andrej Karpathy
- AI-assisted coding: You use an AI tool (like Vercel v0 or similar) as a pair programmer. The AI can generate React components, pages, styles, and even connect to APIs based on your instructions.
- Rapid prototyping: The goal is to get a working prototype up and running quickly. It’s about turning ideas into working code in minutes or hours, not days, by letting the AI handle the heavy lifting of boilerplate code generation.
- Iterative exploration: You don’t necessarily have a fully specified end product from the start. Instead, you prompt the AI to build one piece at a time, refining and adding features in short cycles.
- This trial-and-error encourages experimentation and creativity.
- Human oversight: Importantly, vibe coding doesn’t mean the AI does everything perfectly. Think of it like working with a Jr. developer ( I mean a tool ), let's not demean JR developers here, we need them, otherwise who is going to become Sr. engineer.
- The AI can produce a lot of code quickly, but you need to review, test, and guide it.
As one developer put it, “It felt a lot like mentoring a very junior developer: you get raw productivity — but you also need to review and guide carefully.”
In other words, the human developer remains responsible for the final quality and correctness of the code. ( At least hope this is a standard )
What is v0: ( by Vercel ) A browser-based AI tool that rapidly generates front-end code and user interfaces using natural language or design files, built specifically for Next.js projects.
What is Claude Code: ( by Anthropic ) A terminal-based AI coding assistant that acts as an autonomous developer—able to read, write, debug, and execute code across your full-stack project, guided by you.
When coding with AI, your starting point and end goal should shape your entire approach.
Since we’ll keep this Strapi-specific, here are the first questions I ask before getting started:
- Do you already have a Strapi project?
- Do you already have a Next.js ( Frontend ) project?
- Are you starting completely from scratch?
On the way, we will cover some best practices and patterns that I discovered during this process.
But first—why did I choose V0 and Claude Code?
For me, it comes down to keeping a clear separation from my IDE. I want my workflow to be IDE-agnostic, adding a layer of separation that forces me to slow down and think more intentionally about what I'm building.
With Claude Code, I've adopted the agentic coding mindset, treating AI agents as independent contributors, much like a product manager working with a team of developers. This allows me to assign different tasks to multiple agents, enabling them to work in parallel on various parts of the codebase.
v0 is also a perfect fit for the kind of work I do—building with Next.js and shadcn/ui. It's fast, visually focused, and great for iterating on UI ideas.
On top of that, V0 offers an API, which I plan to explore for automating UI creation. And like Claude Code's terminal tabs, V0's multiple browser tabs make it easy to explore and refine multiple concepts in parallel.
This ability to work in parallel is already one of the biggest wins these tools bring to my development process.
If You Already Have a Strapi Project
If you already have a Strapi project and want to quickly build or prototype a frontend, here’s how I usually approach it.
I tend to work with Next.js and ShadCN UI (built on top of Tailwind), and for this kind of project my go-to tool is V0(https://v0.app.
We’ll start with a quick overview of the steps I follow, then go over some best practices, common pitfalls, and one critical warning:
Note: Never point your AI tools directly at your production database or server. Always use the dev environment.
It’s surprisingly easy to trigger thousands of API requests in seconds and accidentally DDoS yourself—or cause even bigger problems—if you’re not careful.
Of course, I knew better, and it was not something I did.
Steps:
- Make sure your Strapi API is accessible—locally or via a deployed environment.
I already had a test project that I deployed to Strapi Cloud.
- Retrieve and save an example JSON response from your API.
Having the response is a good way to guide the LLM to understand how your data is structure. This approach worked well for me.
- Use that JSON as context in your prompt to V0 infer correct types and data structure.
I went with "one shot" prompt approach, but way better, would of been to:
- Start with a small scope: have the AI generate a single page (e.g., Articles list) that fetches and displays your data.
- Once the basics work, incrementally add more pages and features.
Here is the prompt I used:
1You are a senior frontend developer experienced with TypeScript, React, Next.js, and building dynamic content-driven websites with Strapi as the backend.
2
3TASK: Build a mock frontend application in TypeScript that consumes the following API response (below under `<resource>`) and renders a blog platform.
4
5TECH: Use the following technologies
6- Next.js 15
7- Tailwind 4
8- ShadCN UI
9
10REQUIREMENTS:
11 - Create a blog listing page that displays all articles
12 - Each article should show the title, description, author, category, and cover image
13 - Include search functionality to filter articles by title or category - Implement pagination to support large datasets
14 - Create a single blog article page
15 - When a user clicks on a blog post, they are taken to a detailed view using the slug
16 - Render all associated blocks (rich-text, quotes, media, sliders) - Each block type should map to a dedicated React component
17 - Use an object map or a `switch` statement to select the correct component for each block
18 - The application should use clean TypeScript types and structure
19
20 CONSTRAINTS:
21 - Use the provided mock API data in `<resource>` to create the types and build all the appropriate componetns
22 - Afterwards use fetch to fetch the date from live url: https://inspired-duck-61a6601220.strapiapp.com/api/articles
23 - We are using Next.js App Router
24 - Design and layout is not important
25 — focus on functional logic and clean structure
26 - Follow best practices in separating concerns and component design
27
28 DELIVERABLE: Return a full working Blog website, with search and pagination features using TypeScript code example structured as follows:
29
30 1. Type definitions for the API data
31 2. Components for each block type
32 3. Blog listing component with search and pagination
33 4. Single blog article page that renders all content blocks dynamically
34 5. A simple mock API client to fetch the data
35
36 <resources>
37 Add Json data from your response. I omit it here to save space.
38 </resources>
Between the resources you can add your data structure, I added my output from my api here
This seemed to guide it really well. You will also notice that I asked the prompt to pull real data from my API. I like to live adventurously, but keep in mind that everything should be done in an environment you don't mind breaking.
Here you can see me starting the process.
Doing some simple tests and publishing.
And here I was able to publish the project to Vercel and our content is powered by Strapi on Strapi Cloud.
This is the typical flow I follow for quick iterations, you can even open multiple tabs, modify the prompt for each and run multiple instances, then pick the best one.
Why Start with Your Data
By retrieving and saving an example JSON response from your Strapi API before prompting v0, you give the AI concrete context about your data structure and types.
This:
- Helps v0 infer accurate TypeScript types
- Ensures components match your actual content model
- Reduces hallucinations and mismatched field usage
- Speeds up the iteration process by grounding the AI in real data
In terms of what is next? Typically, at this point, I would move the project to local dev and continue to build out features with Claude Code. But more on this later.
You can either run the project locally and paste your JSON data response into your prompt, or take a more adventurous route and deploy it to Strapi Cloud. That’s the approach I used, and the free tier works perfectly for this kind of project.
Note: If you choose the deployed project route, ensure you set up a proper rate limiter to prevent accidentally overwhelming your server.
In the future, I will make a separate blog post covering v0 specific overview, but for now, here is what you should keep in mind. You can also check out this edited video of my live session where I explored this.
Lessons learned
Vague Prompts Cause AI Hallucinations If you don’t tell the AI exactly what your API returns or what the UI should display, it will guess—and often get it wrong. In my case, v0 created a non-existent helper function.
Avoid it: Be explicit. Provide real data structures or example JSON so the AI can map code to actual fields. Detailed prompts lead to correct, type-safe components.
One-Shot Prompts Give Half-Baked Results Asking for an entire app in a single prompt resulted in a generic site, leaving much of the LLM's imagination unexplored. Although we used a one-shot prompt, we made it as detailed as possible. However, as best practice, I recommend breaking things down into steps.
Avoid it: Break the build into small, focused prompts. Start with a basic layout, then add features step-by-step (search, pagination, detail pages, etc.), testing each before moving on.
Uncontrolled Side Effects Can Overload Your API AI-generated code may introduce runaway loops or inefficient API calls—ours triggered 5,000 requests in a second.
Avoid it: Review API logic. Add dependency arrays, debounces, and rate-limits where needed. Monitor the network tab to catch excessive requests early.
General Prompting Best Practices for Vercel v0
When working with Vercel v0 or any AI coding assistant, the quality of the output depends heavily on the quality of your input.
Creating a good prompt is both an art and a science—often called prompt engineering. I'm not a big fan of that term, so I think of it simply as defining your requirements clearly.
After a lot of experimenting, here are the best practices I've found for writing prompts in v0:
1. Be Specific About the Role and Tech Stack
Begin by instructing the AI on the role it should assume and the technologies it should utilize.
Example:
"You are a senior front-end developer using Next.js 15 and TypeScript."
This gives v0 a clear perspective and ensures the output follows the conventions of your stack—such as TypeScript types and Next.js App Router patterns.
2. Clearly State the Task
Explain exactly what you want built.
Example:
"Task: Create a blog listing page that displays a list of articles."
If you're asking for a specific component or page, mention it directly so the AI knows the high-level goal from the start.
3. Provide Context and Data Structures
Give the AI the background it needs, including frameworks, libraries, and the shape of your data.
Example:
"The app uses Next.js App Router and the shadcn/UI component library."
Provide a sample API response or JSON schema so v0 understands the fields and their types.
This helps avoid hallucinations and allows v0 to generate TypeScript interfaces automatically, catching errors early.---
4. Enumerate Requirements and Features
List the features and elements you want.
Example:
- Show article title, short description, author name, and category.
- Include a search bar to filter by title or category.
- Add pagination (4 articles per page).
By listing requirements, you remove ambiguity and help the AI satisfy each one.
5. Specify Constraints or Boundaries
If there are limitations or best practices to follow, be explicit.
Example:
- Use only the provided API structure—no external API calls.
- Style with Tailwind CSS and shadcn/UI components.
- Do not use a client-side state management library; rely on React hooks.
Constraints keep the AI from straying off track.
6. Define Deliverables
For more complex tasks, specify exactly what you expect in the output.
Example:
"Deliverables: A fully typed Next.js page component for the blog listing, child components for article preview cards, an API utility for fetching articles, and a dynamic page route for article details."
This reinforces the expected structure and makes it easier for the AI to meet your needs.
To tie it all together, here's an example prompt template incorporating these elements (as one might use in Vercel v0, this is the pattern I used earlier):
1You are a senior frontend developer experienced with TypeScript, React, Next.js, and building dynamic content-driven websites with Strapi as the backend.
2
3TASK:
4
5REQUIREMENTS:
6 -
7 CONSTRAINTS:
8 -
9
10 DELIVERABLE: Return a full working TypeScript code example structured as follows:
11
12 1. Type definitions for the API data
13
14
15 <resources>
16 Add Json data from your response.
17 </resources>
By giving v0 such a structured prompt, we effectively handed it a blueprint to follow. As a rule of thumb, clear and structured prompts return more accurate and useful code.
If You Already Have a Next.js Project
If you already have a frontend project with mocked data, a Figma design, or want to explore how to structure your collection types in Strapi. In that case, you have a couple of options:
- Use Claude Code to discuss and plan how to organize your content.
- Try Strapi AI: Content Architect to help you design your content types directly.
Also checkout more detailed overview on Strapi's Content Modeling best practices here.
Depending on when you're reading this, Strapi AI: Content Architect may still be in beta (learn more here), or it might already be fully released.
Let me take you through a quick overview of how you can use it. In this flow, we will:
- Create a frontend prototype in v0.
- Use the created project to help us build out our strapi collection types
- Refine our v0 frontend project based on our data
- Publish our project.
For this example, we will keep it simple and build a simple landing page for an Influencer Managing Service using v0. We just covered it above, so why not get some extra practice? And I don't have a project handy.
Let's Create a frontend prototype in v0 We can put our best prompting practices to the test. Here is the prompt I am going to use.
1You are a senior frontend designer experienced with TypeScript, React, Next.js (App Router), Tailwind CSS, and shadcn/ui. You build accessible, beautiful, responsive, production-ready UIs with clean structure and strong typing.
2
3TASK
4Build a simple landing page for a future product that helps teams manage YouTube influencer partnerships with ease. The page must be driven by aStrapi-style `blocks` array and render each block with a dedicated React component selected via a component map.
5
6TECH & SETUP
7- Next.js (App Router) with TypeScript
8- Tailwind 4 CSS + shadcn/ui + lucide-react icons
9- No external API calls—
10- Accessibility, keyboard navigation, focus states
11- Basic SEO metadata for the landing page
12
13DATA MODEL (IMPORTANT)
14- Treat the landing page as a Strapi “single type” that returns a `blocks: Block[]` array.
15- Each block has a `__component` discriminator (e.g., `"section.hero"`, `"section.features"`).
16- Create TypeScript types for all block variants and a union type `Block`.
17- Use a component map or `switch` statement to select a block renderer.
18- Do not hardcode copy in components—read everything from the block props.
19
20REQUIREMENTS
211. Sections (rendered from `blocks`):
22 - `section.hero` — headline, subhead, bullets, primary CTA (“Join Waitlist”), optional secondary CTA link.
23 - `section.problem-solution` — two short lists: pain points vs. how we solve them.
24 - `section.features` — feature card grid (icon, title, description).
25 - `section.testimonials` — quotes with name/role.
26 - `section.cta` — bold final CTA band (“Join Waitlist”).
27 - `section.footer` — links and social.
28
292. Header / Nav
30 - Sticky header with logo (placeholder) and anchors to sections
31 - “Join Waitlist” CTA button that scrolls to the form
32
333. Waitlist Form (core)
34 - Inline form block used in hero and CTA band (same component)
35 - Fields: email (required)
36 - Validation: email required
37 - On submit: simulate success response show toast
38
394. **Code Structure**
40
41app/
42layout.tsx
43page.tsx
44globals.css
45components/
46blocks/
47Hero.tsx
48ProblemSolution.tsx
49Features.tsx
50Testimonials.tsx
51CTABand.tsx
52Footer.tsx
53WaitlistForm.tsx
54Header.tsx
55BlockRenderer.tsx
56
57- Use component map in `BlockRenderer.tsx` (no `any`).
58- Keep state local; no global state libraries.
59
605. Styling & UI
61- Mobile-first, clean spacing, readable typography
62- Use shadcn/ui: `Button`, `Card`, `Accordion`, `Input`, `Textarea`, `Select`, `Badge`, `Dialog` (if needed)
63- Design polish is a priority — ensure modern, cohesive visual hierarchy, balanced whitespace, and consistent component styling
64- Use Tailwind utilities to achieve a visually appealing and on-brand design without sacrificing performance
65- Maintain accessibility and responsive layout across devices
66
67CONSTRAINTS
68- Prioritize both functionality and high-quality visual design**; final output should feel like a polished marketing site ready for launch.
69- Assume routing is already set up (single page at `/`).
70- Visual presentation matters — focus on layout, color balance, typography, and spacing while keeping the code type-safe and modular.
71
72DELIVERABLE
73Return a full working TypeScript code example with:
741) Types for the blocks and shared data
752) Block components (one per `__component`)
763) `BlockRenderer` that dynamically renders the blocks
774) A landing page (`app/page.tsx`) that fetches from the mock client and renders all blocks
78
79ACCEPTANCE CRITERIA
80- Page renders all sections from `blocks` with type-safe props
81- “Join Waitlist” form validates, simulates submission, persists payload in `localStorage`, and shows success feedback
82- UI is cohesive, responsive, and visually appealing — consistent paddings, margins, typography, and colors applied across all sections
Yes, I know—it’s a pretty verbose prompt. But as we discussed earlier, if you’re one-shotting, you shouldn’t be vague.
This will generate your project, which we can take and download as a zip file.
I am going to show you the Strapi AI Architect in action, you can sign up for beta here.
I have the project running locally on my computer. In the content-builder
you will notice the new UI consisting of a few options and a chatbot window.
Now let's pull in our Next.js project we downloaded from v0.
Nice, now that we have our collections, you can review or update them, but I will keep it as is and add my data. Oh wait, I noticed that it did not add the image
field to our Hero section.
Now that this is done, I've added my data.
Now that our Strapi project is running locally, we want to retrieve its response data so we can use it in our prompt to update the v0 frontend. Alternatively, we could deploy the project and have v0 consume the API directly, as we saw earlier.
Here's what I did behind the scenes to keep this blog post concise:
- Deployed the local project to Strapi Cloud
- Used the Strapi CLI (yarn strapi transfer) to push local data to the Strapi Cloud instance
- Exposed the API so v0 could access it
Now that we have this. Let's prompt our v0 instance to update our code based on the example API response.
Update the code to use this mock response, which mimics an actual API call from our Strapi Cloud Account.
``` json
{
"data": {
"id": 4,
"documentId": "v119x6hbaoi4k3xs0h2bxrcx",
"createdAt": "2025-08-10T22:06:04.811Z",
"updatedAt": "2025-08-10T22:19:03.445Z",
"publishedAt": "2025-08-10T22:19:03.464Z",
"title": "YT Influencer Connect",
"description": "Find your next influencer partnership.",
"blocks": [
{
"__component": "section.hero",
"id": 3,
"headline": "Manage YouTube influencer partnerships with ease",
"subhead": "Purpose-built CRM for creator discovery, outreach, briefs, and performance—designed for YouTube.",
"showForm": true,
"bullets": [
{
"id": 19,
"value": "Find the right creators by niche and audience"
},
{
"id": 20,
"value": "Find the right creators by niche and audience"
},
{ "id": 21, "value": "Find the right creators by niche and audience" }
],
"secondaryCta": null,
"image": {
"id": 1,
"documentId": "atqbkx8g82t5zuhhxmu4fkvg",
"alternativeText": null,
"url": "/uploads/pexels_aperture_32942828_833b0879c7.jpg"
}
},
{
"__component": "section.problem-solution",
"id": 3,
"title": "From chaos to clarity",
"pains": [
{ "id": 22, "value": "Scattered spreadsheets and DMs" },
{ "id": 23, "value": "Missed follow-ups and unclear statuses" },
{ "id": 24, "value": "Difficulty measuring campaign ROI" }
],
"solutions": [
{
"id": 25,
"value": "One place for discovery, outreach, and briefs"
},
{ "id": 26, "value": "Automated reminders and clear pipelines" },
{ "id": 27, "value": "Performance tracking tailored for YouTube" }
]
},
{
"__component": "section.feature",
"id": 3,
"title": "Everything you need to collaborate at scale",
"items": [
{
"id": 7,
"icon": "Search",
"title": "Creator Discovery",
"description": "Filters by niche, region, audience size, and brand fit."
},
{
"id": 8,
"icon": "Handshake",
"title": "Outreach Tracking",
"description": "Centralized messages, statuses, and follow-ups."
},
{
"id": 9,
"icon": "Gauge",
"title": "Performance Analytics",
"description": "Views, CTR, conversions, and cost efficiency."
}
]
},
{
"__component": "section.testimonial",
"id": 3,
"title": "What teams say",
"items": [
{
"id": 7,
"quote": "We moved our entire YouTube program into CollabFlow and cut campaign setup time in half.",
"name": "Priya S.",
"role": "Head of Influencer Marketing"
},
{
"id": 8,
"quote": "Finally a tool that gets how YouTube partnerships really work. The briefs feature is gold.",
"name": "Alex W.",
"role": "Creator Partnerships Lead"
},
{
"id": 9,
"quote": "Our reporting is so much cleaner, and the team never misses a follow-up anymore.",
"name": "Sam K.",
"role": "Growth Manager"
}
]
},
{
"__component": "section.cta",
"id": 3,
"title": "Be first to try CollabFlow",
"subhead": "Join the waitlist and get early access invites.",
"showForm": true
},
{
"__component": "section.footer",
"id": 3,
"copyright": "CollabFlow. All rights reserved.",
"links": [
{ "id": 9, "label": "Why", "href": "/" },
{ "id": 10, "label": "Features", "href": "/" },
{ "id": 11, "label": "Testimonials", "href": "/" },
{ "id": 12, "label": " Join Waitlist", "href": "/" }
],
"social": [
{ "id": 7, "platform": "Twitter", "href": "https://x.com" },
{ "id": 8, "platform": "YouTube", "href": "https://youtube.com" },
{ "id": 9, "platform": "LinkedIn", "href": "https://linkedin.com" }
]
}
]
},
"meta": {}
}
And finally, let's run our final prompt to update our project to use the live API.
Update the code to use the live api, I added it to the ENV vars.
Base url: https://effortless-wisdom-14cb99a371.strapiapp.com
Path for landing page: /api/landing-page
I chose to break the process into multiple steps, although we could have done it in one, similar to our first example.
Afterward, I published my project from v0 and connected it to my Strapi Cloud instance to manage its content.
One thing to remember when working with AI tools is that you rarely reach the final result in just a few prompts. Some prompts might even break the app, requiring you to re-prompt to fix issues.
Once I have a solid concept in place, I shift my development flow to a local environment using VS Code and Claude to continue building on the project. This time around, I won't be doing it, but instead, I will walk you through how I set up Claude in a fresh Next.js and Strapi Project.
If You’re Starting From Scratch ( Or looking to take your prototype to next level )
If you haven’t used Claude Code yet, I highly recommend it. It’s been my go-to coding tool lately. I even ended up removing Cursor—not because it’s bad, but because I’ve decided I don’t want any AI directly inside my code editor.
But Paul… why on earth would you do that?
Well, here’s the thing: I don’t want to completely offload all my mental heavy lifting to a machine. I know some of you are thinking, “But hey, we have calculators—do you still do calculus in your head?” Sure, but I still know basic math, and I’d rather not forget it.
So here are my two big reasons:
I don’t want autocomplete interrupting my thought process. Let me finish—even if I’m wrong—then I can go argue with the AI about it later.
I’ve noticed I’ve started to forget the simplest programming things that I feel I should remember. I mean… what happens if the internet goes out?
With that out of the way, let’s jump in. Just like you, I’m still navigating this whole AI thing—it’s new territory, and best practices are evolving every day. People like to throw around terms like “MCPs,” but I recommend starting with the basics first.
We’ve already covered some general prompting best practices, but now let’s talk specifically about Claude.
I would also recommend saving this as reference, it is an article written by the Anthropic team.
Getting Started with Claude Code
Claude Code is a command-line tool that lets you work with Claude as an agentic coding assistant. Think of it as a developer buddy living right in your terminal—one that can read your code, run commands, create plans, write implementations, and even interact with GitHub or your favorite dev tools.
If you're new to Claude Code, I would like to start with a basic overview before diving into how I set up my Strapi and Next.js dev environment.
1. Install and Run Claude Code
I’m on macOS, but it should work on Linux, and I think it will also work on Windows. (Kidding, I do have Windows—how else would I play multiplayer games? Plus, if you’re a .NET developer, what else are you going to use?)
Follow the official installation instructions from claude.ai/code.
Once installed, run:
claude
2. Add a CLAUDE.md File
Your CLAUDE.md
is Claude’s “cheat sheet” for your project. It’s automatically read when you start a session and can include:
- Common bash commands (
npm run build
,npm run typecheck
) - Code style guidelines
- Testing instructions
- Workflow rules (branch naming, commit style)
- Special notes about your project setup
You can learn more here.
You can also add it by running claude init
in your project, or if claude is running, you can use the /init
command.
> /init // Initialize a new CLAUDE.md file with codebase documentation
Tip:
Keep it short, readable, and update it often. You can have:
- A root-level
CLAUDE.md
for all sessions - Folder-specific ones for monorepos
**Bonus: you can easily add Claude to VS Code From your IDE by running it from your IDE’s integrated terminal, and all features will be active.
Or from external terminals in Clade running the /ide
command in any external terminal to connect Claude Code to your IDE and activate all features.
3. Manage Permissions Claude will ask for permission before doing risky actions (editing files, running commands).
To avoid approving every safe action:
/permissions
Or edit/create:
1.claude/settings.json
Add commands you trust, like ls
, mkdir
, or git commit
.
⚠️ Never allow rm -rf
unless running inside a safe container.
You can learn more here
4. Give Claude More Tools Claude works best when it knows your environment:
- Custom scripts: Document them in
CLAUDE.md
- MCP servers: Add integrations like Puppeteer or Sentry
- GitHub CLI (
gh
): Lets Claude manage PRs, issues, and more
Use CLAUDE.md file for project-specific instructions and documenting custom scripts/commands that Claude should know about.
I mentioned the docs above, but will call out again, great resource: CLAUDE.md documentation: https://docs.anthropic.com/en/docs/claude-code/memory Settings and tools configuration: https://docs.anthropic.com/en/docs/claude-code/settings
Some More Additional Tips
a) Explore → Plan → Code → Commit
- Ask Claude to read files and understand the task.
- Have it make a plan (use “think hard” for deeper reasoning).
- Review the plan, then approve coding.
- Commit changes and open a PR.
b) Test-Driven Development (TDD)
- Ask Claude to write tests first.
- Run and confirm they fail.
- Commit the tests.
- Have Claude write code until tests pass.
- Commit the working implementation.
c) Code + Iterate with Screenshots
- Provide design mocks or screenshots.
- Let Claude implement and refine until it matches.
Use Slash Commands
Put reusable prompts in .claude/commands/
.
Example: Fix GitHub Issue
1Please analyze and fix the GitHub issue: $ARGUMENTS.
2Follow these steps:
3
41. Use `gh issue view` to read the issue
52. Search the codebase
63. Implement a fix
74. Run tests
85. Commit and push a PR
Run it like:
/project:fix-github-issue 42
Custom slash commands in .claude/commands/ are documented in the Claude Code documentation. This lets you create reusable workflows specific to your project.
You can learn more about slash commands here:
- Slash commands overview: https://docs.anthropic.com/en/docs/claude-code/slash-commands
- CLI reference: https://docs.anthropic.com/en/docs/claude-code/cli-reference
The example you showed is exactly how it works - you create markdown files in .claude/commands/ with your workflow templates, and then run them with /project:command-name arguments.
Explore Codebases with Q&A When joining a new project, just ask:
- “How does logging work?”
- “Where is the API endpoint for
/users
?” - “Why does function
foo()
do X?”
Claude will search the repo and explain.
Stay Safe with YOLO Mode by using VM/Container To let Claude run without asking for permission:
claude --dangerously-skip-permissions
✅ Do this only in a container or VM to protect your real system.
Keep Context Fresh
- Use
/clear
between tasks to avoid “context bloat” - Guide Claude early and correct often
- Provide specific instructions and relevant files
Level Up Over Time Once you’re comfortable:
- Add subagents for specialized tasks (e.g., test validation)
- Use parallel Claude sessions for multi-branch work
- Automate with headless mode for CI/CD or pre-commit hooks
Quick Reference
| Command | What it Does |
|---------|--------------|
| /permissions
| Manage allowed commands |
| /clear
| Reset session context |
| /init
| Create starter CLAUDE.md
|
| /project:fix-github-issue
| Run a saved workflow |
| claude --dangerously-skip-permissions
| Full autonomy (safe container only) |
Tip: Claude Code is most powerful when you treat it like a real teammate—share your project rules, give it tools, let it plan before coding, and review its work.
Setting Up Claude in a New Project
Now that we've covered Claude Code fundamentals, let's explore how to set up Claude for a new project using Strapi. This section will serve as a comprehensive guide to establish best practices from day one.
My goal is to help this demo repository evolve as I discover new best practices, eventually becoming a robust foundation for your Strapi and Next.js projects.
Create a Strapi Project
Let's start by creating a fresh Strapi project with proper configuration:
➜ vibecoding-blogpost-working git:(main) npx create-strapi-app@latest server
Strapi v5.23.4 🚀 Let's create your new project
🚀 Welcome to Strapi! Ready to bring your project to life?
Create a free account and get:
✨ 30 days of access to the Growth plan, which includes:
✅ Single Sign-On (SSO) login
✅ Content History
✅ Releases
? Please log in or sign up. Skip
? Do you want to use the default database (sqlite) ? No
? Choose your default database client sqlite
? Filename: .tmp/data.db
? Start with an example structure & data? No
? Start with Typescript? Yes
? Install dependencies with npm? Yes
? Initialize a git repository? Yes
? Participate in anonymous A/B testing (to improve Strapi)? No
Initialize Claude for Your Project
Once your Strapi application is ready, initialize Claude Code in your project directory:
claude
Run the initialization command:
/init
This creates a CLAUDE.md
file in your project root - a crucial document that provides context and guidance for future Claude interactions.
Enhance Your CLAUDE.md File
After creating the initial CLAUDE.md
file, enhance it using framework-specific documentation. For Strapi projects, I recommend referencing the Strapi Documentation llms.txt file to provide Claude with comprehensive context.
Here's the enhanced CLAUDE.md file I created for our Strapi project:
1# CLAUDE.md
2
3This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
5## Project Overview
6
7This is a Strapi v5.23.4 headless CMS server application built with TypeScript. It provides a backend API for content management with block-based content modeling capabilities.
8
9## Architecture
10
11### Core Structure
12
13- **Config Layer** (`config/`): Database, middleware, admin, and server configuration
14- **Application Layer** (`src/`): Main application entry point and lifecycle hooks
15- **API Layer** (`src/api/`): Content types, controllers, routes, and services (currently empty - will be populated as content types are created)
16- **Admin Layer** (`src/admin/`): Admin panel customizations
17- **Extensions** (`src/extensions/`): Plugin extensions and customizations
18
19### Key Configuration Files
20
21- `config/database.ts`: Database configuration (currently SQLite with better-sqlite3)
22- `config/server.ts`: Server configuration and port settings
23- `config/middlewares.ts`: Middleware stack configuration
24- `src/index.ts`: Application lifecycle hooks (register/bootstrap)
25
26## Development Commands
27
28### Core Development
29
30```bash
31npm run develop # Start development server with auto-reload
32npm run dev # Alias for develop
33npm run start # Start production server
34npm run build # Build admin panel
35```
36
37
38### Strapi CLI
39
40```bash
41npm run strapi # Access Strapi CLI directly
42npm run console # Open Strapi console
43npm run deploy # Deploy to Strapi Cloud
44```
45
46### Maintenance
47
48```bash
49npm run upgrade # Upgrade to latest Strapi version
50npm run upgrade:dry # Preview upgrade changes
51```
52
53## Environment Configuration
54
55The application uses environment variables defined in `.env`:
56
57- `HOST`: Server host (default: 0.0.0.0)
58- `PORT`: Server port (default: 1337)
59- `APP_KEYS`: Application encryption keys
60- `API_TOKEN_SALT`: API token salt
61- `ADMIN_JWT_SECRET`: Admin JWT secret
62- `TRANSFER_TOKEN_SALT`: Transfer token salt
63- `JWT_SECRET`: General JWT secret
64- `ENCRYPTION_KEY`: Encryption key
65
66Copy `.env.example` to `.env` and update values for local development.
67
68## TypeScript Configuration
69
70- **Target**: ES2019 with CommonJS modules
71- **Strict Mode**: Disabled (Strapi compatibility)
72- **Output**: `dist/` directory
73- **Excludes**: Admin files, tests, and plugins from server compilation
74
75## Content Type Development
76
77When creating new content types, they will be automatically scaffolded in:
78
79- `src/api/[content-type]/controllers/`
80- `src/api/[content-type]/routes/`
81- `src/api/[content-type]/services/`
82- `src/api/[content-type]/content-types/`
83
84Use the Strapi admin panel or CLI to generate content types rather than creating them manually.
85
86## Admin Panel
87
88Access the admin panel at `http://localhost:1337/admin` when running in development mode. Admin customizations go in `src/admin/`.
89
90## Strapi Documentation Reference
91
92When answering questions about Strapi features, architecture, or best practices, reference the official Strapi v5 documentation:
93
94### Core Documentation Areas
95
96- **Installation & Setup**: `https://docs.strapi.io/cms/installation`, `https://docs.strapi.io/cms/quick-start`
97- **Project Structure**: `https://docs.strapi.io/cms/project-structure`
98- **Configuration**: `https://docs.strapi.io/cms/configurations/database`, `https://docs.strapi.io/cms/configurations/server`, `https://docs.strapi.io/cms/configurations/environment`
99- **Backend Customization**: `https://docs.strapi.io/cms/backend-customization/controllers`, `https://docs.strapi.io/cms/backend-customization/services`, `https://docs.strapi.io/cms/backend-customization/routes`, `https://docs.strapi.io/cms/backend-customization/policies`, `https://docs.strapi.io/cms/backend-customization/middlewares`
100- **Content API**: `https://docs.strapi.io/cms/api/content-api`, `https://docs.strapi.io/cms/api/rest`, `https://docs.strapi.io/cms/api/document-service`
101- **Admin Panel**: `https://docs.strapi.io/cms/admin-panel-customization`, `https://docs.strapi.io/cms/features/admin-panel`
102- **Content Management**: `https://docs.strapi.io/cms/features/content-manager`, `https://docs.strapi.io/cms/features/content-type-builder`
103- **Plugin Development**: `https://docs.strapi.io/cms/plugins-development/developing-plugins`, `https://docs.strapi.io/cms/plugins-development/create-a-plugin`
104
105### Key Features Documentation
106
107- **Draft & Publish**: `https://docs.strapi.io/cms/features/draft-and-publish`
108- **Internationalization**: `https://docs.strapi.io/cms/features/internationalization`
109- **Role-Based Access Control**: `https://docs.strapi.io/cms/features/rbac`
110- **Users & Permissions**: `https://docs.strapi.io/cms/features/users-permissions`
111- **API Tokens**: `https://docs.strapi.io/cms/features/api-tokens`
112- **Media Library**: `https://docs.strapi.io/cms/features/media-library`
113- **Custom Fields**: `https://docs.strapi.io/cms/features/custom-fields`
114- **Review Workflows**: `https://docs.strapi.io/cms/features/review-workflows`
115- **Releases**: `https://docs.strapi.io/cms/features/releases`
116- **Content History**: `https://docs.strapi.io/cms/features/content-history`
117- **Audit Logs**: `https://docs.strapi.io/cms/features/audit-logs`
118
119### Cloud & Deployment
120
121- **Strapi Cloud**: `https://docs.strapi.io/cloud/getting-started/intro`, `https://docs.strapi.io/cloud/projects/overview`
122- **Deployment**: `https://docs.strapi.io/cms/deployment`, `https://docs.strapi.io/cloud/getting-started/deployment`
123- **CLI**: `https://docs.strapi.io/cms/cli`, `https://docs.strapi.io/cloud/cli/cloud-cli`
124
125### Development Topics
126
127- **TypeScript**: `https://docs.strapi.io/cms/typescript`, `https://docs.strapi.io/cms/typescript/development`
128- **Testing**: `https://docs.strapi.io/cms/testing`
129- **Database**: `https://docs.strapi.io/cms/configurations/database`, `https://docs.strapi.io/cms/database-migrations`
130- **Error Handling**: `https://docs.strapi.io/cms/error-handling`
131- **Webhooks**: `https://docs.strapi.io/cms/backend-customization/webhooks`
132- **CRON Jobs**: `https://docs.strapi.io/cms/configurations/cron`
133
134Use WebFetch tool to access specific documentation pages when providing detailed answers about Strapi features or best practices.
Testing the Enhanced Context
With our enhanced CLAUDE.md file in place, Claude now has access to comprehensive Strapi documentation and can provide detailed, framework-specific answers. Here's an example of how this improved context works:
> how to create cron job in strapi
⎿ ⧉ Selected 1 lines from README.md in Visual Studio Code
⏺ Fetch(https://docs.strapi.io/cms/configurations/cron)
⎿ Received 125.9KB (200 OK)
⏺ To create a CRON job in Strapi:
1. Enable CRON in Server Config
// config/server.ts
export default ({ env }) => ({
host: env('HOST', '0.0.0.0'),
port: env.int('PORT', 1337),
cron: {
enabled: true,
},
});
2. Create CRON Tasks File
// config/cron-tasks.ts
export default {
// Run every day at 2:30 AM
dailyCleanup: {
task: ({ strapi }) => {
console.log('Running daily cleanup...');
// Your task logic here
},
options: {
rule: '30 2 * * *',
tz: 'America/New_York', // Optional timezone
},
},
// Run every Monday at 1 AM
weeklyReport: {
task: async ({ strapi }) => {
// Generate weekly reports
const reports = await strapi.db.query('api::report.report').findMany();
console.log(`Generated ${reports.length} reports`);
},
options: {
rule: '0 1 * * 1',
},
},
// Run every 30 minutes
healthCheck: {
task: ({ strapi }) => {
console.log('Health check completed');
},
options: {
rule: '*/30 * * * *',
},
},
};
3. CRON Schedule Format
* * * * * *
│ │ │ │ │ │
│ │ │ │ │ └─ day of week (0-7, both 0 and 7 are Sunday)
│ │ │ │ └─── month (1-12)
│ │ │ └───── day of month (1-31)
│ │ └─────── hour (0-23)
│ └───────── minute (0-59)
└─────────── second (0-59, optional)
Common Examples:
- '0 0 * * *' - Daily at midnight
- '0 */6 * * *' - Every 6 hours
- '0 9 * * 1-5' - Weekdays at 9 AM
- '*/15 * * * *' - Every 15 minutes
4. Managing CRON Jobs Programmatically
// In your application code
// Add a job
strapi.cron.add('myJob', {
task: ({ strapi }) => {
console.log('Dynamic job executed');
},
options: {
rule: '0 * * * *', // Every hour
},
});
// Remove a job
strapi.cron.remove('myJob');
// List all jobs
console.log(strapi.cron.jobs);
CRON jobs in Strapi are perfect for automated tasks like data cleanup, report generation, sending notifications, or maintaining system health.
Best Practices for Claude To Keep In Mind
- Document Project Architecture: Include clear descriptions of your project structure, key files, and architectural decisions. This helps Claude understand your codebase organization.
- Specify Development Commands: List all relevant npm scripts, CLI commands, and development workflows. This enables Claude to suggest the correct commands for common tasks.
- Reference Official Documentation: Link to framework-specific documentation URLs. Claude can then fetch current information when providing detailed answers about framework features.
- Include Environment Configuration: Document your environment variables, configuration files, and setup requirements. This helps Claude understand deployment and development contexts.
- Define Code Conventions: Specify your TypeScript configuration, code style preferences, and architectural patterns. This ensures Claude follows your project's established conventions.
- Create Modular Documentation: Consider creating additional markdown files for complex patterns and examples, then reference them in your CLAUDE.md file. This keeps the main file focused while providing comprehensive context.
- Update Documentation Regularly: Keep your CLAUDE.md file current as your project evolves. Add new sections for additional technologies, update command references, and document new architectural decisions.
The CLAUDE.md file is your project's knowledge base for AI collaboration. A well-structured CLAUDE.md file transforms Claude from a generic assistant into a project-specific expert that understands your codebase, follows your conventions, and provides contextually relevant guidance.
Conclusion
AI-powered development tools like V0 and Claude Code are awesome, but they're not magic. It is important to keep in mind that these tools should help you amplify your knowledge—but not replace it. AI is just like any tool, you need to understand how to use it effectively. Even though it might seem like magic, you have to remind yourself, that it will only be as good as the instructions and context you give.
This space is evolving rapidly, and what works today might change six months from now.
I am going to continue to explore these tools and write about lessons learned from me experience building real-world projects.
In the meantime, start experimenting. Create project, set up proper documentation, and see what these tools can do. Just remember—the goal isn't to stop thinking, it's to think better and build faster.
Let me know your thoughts and feedback, I would love to here about it. You can find me @codingthirty on X, or stop on by Mon - Fri 12:30 pm CST for Strapi's open office hours on our Discord.
Paul
p.s: if you are interested on how SEO is changing due to LLMs, you may find this article interesting.