|
| 1 | +import { revalidateTag } from 'next/cache'; |
| 2 | +import { NextRequest, NextResponse } from 'next/server'; |
| 3 | + |
| 4 | +type SanityWebhookPayload = { |
| 5 | + _type?: string; |
| 6 | + _id?: string; |
| 7 | +}; |
| 8 | + |
| 9 | +export async function POST(request: NextRequest) { |
| 10 | + const timestamp = new Date().toISOString(); |
| 11 | + console.log(`[${timestamp}] 🔔 Webhook received from Sanity`); |
| 12 | + |
| 13 | + // Validate secret token from env var |
| 14 | + const secret = request.nextUrl.searchParams.get('secret'); |
| 15 | + |
| 16 | + if (secret !== process.env.SANITY_REVALIDATE_SECRET) { |
| 17 | + console.log(`[${timestamp}] ❌ Invalid token provided`); |
| 18 | + return NextResponse.json({ message: 'Invalid token' }, { status: 401 }); |
| 19 | + } |
| 20 | + |
| 21 | + try { |
| 22 | + // Parse the webhook payload to determine what to revalidate |
| 23 | + const body = await request.json().catch(() => ({})) as SanityWebhookPayload; |
| 24 | + const { _type, _id } = body; |
| 25 | + |
| 26 | + console.log(`[${timestamp}] 📦 Content type: ${_type || 'unknown'}, ID: ${_id || 'unknown'}`); |
| 27 | + |
| 28 | + const revalidatedTags: string[] = []; |
| 29 | + |
| 30 | + // Revalidate based on content type |
| 31 | + // Note: In Next.js 16, revalidateTag requires a second argument (cache profile) |
| 32 | + // Using empty string for default behavior |
| 33 | + if (_type === 'project') { |
| 34 | + revalidateTag('projects', ''); |
| 35 | + revalidatedTags.push('projects'); |
| 36 | + } else if (_type === 'certification') { |
| 37 | + revalidateTag('certifications', ''); |
| 38 | + revalidatedTags.push('certifications'); |
| 39 | + } else if (_type === 'connectphoto') { |
| 40 | + revalidateTag('connectphoto', ''); |
| 41 | + revalidatedTags.push('connectphoto'); |
| 42 | + } else if (_type === 'experience') { |
| 43 | + revalidateTag('experience', ''); |
| 44 | + revalidatedTags.push('experience'); |
| 45 | + } else { |
| 46 | + // If no type specified or unknown type, revalidate everything |
| 47 | + console.log(`[${timestamp}] ⚠️ Unknown content type, revalidating all tags`); |
| 48 | + revalidateTag('projects', ''); |
| 49 | + revalidateTag('certifications', ''); |
| 50 | + revalidateTag('connectphoto', ''); |
| 51 | + revalidateTag('experience', ''); |
| 52 | + revalidatedTags.push('projects', 'certifications', 'connectphoto', 'experience'); |
| 53 | + } |
| 54 | + |
| 55 | + console.log(`[${timestamp}] ✅ Successfully revalidated tags: ${revalidatedTags.join(', ')}`); |
| 56 | + |
| 57 | + return NextResponse.json({ |
| 58 | + revalidated: true, |
| 59 | + tags: revalidatedTags, |
| 60 | + now: Date.now(), |
| 61 | + message: `Successfully revalidated tags: ${revalidatedTags.join(', ')}`, |
| 62 | + }); |
| 63 | + } catch (err) { |
| 64 | + console.error(`[${timestamp}] ❌ Error revalidating:`, err); |
| 65 | + return NextResponse.json( |
| 66 | + { message: 'Error revalidating', error: String(err) }, |
| 67 | + { status: 500 } |
| 68 | + ); |
| 69 | + } |
| 70 | +} |
0 commit comments