DEV Community

CarsonJ
CarsonJ

Posted on

How I Built an AI Prompt Generator with Next.js 15, Cloudflare Pages, and DeepSeek

How I Built an AI Prompt Generator with Next.js 15, Cloudflare Pages, and DeepSeek

Building AI tools in 2026 is easier than ever — but getting the architecture right takes some thought. Here's how I built a free AI Prompt Generator that supports 4 models, 6 languages, and handles rate limiting at scale.

The Problem

I wanted a prompt builder that:

  1. Works offline-first for basic prompt construction
  2. Uses AI only when explicitly requested (cost control)
  3. Supports multiple models with different field sets
  4. Handles rate limiting per IP without a database
  5. Deploys to a global CDN for free

Architecture Overview

Frontend: Next.js 15 Static Export

I used Next.js 15 with output: 'export' mode — this generates static HTML/CSS/JS that can be served from any CDN. The core prompt building is pure frontend:

interface PromptField {
  key: string;
  options: string[];
}

interface PromptModel {
  id: string;
  kind: 'image' | 'video';
  fields: PromptField[];
  join: (values: Record<string, string>, lang: 'en' | 'zh') => string;
}
Enter fullscreen mode Exit fullscreen mode

Each model has its own field configuration and join function that assembles the prompt. The join function takes the user's selected options and outputs either English or Chinese prompts based on a toggle.

Backend: Cloudflare Pages Functions

For the AI refinement, I used Cloudflare Pages Functions as my serverless backend. The key insight here is that Cloudflare Functions run at edge locations worldwide, so latency is minimal.

// functions/api/[[path]].ts
case '/api/prompt-refine': {
  const prompt = payload.prompt as string;
  const kind = (payload.kind as string) || 'image';
  const lang = (payload.lang as string) || 'en';

  const rateLimitResult = await checkRateLimit(env, request, 10);
  if (rateLimitResult.blocked) {
    return json({ error: 'RATE_LIMIT', message: rateLimitResult.message }, 429);
  }

  const content = await callDeepseek(env, systemPrompt, userPrompt, true);
  // ...
}
Enter fullscreen mode Exit fullscreen mode

Rate Limiting: D1 Database

For rate limiting, I used Cloudflare D1 (a SQLite-compatible serverless database). Each IP gets a counter keyed by ${ip}:${day}. No Redis needed — D1 is fast enough for this use case.

async function checkRateLimit(env, request, limit) {
  const ip = request.headers.get('CF-Connecting-IP');
  const day = new Date().toISOString().split('T')[0];
  const key = `${ip}:${day}`;

  const { results } = await env.DB.prepare(
    'SELECT count FROM ai_usage WHERE key = ?'
  ).bind(key).run();

  // ... increment and check
}
Enter fullscreen mode Exit fullscreen mode

AI Integration: DeepSeek API

I chose DeepSeek for its JSON response mode — no parsing markdown or extracting text from code blocks. The system prompt instructs the AI to return valid JSON only:

Top comments (0)