0
Revalidation
Mutasyonlardan sonra değişiklikleri yansıtacak şekilde önbelleğe alınan verileri yeniden doğrulayın:
yazan kuscubasiece·8 Eylül 2026
Kaynak: davepoon/claude-code-subagents-collection · MIT
Mutasyonlardan sonra değişiklikleri yansıtacak şekilde önbelleğe alınan verileri yeniden doğrulayın:
Kaynak: davepoon/claude-code-subagents-collection · MIT
mkdir -p .claude/skills/revalidation && curl -sL https://www.antrophiclove.com/api/kaynak/revalidation/raw -o .claude/skills/revalidation/SKILL.mdHedef dosya: .claude/skills/revalidation/SKILL.md
After mutations, revalidate cached data to reflect changes:
revalidatePath() - Invalidate specific routesrevalidateTag() - Invalidate by cache tag// actions/posts.ts
'use server'
import { revalidatePath } from 'next/cache'
export async function createPost(formData: FormData) {
const post = await db.post.create({
data: {
title: formData.get('title') as string,
content: formData.get('content') as string,
},
})
// Revalidate the posts list page
revalidatePath('/posts')
}
// Revalidate a specific page
revalidatePath('/posts')
// Revalidate a dynamic route
revalidatePath('/posts/[slug]', 'page')
// Revalidate a layout (and all pages using it)
revalidatePath('/posts', 'layout')
// Revalidate everything
revalidatePath('/', 'layout')
// actions/update-post.ts
'use server'
import { revalidatePath } from 'next/cache'
export async function updatePost(id: string, formData: FormData) {
const post = await db.post.update({
where: { id },
data: {
title: formData.get('title') as string,
content: formData.get('content') as string,
},
})
// Revalidate both the list and detail pages
revalidatePath('/posts')
revalidatePath(`/posts/${post.slug}`)
}
// actions/category.ts
'use server'
import { revalidatePath } from 'next/cache'
export async function updateCategory(categorySlug: string, formData: FormData) {
await db.category.update({
where: { slug: categorySlug },
data: { name: formData.get('name') as string },
})
// Revalidate the specific category page
revalidatePath(`/categories/${categorySlug}`)
// Also revalidate all product pages in this category
revalidatePath('/products/[...slug]', 'page')
}
// lib/data.ts
export async function getPosts() {
const res = await fetch('https://api.example.com/posts', {
next: { tags: ['posts'] },
})
return res.json()
}
export async function getPost(id: string) {
const res = await fetch(`https://api.example.com/posts/${id}`, {
next: { tags: ['posts', `post-${id}`] },
})
return res.json()
}
export async function getUser(id: string) {
const res = await fetch(`https://api.example.com/users/${id}`, {
next: { tags: ['users', `user-${id}`] },
})
return res.json()
}
// actions/posts.ts
'use server'
import { revalidateTag } from 'next/cache'
export async function createPost(formData: FormData) {
await db.post.create({
data: {
title: formData.get('title') as string,
},
})
// Invalidate all data tagged with 'posts'
revalidateTag('posts')
}
export async function updatePost(id: string, formData: FormData) {
await db.post.update({
where: { id },
data: { title: formData.get('title') as string },
})
// Invalidate just this specific post
revalidateTag(`post-${id}`)
}
export async function deletePost(id: string) {
await db.post.delete({ where: { id } })
// Invalidate both the specific post and the list
revalidateTag(`post-${id}`)
revalidateTag('posts')
}
// actions/user.ts
'use server'
import { revalidateTag } from 'next/cache'
export async function updateUserProfile(userId: string, formData: FormData) {
await db.user.update({
where: { id: userId },
data: {
name: formData.get('name') as string,
bio: formData.get('bio') as string,
},
})
// Revalidate user data
revalidateTag(`user-${userId}`)
// Also revalidate their posts (which show author info)
revalidateTag(`posts-by-${userId}`)
}
// actions/blog.ts
'use server'
import { revalidatePath, revalidateTag } from 'next/cache'
export async function publishPost(id: string) {
const post = await db.post.update({
where: { id },
data: { published: true },
})
// Revalidate cached API data by tag
revalidateTag('posts')
revalidateTag(`post-${id}`)
// Revalidate rendered pages by path
revalidatePath('/posts')
revalidatePath(`/posts/${post.slug}`)
revalidatePath('/') // Home page might show latest posts
}
// components/like-button.tsx
'use client'
import { useOptimistic, useTransition } from 'react'
import { likePost } from '@/actions/posts'
interface Props {
postId: string
initialLikes: number
isLiked: boolean
}
export function LikeButton({ postId, initialLikes, isLiked }: Props) {
const [isPending, startTransition] = useTransition()
const [optimisticState, addOptimistic] = useOptimistic(
{ likes: initialLikes, isLiked },
(state, _action) => ({
likes: state.isLiked ? state.likes - 1 : state.likes + 1,
isLiked: !state.isLiked,
})
)
const handleLike = () => {
startTransition(async () => {
addOptimistic(null)
await likePost(postId) // This will revalidate
})
}
return (
<button onClick={handleLike} disabled={isPending}>
{optimisticState.isLiked ? '❤️' : '🤍'} {optimisticState.likes}
</button>
)
}
// actions/posts.ts
'use server'
import { revalidateTag } from 'next/cache'
export async function likePost(postId: string) {
const userId = await getCurrentUserId()
await db.like.upsert({
where: {
userId_postId: { userId, postId },
},
create: { userId, postId },
update: {},
})
revalidateTag(`post-${postId}`)
}
// actions/comments.ts
'use server'
import { revalidateTag, revalidatePath } from 'next/cache'
export async function addComment(postId: string, formData: FormData) {
const comment = await db.comment.create({
data: {
postId,
content: formData.get('content') as string,
authorId: await getCurrentUserId(),
},
include: { post: true },
})
// Revalidate the specific post (comment count changed)
revalidateTag(`post-${postId}`)
// Revalidate comments for this post
revalidateTag(`comments-${postId}`)
// Revalidate the post page
revalidatePath(`/posts/${comment.post.slug}`)
// Revalidate "recent comments" widgets
revalidateTag('recent-comments')
}
// actions/posts.ts
'use server'
import { revalidatePath, revalidateTag } from 'next/cache'
export async function updatePost(id: string, formData: FormData) {
const wasPublished = await db.post.findUnique({
where: { id },
select: { published: true },
})
const post = await db.post.update({
where: { id },
data: {
title: formData.get('title') as string,
published: formData.get('published') === 'true',
},
})
// Always revalidate the specific post
revalidateTag(`post-${id}`)
revalidatePath(`/posts/${post.slug}`)
// Only revalidate the list if publish status changed
if (wasPublished?.published !== post.published) {
revalidateTag('posts')
revalidatePath('/posts')
revalidatePath('/') // Feed page
}
}
// app/api/revalidate/route.ts
import { NextRequest, NextResponse } from 'next/server'
import { revalidateTag, revalidatePath } from 'next/cache'
export async function POST(request: NextRequest) {
const secret = request.headers.get('x-revalidate-secret')
if (secret !== process.env.REVALIDATE_SECRET) {
return NextResponse.json({ error: 'Invalid secret' }, { status: 401 })
}
const body = await request.json()
if (body.tag) {
revalidateTag(body.tag)
}
if (body.path) {
revalidatePath(body.path)
}
return NextResponse.json({ revalidated: true, now: Date.now() })
}
// app/api/webhook/cms/route.ts
import { NextRequest, NextResponse } from 'next/server'
import { revalidateTag } from 'next/cache'
export async function POST(request: NextRequest) {
const signature = request.headers.get('x-webhook-signature')
const body = await request.json()
// Verify webhook signature
if (!verifyWebhookSignature(signature, body)) {
return NextResponse.json({ error: 'Invalid signature' }, { status: 401 })
}
const { event, data } = body
switch (event) {
case 'post.created':
case 'post.updated':
case 'post.deleted':
revalidateTag('posts')
revalidateTag(`post-${data.id}`)
break
case 'user.updated':
revalidateTag(`user-${data.id}`)
break
case 'cache.purge':
// Full cache purge
revalidateTag('all')
break
}
return NextResponse.json({ success: true })
}
// actions/debug.ts
'use server'
import { revalidatePath, revalidateTag } from 'next/cache'
export async function debugRevalidate(target: string, type: 'path' | 'tag') {
console.log(`Revalidating ${type}: ${target}`)
if (type === 'tag') {
revalidateTag(target)
} else {
revalidatePath(target)
}
console.log(`Revalidation complete at: ${new Date().toISOString()}`)
}