← back to Letsbegin
app/api/prd/clarify/route.ts
152 lines
import { NextRequest, NextResponse } from 'next/server'
import { logGemini } from '@/lib/cost-track'
// Gemini API configuration (FREE - no credits needed!)
const GEMINI_API_KEY = process.env.GEMINI_API_KEY
if (!GEMINI_API_KEY) {
throw new Error('GEMINI_API_KEY environment variable is required')
}
const GEMINI_ENDPOINT = 'https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent'
async function callGemini(prompt: string): Promise<string> {
const response = await fetch(`${GEMINI_ENDPOINT}?key=${GEMINI_API_KEY}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
contents: [{ parts: [{ text: prompt }] }],
generationConfig: { temperature: 0.7, maxOutputTokens: 2000 }
})
})
if (!response.ok) {
const error = await response.text()
throw new Error(`Gemini API error: ${error}`)
}
const data = await response.json()
logGemini(data, { note: 'prd-clarify' })
return data.candidates?.[0]?.content?.parts?.[0]?.text || ''
}
interface PRDInput {
projectName: string
featureTitle: string
problemStatement: string
targetUser: string
scope: string
priority: string
keyFeatures: string
nonGoals: string
successMetrics: string
components: string[]
integrations: string
techStack: string
additionalAnswers: string
projectPath?: string
}
const targetUserMap: Record<string, string> = {
'A': 'New users',
'B': 'Existing users',
'C': 'Admin users',
'D': 'All users'
}
const scopeMap: Record<string, string> = {
'A': 'Minimal viable implementation',
'B': 'Full-featured implementation',
'C': 'Backend/API only',
'D': 'Frontend/UI only'
}
const priorityMap: Record<string, string> = {
'A': 'Critical (ASAP)',
'B': 'High priority',
'C': 'Medium priority',
'D': 'Low priority (nice-to-have)'
}
interface ClarifyingQuestion {
id: string
question: string
options: { key: string; label: string }[]
}
export async function POST(request: NextRequest) {
try {
let input: PRDInput
try {
input = await request.json()
} catch {
return NextResponse.json({ error: 'Invalid JSON in request body' }, { status: 400 })
}
// Build context from the questionnaire
const context = `
Project: ${input.projectName}
Feature: ${input.featureTitle}
Problem: ${input.problemStatement}
Target User: ${targetUserMap[input.targetUser] || input.targetUser}
Scope: ${scopeMap[input.scope] || input.scope}
Priority: ${priorityMap[input.priority] || input.priority}
Key Features: ${input.keyFeatures || 'Not specified'}
Non-Goals: ${input.nonGoals || 'Not specified'}
Success Metrics: ${input.successMetrics || 'Not specified'}
Tech Stack: ${input.techStack || 'Not specified'}
Integrations: ${input.integrations || 'None'}
`
const prompt = `You are a PRD (Product Requirements Document) generation assistant. Based on the following feature information, generate 3-5 clarifying questions that would help create a more specific and actionable PRD.
${context}
Generate questions that:
1. Resolve ambiguities about the problem or solution
2. Clarify technical constraints or requirements
3. Identify edge cases or error handling needs
4. Determine success criteria specifics
5. Understand integration or dependency details
For each question, provide exactly 4 options (A, B, C, D) that represent different approaches or answers.
IMPORTANT: Return ONLY a JSON array with this exact structure:
[
{
"id": "q1",
"question": "How should the system handle users who...",
"options": [
{"key": "A", "label": "Option A description"},
{"key": "B", "label": "Option B description"},
{"key": "C", "label": "Option C description"},
{"key": "D", "label": "Option D description"}
]
}
]
Return ONLY the JSON array, no other text or explanation.`
const responseText = await callGemini(prompt)
// Parse the JSON response
let questions: ClarifyingQuestion[] = []
try {
// Try to find JSON array in the response
const jsonMatch = responseText.match(/\[[\s\S]*\]/)
if (jsonMatch) {
questions = JSON.parse(jsonMatch[0])
} else {
questions = JSON.parse(responseText)
}
} catch (parseErr) {
console.error('Failed to parse clarifying questions:', parseErr, 'Response:', responseText)
// Return empty array - will skip to generation
questions = []
}
return NextResponse.json({ questions, success: true })
} catch (error) {
console.error('Failed to generate clarifying questions:', error)
return NextResponse.json({ error: 'Failed to generate clarifying questions', questions: [] }, { status: 500 })
}
}