Skip to main content

AI Features

AI-powered description generation, category suggestions and SEO metadata — when to enable, how to budget, and where it pays back.

Why this matters

The biggest dropout point in any directory submission flow is the description field. Users paste a URL, type a name, then hit a blank textarea and bounce. AI-generated descriptions cut that drop-off by 40–60% in our observation: paste URL, click "Generate", review and edit the result. That's the difference between a directory that scales to 1,000 listings and one that stalls at 80.

The catch is cost: every generation is real money (fractions of a cent, but real). This page covers when AI features are worth enabling, how to keep costs predictable, and how to wire your own provider. If you operate an AI-tools directory specifically, this becomes a hard requirement — listing 200 tools means 200 hand-written descriptions or one prompt scaffold.

Off by default. When on, users get an ✨ Generate with AI button in the submit flow that pre-fills descriptions, tags, and SEO metadata from a URL.

Not required

AI is opt-in because it costs money per use (pennies, but still). Ship without it, turn it on if users are dropping off at the description step.

What AI does

Description generation

User enters project URL + name → click Generate with AI → the LLM fetches the page, extracts the value prop, writes a directory-style short description.

Category suggestions

Given the URL and description, the LLM picks which of your existing categories fit best. Saves users from scrolling a long category list.

SEO metadata

Auto-fills meta title and description for the project page.

Turning it on

1. Enable feature flag

config/features.config.ts
export const featuresConfig = {
  // ...
  ai: true,
};

2. Set env vars

.env.local
AI_PROVIDER=openai      # or 'anthropic'
AI_MODEL=gpt-4o-mini    # cheap and fast
AI_API_KEY=sk-...

See AI Config for provider setup and recommended models.

3. Restart the dev server

Under the hood

Built on the Vercel AI SDK with adapters for OpenAI and Anthropic. Central file: lib/ai.ts.

The API route is app/api/ai/generate/. Protected by the ai feature flag — returns 404 when off.

Cost guardrails

  • Each generation is ~300–500 tokens, so fractions of a cent per request
  • Rate-limit abuse with the general rate limiter in lib/rate-limit.ts
  • Consider caching generated descriptions keyed by URL

A real-world walkthrough: bulk-generating descriptions for 200 imported tools

You've imported 200 AI tools from a CSV scrape — names and URLs only, descriptions empty. Manually writing each takes ~5 minutes; AI generation takes 4 seconds and costs about $0.04 per tool with gpt-4o-mini. Total: $8 to fill the catalog vs ~17 hours of writing. Here's the script:

scripts/backfill-ai-descriptions.ts
import { db } from '@/lib/supabase/database';
import { generateDescription } from '@/lib/ai';
 
const projects = await db.findMany('apps', { description: '' });
 
for (const p of projects) {
  const description = await generateDescription({
    name: p.name,
    url: p.url,
  });
  await db.updateOne('apps', { id: p.id }, { description });
  // Polite pause to stay under rate limits
  await new Promise((r) => setTimeout(r, 500));
}

Run with pnpm tsx scripts/backfill-ai-descriptions.ts. Each call fetches the project URL, extracts the value prop, writes a directory-style 50–80 word description, and updates the row. Review a sample of 10–15 outputs before pushing to production — your prompt may need tuning for your niche.

Common pitfalls

  • Leaking the API key client-side. AI generation runs from the API route, never directly from the browser. The key lives in .env.local (server-side only). If you see an AI_API_KEY reference in client components, it'll leak into the JS bundle and someone will burn through your credits.
  • Skipping the rate limiter. A single user with a script can rapid-fire the generate endpoint and rack up $50 in credits in an hour. Apply the submission tier to /api/ai/generate (it's there by default — don't remove it).
  • Trusting raw output. AI sometimes generates content that misrepresents the project ("the only X tool with feature Y" when it isn't). Always pre-fill the field but require user review before submission. Mark AI-generated descriptions with a flag in the DB so you can audit if a niche regulator complains.
  • Caching by URL alone. Same URL, different time → different page content (especially for AI tools that update weekly). Cache by (url, content_hash) if you want long-lived caches; otherwise expire after 7 days.
  • Forgetting the cost cap. Set a monthly budget in your provider dashboard (OpenAI, Anthropic both support spend caps). Without it, a runaway loop in a custom integration can drain $500 before you notice.

FAQ

Which model should I pick — gpt-4o-mini or claude-haiku?

For directory descriptions, both produce nearly identical quality at similar cost. gpt-4o-mini is slightly cheaper per token; claude-haiku-4-5 is faster on long pages and tends to write more natural marketing-style copy. Start with gpt-4o-mini and switch if your niche needs more polish — the provider is a one-line config change.

Can I use a self-hosted LLM (Ollama, vLLM)?

Yes — set AI_PROVIDER=openai with a custom AI_BASE_URL pointing to your self-hosted endpoint (Ollama exposes an OpenAI-compatible API on :11434/v1). Quality of self-hosted 7B–13B models is noticeably worse for short marketing copy than the hosted commercial models, but it's free.

How do I handle non-English directories?

Pass the target language in the prompt context. lib/ai.ts accepts a language argument that's interpolated into the system prompt. For Spanish: generateDescription({ name, url, language: 'es' }). The model is multilingual; results are usable in Spanish, French, German, Portuguese and most major languages without extra config.

See also