P PasteCode
Prompt

Prompt to Build a Next.js AI Tool Directory

AI agent prompt to build a searchable Next.js AI tool directory with MDX data files, category filters, and static generation.

CursorClaude CodeCodexWindsurf Next.jsTypeScriptTailwind
.md .json Difficulty: Medium Updated Jun 8, 2026

Give this prompt to your agent to build a statically generated, SEO-friendly directory of AI tools with category filtering, client-side search, and a detail page per tool — without it reaching for a database when flat MDX files are sufficient.

Main Prompt

Main Prompt
You are building a new Next.js 15 App Router project using TypeScript and Tailwind CSS v4.
Task: build an AI tool directory site.
Data model — each tool is a `.mdx` file in `src/data/tools/` with this frontmatter:
name, slug, tagline, description, category, website, pricing ('free'|'freemium'|'paid'),
tags (string[]), logo (relative path to public/).
Requirements:
- `src/lib/tools.ts`: read all MDX files at build time using `fs` + `gray-matter`; export
`getAllTools()` returning `Tool[]` and `getToolBySlug(slug)` returning `Tool | undefined`.
- `src/app/page.tsx`: static page showing a grid of `<ToolCard>` components.
- A `<CategoryFilter>` client component that filters by category using URL search params
(`?category=writing`). Use `useSearchParams` — no external state library.
- A `<SearchBar>` client component that does client-side substring match on name and tagline
using `useSearchParams` (`?q=cursor`).
- `src/app/tools/[slug]/page.tsx`: static detail page with `generateStaticParams` and
`generateMetadata`. Include og:title, og:description, og:image (the tool logo).
- `src/app/categories/[category]/page.tsx`: static list filtered by category.
- Seed data: create 5 real AI coding tools as MDX files (Cursor, GitHub Copilot, Claude Code,
Codeium, Tabnine) with accurate free/paid info.
- Do NOT use a database, Contentlayer, or next-mdx-remote. Use `gray-matter` + `fs` only.
Stop and list all planned files before writing code.

Implementation Notes

  • getAllTools() must only run server-side; calling it in a Client Component will expose fs to the browser and crash the build. Pass data as props to client components.
  • generateStaticParams for [slug] should call getAllTools() and map to { slug } objects.
  • For category pages, derive the category list from the tools data rather than hard-coding it.

Expected File Changes

src/lib/tools.ts (new)
src/app/page.tsx (new)
src/app/tools/[slug]/page.tsx (new)
src/app/categories/[category]/page.tsx (new)
src/components/ToolCard.tsx (new)
src/components/CategoryFilter.tsx (new — Client)
src/components/SearchBar.tsx (new — Client)
src/data/tools/cursor.mdx (new)
src/data/tools/github-copilot.mdx (new)
src/data/tools/claude-code.mdx (new)
src/data/tools/codeium.mdx (new)
src/data/tools/tabnine.mdx (new)

Acceptance Criteria

  • bun run build exits 0 and generates a static page for each tool slug.
  • Clicking a category filter updates the URL and filters the grid without a full reload.
  • Each tool detail page has unique og:title and og:description in the HTML <head>.
  • Searching for “cursor” shows only the Cursor card.

Test Commands

Terminal window
bun run typecheck
bun run build
bun run start
curl -s http://localhost:3000/tools/cursor | grep 'og:title'
# navigate to /?category=writing and confirm filter

Common AI Mistakes

  • Calling getAllTools() inside a Client Component, breaking the build with a fs module error.
  • Forgetting generateStaticParams on the [slug] page, causing 404s in static export.
  • Using next-mdx-remote when the prompt explicitly bans it.
  • Hard-coding the category list instead of deriving it from tool data.

Fix Prompt

Fix Prompt
The build fails because `fs` is used in a client component, or static pages are not generated.
Fix in order:
1. Move `getAllTools()` to a Server Component and pass the `tools` array as a prop to
`CategoryFilter` and `SearchBar`.
2. Add `export async function generateStaticParams()` to `src/app/tools/[slug]/page.tsx`.
3. Confirm `gray-matter` is installed: `bun add gray-matter`.
Show only the corrected diff.