[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M73157MN5E7622DMSRDF52AM":3,"skill-same:01M73157MN5E7622DMSRDF52AM":48},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":22,"frontMatter":23,"refName":24,"commitSha":25,"skillDirectory":26,"forksCount":27,"repositoryHtmlUrl":28,"repositoryHomepageUrl":29,"ownerHtmlUrl":30,"ownerBlogUrl":31,"ownerDescription":32,"updatedAt":33,"install":34,"resources":47},"01M73157MN5E7622DMSRDF52AM","cache-components",null,"Expert guidance for Next.js Cache Components and Partial Prerendering (PPR).\n\n**PROACTIVE ACTIVATION**: Use this skill automatically when working in Next.js projects that have `cacheComponents: true` in their next.config.ts\u002Fnext.config.js. When this config is detected, proactively apply Cache Components patterns and best practices to all React Server Component implementations.\n\n**DETECTION**: At the start of a session in a Next.js project, check for `cacheComponents: true` in next.config. If enabled, this skill's patterns should guide all component authoring, data fetching, and caching decisions.\n\n**USE CASES**: Implementing 'use cache' directive, configuring cache lifetimes with cacheLife(), tagging cached data with cacheTag(), invalidating caches with updateTag()\u002FrevalidateTag(), optimizing static vs dynamic content boundaries, debugging cache issues, and reviewing Cache Component implementations.","Horonomos-laps\u002FYana-AI","Horonomos-laps","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F355299122?v=4","01M76B3QPXE88ET2SQPDPVATZT"," Horonomos-laps","01M72ZQRJPCYPSSWT4D00VJR2A",13,"Apache-2.0","https:\u002F\u002Fgithub.com\u002FHoronomos-laps\u002FYana-AI\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fcache-components\u002FSKILL.md",[],[],"2026-11-11 15:11:14",false,"---\nname: cache-components\ndescription: |\n  Expert guidance for Next.js Cache Components and Partial Prerendering (PPR).\n\n  **PROACTIVE ACTIVATION**: Use this skill automatically when working in Next.js projects that have `cacheComponents: true` in their next.config.ts\u002Fnext.config.js. When this config is detected, proactively apply Cache Components patterns and best practices to all React Server Component implementations.\n\n  **DETECTION**: At the start of a session in a Next.js project, check for `cacheComponents: true` in next.config. If enabled, this skill's patterns should guide all component authoring, data fetching, and caching decisions.\n\n  **USE CASES**: Implementing 'use cache' directive, configuring cache lifetimes with cacheLife(), tagging cached data with cacheTag(), invalidating caches with updateTag()\u002FrevalidateTag(), optimizing static vs dynamic content boundaries, debugging cache issues, and reviewing Cache Component implementations.\n---\n\n# Next.js Cache Components\n\n> **Auto-activation**: This skill activates automatically in projects with `cacheComponents: true` in next.config.\n\n## Project Detection\n\nWhen starting work in a Next.js project, check if Cache Components are enabled:\n\n```bash\n# Check next.config.ts or next.config.js for cacheComponents\ngrep -r \"cacheComponents\" next.config.* 2>\u002Fdev\u002Fnull\n```\n\nIf `cacheComponents: true` is found, apply this skill's patterns proactively when:\n\n- Writing React Server Components\n- Implementing data fetching\n- Creating Server Actions with mutations\n- Optimizing page performance\n- Reviewing existing component code\n\nCache Components enable **Partial Prerendering (PPR)** - mixing static HTML shells with dynamic streaming content for optimal performance.\n\n## Philosophy: Code Over Configuration\n\nCache Components represents a shift from **segment configuration** to **compositional code**:\n\n| Before (Deprecated)                     | After (Cache Components)                  |\n| --------------------------------------- | ----------------------------------------- |\n| `export const revalidate = 3600`        | `cacheLife('hours')` inside `'use cache'` |\n| `export const dynamic = 'force-static'` | Use `'use cache'` and Suspense boundaries |\n| All-or-nothing static\u002Fdynamic           | Granular: static shell + cached + dynamic |\n\n**Key Principle**: Components co-locate their caching, not just their data. Next.js provides build-time feedback to guide you toward optimal patterns.\n\n## Core Concept\n\n```\n┌─────────────────────────────────────────────────────┐\n│                   Static Shell                       │\n│  (Sent immediately to browser)                       │\n│                                                      │\n│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  │\n│  │   Header    │  │  Cached     │  │  Suspense   │  │\n│  │  (static)   │  │  Content    │  │  Fallback   │  │\n│  └─────────────┘  └─────────────┘  └──────┬──────┘  │\n│                                           │         │\n│                                    ┌──────▼──────┐  │\n│                                    │  Dynamic    │  │\n│                                    │  (streams)  │  │\n│                                    └─────────────┘  │\n└─────────────────────────────────────────────────────┘\n```\n\n## Mental Model: The Caching Decision Tree\n\nWhen writing a React Server Component, ask these questions in order:\n\n```\n┌─────────────────────────────────────────────────────────┐\n│ Does this component fetch data or perform I\u002FO?          │\n└─────────────────────┬───────────────────────────────────┘\n                      │\n           ┌──────────▼──────────┐\n           │   YES               │ NO → Pure component, no action needed\n           └──────────┬──────────┘\n                      │\n    ┌─────────────────▼─────────────────┐\n    │ Does it depend on request context? │\n    │ (cookies, headers, searchParams)   │\n    └─────────────────┬─────────────────┘\n                      │\n         ┌────────────┴────────────┐\n         │                         │\n    ┌────▼────┐              ┌─────▼─────┐\n    │   YES   │              │    NO     │\n    └────┬────┘              └─────┬─────┘\n         │                         │\n         │                   ┌─────▼─────────────────┐\n         │                   │ Can this be cached?   │\n         │                   │ (same for all users?) │\n         │                   └─────┬─────────────────┘\n         │                         │\n         │              ┌──────────┴──────────┐\n         │              │                     │\n         │         ┌────▼────┐          ┌─────▼─────┐\n         │         │   YES   │          │    NO     │\n         │         └────┬────┘          └─────┬─────┘\n         │              │                     │\n         │              ▼                     │\n         │         'use cache'                │\n         │         + cacheTag()               │\n         │         + cacheLife()              │\n         │                                    │\n         └──────────────┬─────────────────────┘\n                        │\n                        ▼\n              Wrap in \u003CSuspense>\n              (dynamic streaming)\n```\n\n**Key insight**: The `'use cache'` directive is for data that's the _same across users_. User-specific data stays dynamic with Suspense.\n\n## Quick Start\n\n### Enable Cache Components\n\n```typescript\n\u002F\u002F next.config.ts\nimport type { NextConfig } from 'next'\n\nconst nextConfig: NextConfig = {\n  cacheComponents: true,\n}\n\nexport default nextConfig\n```\n\n### Basic Usage\n\n```tsx\n\u002F\u002F Cached component - output included in static shell\nasync function CachedPosts() {\n  'use cache'\n  const posts = await db.posts.findMany()\n  return \u003CPostList posts={posts} \u002F>\n}\n\n\u002F\u002F Page with static + cached + dynamic content\nexport default async function BlogPage() {\n  return (\n    \u003C>\n      \u003CHeader \u002F> {\u002F* Static *\u002F}\n      \u003CCachedPosts \u002F> {\u002F* Cached *\u002F}\n      \u003CSuspense fallback={\u003CSkeleton \u002F>}>\n        \u003CDynamicComments \u002F> {\u002F* Dynamic - streams *\u002F}\n      \u003C\u002FSuspense>\n    \u003C\u002F>\n  )\n}\n```\n\n## Core APIs\n\n### 1. `'use cache'` Directive\n\nMarks code as cacheable. Can be applied at three levels:\n\n```tsx\n\u002F\u002F File-level: All exports are cached\n'use cache'\nexport async function getData() {\n  \u002F* ... *\u002F\n}\nexport async function Component() {\n  \u002F* ... *\u002F\n}\n\n\u002F\u002F Component-level\nasync function UserCard({ id }: { id: string }) {\n  'use cache'\n  const user = await fetchUser(id)\n  return \u003CCard>{user.name}\u003C\u002FCard>\n}\n\n\u002F\u002F Function-level\nasync function fetchWithCache(url: string) {\n  'use cache'\n  return fetch(url).then((r) => r.json())\n}\n```\n\n**Important**: All cached functions must be `async`.\n\n### 2. `cacheLife()` - Control Cache Duration\n\n```tsx\nimport { cacheLife } from 'next\u002Fcache'\n\nasync function Posts() {\n  'use cache'\n  cacheLife('hours') \u002F\u002F Use a predefined profile\n\n  \u002F\u002F Or custom configuration:\n  cacheLife({\n    stale: 60, \u002F\u002F 1 min - client cache validity\n    revalidate: 3600, \u002F\u002F 1 hr - start background refresh\n    expire: 86400, \u002F\u002F 1 day - absolute expiration\n  })\n\n  return await db.posts.findMany()\n}\n```\n\n**Predefined profiles**: `'default'`, `'seconds'`, `'minutes'`, `'hours'`, `'days'`, `'weeks'`, `'max'`\n\n### 3. `cacheTag()` - Tag for Invalidation\n\n```tsx\nimport { cacheTag } from 'next\u002Fcache'\n\nasync function BlogPosts() {\n  'use cache'\n  cacheTag('posts')\n  cacheLife('days')\n\n  return await db.posts.findMany()\n}\n\nasync function UserProfile({ userId }: { userId: string }) {\n  'use cache'\n  cacheTag('users', `user-${userId}`) \u002F\u002F Multiple tags\n\n  return await db.users.findUnique({ where: { id: userId } })\n}\n```\n\n### 4. `updateTag()` - Immediate Invalidation\n\nFor **read-your-own-writes** semantics:\n\n```tsx\n'use server'\nimport { updateTag } from 'next\u002Fcache'\n\nexport async function createPost(formData: FormData) {\n  await db.posts.create({ data: formData })\n\n  updateTag('posts') \u002F\u002F Client immediately sees fresh data\n}\n```\n\n### 5. `revalidateTag()` - Background Revalidation\n\nFor stale-while-revalidate pattern:\n\n```tsx\n'use server'\nimport { revalidateTag } from 'next\u002Fcache'\n\nexport async function updatePost(id: string, data: FormData) {\n  await db.posts.update({ where: { id }, data })\n\n  revalidateTag('posts', 'max') \u002F\u002F Serve stale, refresh in background\n}\n```\n\n## When to Use Each Pattern\n\n| Content Type | API                 | Behavior                              |\n| ------------ | ------------------- | ------------------------------------- |\n| **Static**   | No directive        | Rendered at build time                |\n| **Cached**   | `'use cache'`       | Included in static shell, revalidates |\n| **Dynamic**  | Inside `\u003CSuspense>` | Streams at request time               |\n\n## Parameter Permutations & Subshells\n\n**Critical Concept**: With Cache Components, Next.js renders ALL permutations of provided parameters to create reusable subshells.\n\n```tsx\n\u002F\u002F app\u002Fproducts\u002F[category]\u002F[slug]\u002Fpage.tsx\nexport async function generateStaticParams() {\n  return [\n    { category: 'jackets', slug: 'classic-bomber' },\n    { category: 'jackets', slug: 'essential-windbreaker' },\n    { category: 'accessories', slug: 'thermal-fleece-gloves' },\n  ]\n}\n```\n\nNext.js renders these routes:\n\n```\n\u002Fproducts\u002Fjackets\u002Fclassic-bomber        ← Full params (complete page)\n\u002Fproducts\u002Fjackets\u002Fessential-windbreaker ← Full params (complete page)\n\u002Fproducts\u002Faccessories\u002Fthermal-fleece-gloves ← Full params (complete page)\n\u002Fproducts\u002Fjackets\u002F[slug]                ← Partial params (category subshell)\n\u002Fproducts\u002Faccessories\u002F[slug]            ← Partial params (category subshell)\n\u002Fproducts\u002F[category]\u002F[slug]             ← No params (fallback shell)\n```\n\n**Why this matters**: The category subshell (`\u002Fproducts\u002Fjackets\u002F[slug]`) can be reused for ANY jacket product, even ones not in `generateStaticParams`. Users navigating to an unlisted jacket get the cached category shell immediately, with product details streaming in.\n\n### `generateStaticParams` Requirements\n\nWith Cache Components enabled:\n\n1. **Must provide at least one parameter** - Empty arrays now cause build errors (prevents silent production failures)\n2. **Params prove static safety** - Providing params lets Next.js verify no dynamic APIs are called\n3. **Partial params create subshells** - Each unique permutation generates a reusable shell\n\n```tsx\n\u002F\u002F ❌ ERROR with Cache Components\nexport function generateStaticParams() {\n  return [] \u002F\u002F Build error: must provide at least one param\n}\n\n\u002F\u002F ✅ CORRECT: Provide real params\nexport async function generateStaticParams() {\n  const products = await getPopularProducts()\n  return products.map(({ category, slug }) => ({ category, slug }))\n}\n```\n\n## Cache Key = Arguments\n\nArguments become part of the cache key:\n\n```tsx\n\u002F\u002F Different userId = different cache entry\nasync function UserData({ userId }: { userId: string }) {\n  'use cache'\n  cacheTag(`user-${userId}`)\n\n  return await fetchUser(userId)\n}\n```\n\n## Build-Time Feedback\n\nCache Components provides early feedback during development. These build errors **guide you toward optimal patterns**:\n\n### Error: Dynamic data outside Suspense\n\n```\nError: Accessing cookies\u002Fheaders\u002FsearchParams outside a Suspense boundary\n```\n\n**Solution**: Wrap dynamic components in `\u003CSuspense>`:\n\n```tsx\n\u003CSuspense fallback={\u003CSkeleton \u002F>}>\n  \u003CComponentThatUsesCookies \u002F>\n\u003C\u002FSuspense>\n```\n\n### Error: Uncached data outside Suspense\n\n```\nError: Accessing uncached data outside Suspense\n```\n\n**Solution**: Either cache the data or wrap in Suspense:\n\n```tsx\n\u002F\u002F Option 1: Cache it\nasync function ProductData({ id }: { id: string }) {\n  'use cache'\n  return await db.products.findUnique({ where: { id } })\n}\n\n\u002F\u002F Option 2: Make it dynamic with Suspense\n;\u003CSuspense fallback={\u003CLoading \u002F>}>\n  \u003CDynamicProductData id={id} \u002F>\n\u003C\u002FSuspense>\n```\n\n### Error: Request data inside cache\n\n```\nError: Cannot access cookies\u002Fheaders inside 'use cache'\n```\n\n**Solution**: Extract runtime data outside cache boundary (see \"Handling Runtime Data\" above).\n\n## Additional Resources\n\n- For complete API reference, see [REFERENCE.md](REFERENCE.md)\n- For common patterns and recipes, see [PATTERNS.md](PATTERNS.md)\n- For debugging and troubleshooting, see [TROUBLESHOOTING.md](TROUBLESHOOTING.md)\n\n## Code Generation Guidelines\n\nWhen generating Cache Component code:\n\n1. **Always use `async`** - All cached functions must be async\n2. **Place `'use cache'` first** - Must be first statement in function body\n3. **Call `cacheLife()` early** - Should follow `'use cache'` directive\n4. **Tag meaningfully** - Use semantic tags that match your invalidation needs\n5. **Extract runtime data** - Move `cookies()`\u002F`headers()` outside cached scope\n6. **Wrap dynamic content** - Use `\u003CSuspense>` for non-cached async components\n\n---\n\n## Proactive Application (When Cache Components Enabled)\n\nWhen `cacheComponents: true` is detected in the project, **automatically apply these patterns**:\n\n### When Writing Data Fetching Components\n\nAsk yourself: \"Can this data be cached?\" If yes, add `'use cache'`:\n\n```tsx\n\u002F\u002F Before: Uncached fetch\nasync function ProductList() {\n  const products = await db.products.findMany()\n  return \u003CGrid products={products} \u002F>\n}\n\n\u002F\u002F After: With caching\nasync function ProductList() {\n  'use cache'\n  cacheTag('products')\n  cacheLife('hours')\n\n  const products = await db.products.findMany()\n  return \u003CGrid products={products} \u002F>\n}\n```\n\n### When Writing Server Actions\n\nAlways invalidate relevant caches after mutations:\n\n```tsx\n'use server'\nimport { updateTag } from 'next\u002Fcache'\n\nexport async function createProduct(data: FormData) {\n  await db.products.create({ data })\n  updateTag('products') \u002F\u002F Don't forget!\n}\n```\n\n### When Composing Pages\n\nStructure with static shell + cached content + dynamic streaming:\n\n```tsx\nexport default async function Page() {\n  return (\n    \u003C>\n      \u003CStaticHeader \u002F> {\u002F* No cache needed *\u002F}\n      \u003CCachedContent \u002F> {\u002F* 'use cache' *\u002F}\n      \u003CSuspense fallback={\u003CSkeleton \u002F>}>\n        \u003CDynamicUserContent \u002F> {\u002F* Streams at runtime *\u002F}\n      \u003C\u002FSuspense>\n    \u003C\u002F>\n  )\n}\n```\n\n### When Reviewing Code\n\nFlag these issues in Cache Components projects:\n\n- [ ] Data fetching without `'use cache'` where caching would benefit\n- [ ] Missing `cacheTag()` calls (makes invalidation impossible)\n- [ ] Missing `cacheLife()` (relies on defaults which may not be appropriate)\n- [ ] Server Actions without `updateTag()`\u002F`revalidateTag()` after mutations\n- [ ] `cookies()`\u002F`headers()` called inside `'use cache'` scope\n- [ ] Dynamic components without `\u003CSuspense>` boundaries\n- [ ] **DEPRECATED**: `export const revalidate` - replace with `cacheLife()` in `'use cache'`\n- [ ] **DEPRECATED**: `export const dynamic` - replace with Suspense + cache boundaries\n- [ ] Empty `generateStaticParams()` return - must provide at least one param\n","# Next.js Cache Components\n\n> **Auto-activation**: This skill activates automatically in projects with `cacheComponents: true` in next.config.\n\n## Project Detection\n\nWhen starting work in a Next.js project, check if Cache Components are enabled:\n\n```bash\n# Check next.config.ts or next.config.js for cacheComponents\ngrep -r \"cacheComponents\" next.config.* 2>\u002Fdev\u002Fnull\n```\n\nIf `cacheComponents: true` is found, apply this skill's patterns proactively when:\n\n- Writing React Server Components\n- Implementing data fetching\n- Creating Server Actions with mutations\n- Optimizing page performance\n- Reviewing existing component code\n\nCache Components enable **Partial Prerendering (PPR)** - mixing static HTML shells with dynamic streaming content for optimal performance.\n\n## Philosophy: Code Over Configuration\n\nCache Components represents a shift from **segment configuration** to **compositional code**:\n\n| Before (Deprecated)                     | After (Cache Components)                  |\n| --------------------------------------- | ----------------------------------------- |\n| `export const revalidate = 3600`        | `cacheLife('hours')` inside `'use cache'` |\n| `export const dynamic = 'force-static'` | Use `'use cache'` and Suspense boundaries |\n| All-or-nothing static\u002Fdynamic           | Granular: static shell + cached + dynamic |\n\n**Key Principle**: Components co-locate their caching, not just their data. Next.js provides build-time feedback to guide you toward optimal patterns.\n\n## Core Concept\n\n```\n┌─────────────────────────────────────────────────────┐\n│                   Static Shell                       │\n│  (Sent immediately to browser)                       │\n│                                                      │\n│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐  │\n│  │   Header    │  │  Cached     │  │  Suspense   │  │\n│  │  (static)   │  │  Content    │  │  Fallback   │  │\n│  └─────────────┘  └─────────────┘  └──────┬──────┘  │\n│                                           │         │\n│                                    ┌──────▼──────┐  │\n│                                    │  Dynamic    │  │\n│                                    │  (streams)  │  │\n│                                    └─────────────┘  │\n└─────────────────────────────────────────────────────┘\n```\n\n## Mental Model: The Caching Decision Tree\n\nWhen writing a React Server Component, ask these questions in order:\n\n```\n┌─────────────────────────────────────────────────────────┐\n│ Does this component fetch data or perform I\u002FO?          │\n└─────────────────────┬───────────────────────────────────┘\n                      │\n           ┌──────────▼──────────┐\n           │   YES               │ NO → Pure component, no action needed\n           └──────────┬──────────┘\n                      │\n    ┌─────────────────▼─────────────────┐\n    │ Does it depend on request context? │\n    │ (cookies, headers, searchParams)   │\n    └─────────────────┬─────────────────┘\n                      │\n         ┌────────────┴────────────┐\n         │                         │\n    ┌────▼────┐              ┌─────▼─────┐\n    │   YES   │              │    NO     │\n    └────┬────┘              └─────┬─────┘\n         │                         │\n         │                   ┌─────▼─────────────────┐\n         │                   │ Can this be cached?   │\n         │                   │ (same for all users?) │\n         │                   └─────┬─────────────────┘\n         │                         │\n         │              ┌──────────┴──────────┐\n         │              │                     │\n         │         ┌────▼────┐          ┌─────▼─────┐\n         │         │   YES   │          │    NO     │\n         │         └────┬────┘          └─────┬─────┘\n         │              │                     │\n         │              ▼                     │\n         │         'use cache'                │\n         │         + cacheTag()               │\n         │         + cacheLife()              │\n         │                                    │\n         └──────────────┬─────────────────────┘\n                        │\n                        ▼\n              Wrap in \u003CSuspense>\n              (dynamic streaming)\n```\n\n**Key insight**: The `'use cache'` directive is for data that's the _same across users_. User-specific data stays dynamic with Suspense.\n\n## Quick Start\n\n### Enable Cache Components\n\n```typescript\n\u002F\u002F next.config.ts\nimport type { NextConfig } from 'next'\n\nconst nextConfig: NextConfig = {\n  cacheComponents: true,\n}\n\nexport default nextConfig\n```\n\n### Basic Usage\n\n```tsx\n\u002F\u002F Cached component - output included in static shell\nasync function CachedPosts() {\n  'use cache'\n  const posts = await db.posts.findMany()\n  return \u003CPostList posts={posts} \u002F>\n}\n\n\u002F\u002F Page with static + cached + dynamic content\nexport default async function BlogPage() {\n  return (\n    \u003C>\n      \u003CHeader \u002F> {\u002F* Static *\u002F}\n      \u003CCachedPosts \u002F> {\u002F* Cached *\u002F}\n      \u003CSuspense fallback={\u003CSkeleton \u002F>}>\n        \u003CDynamicComments \u002F> {\u002F* Dynamic - streams *\u002F}\n      \u003C\u002FSuspense>\n    \u003C\u002F>\n  )\n}\n```\n\n## Core APIs\n\n### 1. `'use cache'` Directive\n\nMarks code as cacheable. Can be applied at three levels:\n\n```tsx\n\u002F\u002F File-level: All exports are cached\n'use cache'\nexport async function getData() {\n  \u002F* ... *\u002F\n}\nexport async function Component() {\n  \u002F* ... *\u002F\n}\n\n\u002F\u002F Component-level\nasync function UserCard({ id }: { id: string }) {\n  'use cache'\n  const user = await fetchUser(id)\n  return \u003CCard>{user.name}\u003C\u002FCard>\n}\n\n\u002F\u002F Function-level\nasync function fetchWithCache(url: string) {\n  'use cache'\n  return fetch(url).then((r) => r.json())\n}\n```\n\n**Important**: All cached functions must be `async`.\n\n### 2. `cacheLife()` - Control Cache Duration\n\n```tsx\nimport { cacheLife } from 'next\u002Fcache'\n\nasync function Posts() {\n  'use cache'\n  cacheLife('hours') \u002F\u002F Use a predefined profile\n\n  \u002F\u002F Or custom configuration:\n  cacheLife({\n    stale: 60, \u002F\u002F 1 min - client cache validity\n    revalidate: 3600, \u002F\u002F 1 hr - start background refresh\n    expire: 86400, \u002F\u002F 1 day - absolute expiration\n  })\n\n  return await db.posts.findMany()\n}\n```\n\n**Predefined profiles**: `'default'`, `'seconds'`, `'minutes'`, `'hours'`, `'days'`, `'weeks'`, `'max'`\n\n### 3. `cacheTag()` - Tag for Invalidation\n\n```tsx\nimport { cacheTag } from 'next\u002Fcache'\n\nasync function BlogPosts() {\n  'use cache'\n  cacheTag('posts')\n  cacheLife('days')\n\n  return await db.posts.findMany()\n}\n\nasync function UserProfile({ userId }: { userId: string }) {\n  'use cache'\n  cacheTag('users', `user-${userId}`) \u002F\u002F Multiple tags\n\n  return await db.users.findUnique({ where: { id: userId } })\n}\n```\n\n### 4. `updateTag()` - Immediate Invalidation\n\nFor **read-your-own-writes** semantics:\n\n```tsx\n'use server'\nimport { updateTag } from 'next\u002Fcache'\n\nexport async function createPost(formData: FormData) {\n  await db.posts.create({ data: formData })\n\n  updateTag('posts') \u002F\u002F Client immediately sees fresh data\n}\n```\n\n### 5. `revalidateTag()` - Background Revalidation\n\nFor stale-while-revalidate pattern:\n\n```tsx\n'use server'\nimport { revalidateTag } from 'next\u002Fcache'\n\nexport async function updatePost(id: string, data: FormData) {\n  await db.posts.update({ where: { id }, data })\n\n  revalidateTag('posts', 'max') \u002F\u002F Serve stale, refresh in background\n}\n```\n\n## When to Use Each Pattern\n\n| Content Type | API                 | Behavior                              |\n| ------------ | ------------------- | ------------------------------------- |\n| **Static**   | No directive        | Rendered at build time                |\n| **Cached**   | `'use cache'`       | Included in static shell, revalidates |\n| **Dynamic**  | Inside `\u003CSuspense>` | Streams at request time               |\n\n## Parameter Permutations & Subshells\n\n**Critical Concept**: With Cache Components, Next.js renders ALL permutations of provided parameters to create reusable subshells.\n\n```tsx\n\u002F\u002F app\u002Fproducts\u002F[category]\u002F[slug]\u002Fpage.tsx\nexport async function generateStaticParams() {\n  return [\n    { category: 'jackets', slug: 'classic-bomber' },\n    { category: 'jackets', slug: 'essential-windbreaker' },\n    { category: 'accessories', slug: 'thermal-fleece-gloves' },\n  ]\n}\n```\n\nNext.js renders these routes:\n\n```\n\u002Fproducts\u002Fjackets\u002Fclassic-bomber        ← Full params (complete page)\n\u002Fproducts\u002Fjackets\u002Fessential-windbreaker ← Full params (complete page)\n\u002Fproducts\u002Faccessories\u002Fthermal-fleece-gloves ← Full params (complete page)\n\u002Fproducts\u002Fjackets\u002F[slug]                ← Partial params (category subshell)\n\u002Fproducts\u002Faccessories\u002F[slug]            ← Partial params (category subshell)\n\u002Fproducts\u002F[category]\u002F[slug]             ← No params (fallback shell)\n```\n\n**Why this matters**: The category subshell (`\u002Fproducts\u002Fjackets\u002F[slug]`) can be reused for ANY jacket product, even ones not in `generateStaticParams`. Users navigating to an unlisted jacket get the cached category shell immediately, with product details streaming in.\n\n### `generateStaticParams` Requirements\n\nWith Cache Components enabled:\n\n1. **Must provide at least one parameter** - Empty arrays now cause build errors (prevents silent production failures)\n2. **Params prove static safety** - Providing params lets Next.js verify no dynamic APIs are called\n3. **Partial params create subshells** - Each unique permutation generates a reusable shell\n\n```tsx\n\u002F\u002F ❌ ERROR with Cache Components\nexport function generateStaticParams() {\n  return [] \u002F\u002F Build error: must provide at least one param\n}\n\n\u002F\u002F ✅ CORRECT: Provide real params\nexport async function generateStaticParams() {\n  const products = await getPopularProducts()\n  return products.map(({ category, slug }) => ({ category, slug }))\n}\n```\n\n## Cache Key = Arguments\n\nArguments become part of the cache key:\n\n```tsx\n\u002F\u002F Different userId = different cache entry\nasync function UserData({ userId }: { userId: string }) {\n  'use cache'\n  cacheTag(`user-${userId}`)\n\n  return await fetchUser(userId)\n}\n```\n\n## Build-Time Feedback\n\nCache Components provides early feedback during development. These build errors **guide you toward optimal patterns**:\n\n### Error: Dynamic data outside Suspense\n\n```\nError: Accessing cookies\u002Fheaders\u002FsearchParams outside a Suspense boundary\n```\n\n**Solution**: Wrap dynamic components in `\u003CSuspense>`:\n\n```tsx\n\u003CSuspense fallback={\u003CSkeleton \u002F>}>\n  \u003CComponentThatUsesCookies \u002F>\n\u003C\u002FSuspense>\n```\n\n### Error: Uncached data outside Suspense\n\n```\nError: Accessing uncached data outside Suspense\n```\n\n**Solution**: Either cache the data or wrap in Suspense:\n\n```tsx\n\u002F\u002F Option 1: Cache it\nasync function ProductData({ id }: { id: string }) {\n  'use cache'\n  return await db.products.findUnique({ where: { id } })\n}\n\n\u002F\u002F Option 2: Make it dynamic with Suspense\n;\u003CSuspense fallback={\u003CLoading \u002F>}>\n  \u003CDynamicProductData id={id} \u002F>\n\u003C\u002FSuspense>\n```\n\n### Error: Request data inside cache\n\n```\nError: Cannot access cookies\u002Fheaders inside 'use cache'\n```\n\n**Solution**: Extract runtime data outside cache boundary (see \"Handling Runtime Data\" above).\n\n## Additional Resources\n\n- For complete API reference, see [REFERENCE.md](REFERENCE.md)\n- For common patterns and recipes, see [PATTERNS.md](PATTERNS.md)\n- For debugging and troubleshooting, see [TROUBLESHOOTING.md](TROUBLESHOOTING.md)\n\n## Code Generation Guidelines\n\nWhen generating Cache Component code:\n\n1. **Always use `async`** - All cached functions must be async\n2. **Place `'use cache'` first** - Must be first statement in function body\n3. **Call `cacheLife()` early** - Should follow `'use cache'` directive\n4. **Tag meaningfully** - Use semantic tags that match your invalidation needs\n5. **Extract runtime data** - Move `cookies()`\u002F`headers()` outside cached scope\n6. **Wrap dynamic content** - Use `\u003CSuspense>` for non-cached async components\n\n---\n\n## Proactive Application (When Cache Components Enabled)\n\nWhen `cacheComponents: true` is detected in the project, **automatically apply these patterns**:\n\n### When Writing Data Fetching Components\n\nAsk yourself: \"Can this data be cached?\" If yes, add `'use cache'`:\n\n```tsx\n\u002F\u002F Before: Uncached fetch\nasync function ProductList() {\n  const products = await db.products.findMany()\n  return \u003CGrid products={products} \u002F>\n}\n\n\u002F\u002F After: With caching\nasync function ProductList() {\n  'use cache'\n  cacheTag('products')\n  cacheLife('hours')\n\n  const products = await db.products.findMany()\n  return \u003CGrid products={products} \u002F>\n}\n```\n\n### When Writing Server Actions\n\nAlways invalidate relevant caches after mutations:\n\n```tsx\n'use server'\nimport { updateTag } from 'next\u002Fcache'\n\nexport async function createProduct(data: FormData) {\n  await db.products.create({ data })\n  updateTag('products') \u002F\u002F Don't forget!\n}\n```\n\n### When Composing Pages\n\nStructure with static shell + cached content + dynamic streaming:\n\n```tsx\nexport default async function Page() {\n  return (\n    \u003C>\n      \u003CStaticHeader \u002F> {\u002F* No cache needed *\u002F}\n      \u003CCachedContent \u002F> {\u002F* 'use cache' *\u002F}\n      \u003CSuspense fallback={\u003CSkeleton \u002F>}>\n        \u003CDynamicUserContent \u002F> {\u002F* Streams at runtime *\u002F}\n      \u003C\u002FSuspense>\n    \u003C\u002F>\n  )\n}\n```\n\n### When Reviewing Code\n\nFlag these issues in Cache Components projects:\n\n- [ ] Data fetching without `'use cache'` where caching would benefit\n- [ ] Missing `cacheTag()` calls (makes invalidation impossible)\n- [ ] Missing `cacheLife()` (relies on defaults which may not be appropriate)\n- [ ] Server Actions without `updateTag()`\u002F`revalidateTag()` after mutations\n- [ ] `cookies()`\u002F`headers()` called inside `'use cache'` scope\n- [ ] Dynamic components without `\u003CSuspense>` boundaries\n- [ ] **DEPRECATED**: `export const revalidate` - replace with `cacheLife()` in `'use cache'`\n- [ ] **DEPRECATED**: `export const dynamic` - replace with Suspense + cache boundaries\n- [ ] Empty `generateStaticParams()` return - must provide at least one param\n",{"name":5,"description":7},"main","481dcd7dd2e288b9d627a2bd017db70e64e6c6fa",".claude\u002Fskills\u002Fcache-components",2,"https:\u002F\u002Fgithub.com\u002FHoronomos-laps\u002FYana-AI","https:\u002F\u002Fyana.vutam.link\u002F","https:\u002F\u002Fgithub.com\u002FHoronomos-laps","https:\u002F\u002Fyana.vutam.link","An open-source governed runtime & execution environment for multi-agent AI systems.","2026-11-14 13:24:09",{"source":8,"skillName":5,"commands":35,"prompt":45,"zipAvailable":46},[36,39,42],{"tool":37,"command":38},"npx","npx skills add Horonomos-laps\u002FYana-AI --skill cache-components",{"tool":40,"command":41},"bunx","bunx skills add Horonomos-laps\u002FYana-AI --skill cache-components",{"tool":43,"command":44},"pnpm","pnpm dlx skills add Horonomos-laps\u002FYana-AI --skill cache-components","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FHoronomos-laps\u002FYana-AI\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fcache-components\u002FSKILL.md",true,[],[49,57,64,72,80,88],{"skillNo":50,"name":51,"nameZh":6,"description":52,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":53,"licenseFileUrl":6,"sourceHtmlUrl":54,"categories":55,"keywords":56,"publishedAt":19},"01M735GKET5YVYKAY62W2P5YXB","openai--sentry--sentry","Use when the user asks to inspect Sentry issues or events, summarize recent production errors, or pull basic Sentry health data via the Sentry API; perform read-only queries with the bundled script and require `SENTRY_AUTH_TOKEN`.","MIT","https:\u002F\u002Fgithub.com\u002FHoronomos-laps\u002FYana-AI\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fopenai--sentry--sentry\u002FSKILL.md",[],[],{"skillNo":58,"name":59,"nameZh":6,"description":60,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":61,"categories":62,"keywords":63,"publishedAt":19},"01M73DCAP83T17HY7SMGK7MGFE","ito-basket-compare","Compare Itô prediction-market baskets against a user's knowledge base, portfolio notes, financial context, watchlist, or research thesis. Use for read-only basket comparison and gap analysis without investment advice or live trading.","https:\u002F\u002Fgithub.com\u002FHoronomos-laps\u002FYana-AI\u002Fblob\u002Fmain\u002Fcore\u002Fskills\u002Fito-basket-compare\u002FSKILL.md",[],[],{"skillNo":65,"name":66,"nameZh":6,"description":67,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":68,"sourceHtmlUrl":69,"categories":70,"keywords":71,"publishedAt":19},"01M734CYEMZFDR3KH6SW0JP8TD","implementing-network-traffic-baselining","Build network traffic baselines from NetFlow\u002FIPFIX data using Python pandas for statistical analysis, z-score anomaly detection, and hourly\u002Fdaily traffic pattern profiling","https:\u002F\u002Fgithub.com\u002Fyanacuti1121\u002FYana-AI\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fimplementing-network-traffic-baselining\u002FLICENSE","https:\u002F\u002Fgithub.com\u002FHoronomos-laps\u002FYana-AI\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fimplementing-network-traffic-baselining\u002FSKILL.md",[],[],{"skillNo":73,"name":74,"nameZh":6,"description":75,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":76,"sourceHtmlUrl":77,"categories":78,"keywords":79,"publishedAt":19},"01M73ASZ6NJRJM44Z2P84NGQ3Q","detecting-evasion-techniques-in-endpoint-logs","Detects defense evasion techniques used by adversaries in endpoint logs including log tampering, timestomping, process injection, and security tool disabling. Use when investigating suspicious endpoint behavior, building detection rules for evasion tactics, or conducting threat hunting for stealthy adversary activity. Activates for requests involving evasion detection, defense evasion analysis, log tampering detection, or MITRE ATT&CK TA0005.","https:\u002F\u002Fgithub.com\u002Fyanacuti1121\u002FYana-AI\u002Fblob\u002Fmain\u002Fcore\u002Fskills\u002Fdetecting-evasion-techniques-in-endpoint-logs\u002FLICENSE","https:\u002F\u002Fgithub.com\u002FHoronomos-laps\u002FYana-AI\u002Fblob\u002Fmain\u002Fcore\u002Fskills\u002Fdetecting-evasion-techniques-in-endpoint-logs\u002FSKILL.md",[],[],{"skillNo":81,"name":82,"nameZh":6,"description":83,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":84,"sourceHtmlUrl":85,"categories":86,"keywords":87,"publishedAt":19},"01M734AFNXD06Z78QRK0VKGT7Q","implementing-microsegmentation-with-guardicore","Implementing microsegmentation using Akamai Guardicore Segmentation to map application dependencies, create granular network policies, visualize east-west traffic flows, and enforce least-privilege communication between workloads across data centers and cloud.","https:\u002F\u002Fgithub.com\u002Fyanacuti1121\u002FYana-AI\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fimplementing-microsegmentation-with-guardicore\u002FLICENSE","https:\u002F\u002Fgithub.com\u002FHoronomos-laps\u002FYana-AI\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Fimplementing-microsegmentation-with-guardicore\u002FSKILL.md",[],[],{"skillNo":89,"name":90,"nameZh":6,"description":6,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":91,"categories":92,"keywords":93,"publishedAt":19},"01M736TK27QMCXK0DVCH25SJN5","ramdisk-tmpfs-patterns","https:\u002F\u002Fgithub.com\u002FHoronomos-laps\u002FYana-AI\u002Fblob\u002Fmain\u002F.claude\u002Fskills\u002Framdisk-tmpfs-patterns\u002FSKILL.md",[],[]]