[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6FGR1CTDPTEJXWNGKCSR0AW":3,"skill-same:01M6FGR1CTDPTEJXWNGKCSR0AW":110},{"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":23,"publishedAt":44,"linkOnly":45,"markdownContent":46,"markdownBody":47,"frontMatter":48,"refName":57,"commitSha":58,"skillDirectory":59,"forksCount":60,"repositoryHtmlUrl":61,"repositoryHomepageUrl":62,"ownerHtmlUrl":63,"ownerBlogUrl":6,"ownerDescription":64,"updatedAt":65,"install":66,"resources":79},"01M6FGR1CTDPTEJXWNGKCSR0AW","nuxt-production",null,"Nuxt 4 production optimization: hydration, performance, testing with Vitest,\ndeployment to Cloudflare\u002FVercel\u002FNetlify, and v4 migration.\n\nUse when: debugging hydration mismatches, optimizing performance and Core Web Vitals,\nwriting tests with Vitest, deploying to Cloudflare Pages\u002FWorkers\u002FVercel\u002FNetlify,\nor migrating from Nuxt 3 to Nuxt 4.\n\nKeywords: hydration, hydration mismatch, ClientOnly, SSR, performance,\nlazy loading, lazy hydration, Vitest, testing, deployment, Cloudflare Pages,\nCloudflare Workers, Vercel, Netlify, NuxtHub, migration, Nuxt 3 to Nuxt 4","ComeOnOliver\u002Fskillshub","ComeOnOliver","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F43215937?v=4","01M6E5JNFECJAAVFE0W7SMWWD2","Haoran Shu","01M6E5JNNDQS7AJZDYFQ8TPZCK",67,"MIT","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fsecondsky\u002Fclaude-skills\u002Fnuxt-production-nuxt-v4\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",[24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43],"Production","nuxt production","nuxt","vitest","writing","cloudflare pages","loading","2025","optimizing performance","netlify","cloudflare workers","performance","ssr","testing","Optimization","cloudflare","framework","core","debugging","deployment","2026-11-10 10:12:30",false,"---\nname: nuxt-production\ndescription: |\n  Nuxt 4 production optimization: hydration, performance, testing with Vitest,\n  deployment to Cloudflare\u002FVercel\u002FNetlify, and v4 migration.\n\n  Use when: debugging hydration mismatches, optimizing performance and Core Web Vitals,\n  writing tests with Vitest, deploying to Cloudflare Pages\u002FWorkers\u002FVercel\u002FNetlify,\n  or migrating from Nuxt 3 to Nuxt 4.\n\n  Keywords: hydration, hydration mismatch, ClientOnly, SSR, performance,\n  lazy loading, lazy hydration, Vitest, testing, deployment, Cloudflare Pages,\n  Cloudflare Workers, Vercel, Netlify, NuxtHub, migration, Nuxt 3 to Nuxt 4\nlicense: MIT\nmetadata:\n  version: 4.0.0\n  author: Claude Skills Maintainers\n  category: Framework\n  framework: Nuxt\n  framework-version: 4.x\n  last-verified: 2025-12-28\n---\n\n# Nuxt 4 Production Guide\n\nHydration, performance, testing, deployment, and migration patterns.\n\n## What's New in Nuxt 4\n\n### v4.2 Features (Latest)\n\n**1. Abort Control for Data Fetching**\n```typescript\nconst controller = ref\u003CAbortController>()\n\nconst { data } = await useAsyncData(\n  'users',\n  () => $fetch('\u002Fapi\u002Fusers', { signal: controller.value?.signal })\n)\n\nconst abortRequest = () => {\n  controller.value?.abort()\n  controller.value = new AbortController()\n}\n```\n\n**2. Async Data Handler Extraction**\n- 39% smaller client bundles\n- Data fetching logic extracted to server chunks\n- Automatic optimization (no config needed)\n\n**3. Enhanced Error Handling**\n- Dual error display: custom error page + technical overlay\n- Better error messages in development\n\n### v4.1 Features\n\n**1. Enhanced Chunk Stability**\n- Import maps prevent cascading hash changes\n- Better long-term caching\n\n**2. Lazy Hydration**\n```vue\n\u003Cscript setup>\nconst LazyComponent = defineLazyHydrationComponent(() =>\n  import('.\u002FHeavyComponent.vue')\n)\n\u003C\u002Fscript>\n```\n\n### Breaking Changes from v3\n\n| Change | v3 | v4 |\n|--------|----|----|\n| Source directory | Root | `app\u002F` |\n| Data reactivity | Deep | Shallow (default) |\n| Default values | `null` | `undefined` |\n| Route middleware | Client | Server |\n| App manifest | Opt-in | Default |\n\n## When to Load References\n\n**Load `references\u002Fhydration.md` when:**\n- Debugging \"Hydration node mismatch\" errors\n- Implementing ClientOnly components\n- Fixing non-deterministic rendering issues\n- Understanding SSR vs client rendering\n\n**Load `references\u002Fperformance.md` when:**\n- Optimizing Core Web Vitals scores\n- Implementing lazy loading and code splitting\n- Configuring caching strategies\n- Reducing bundle size\n\n**Load `references\u002Ftesting-vitest.md` when:**\n- Writing component tests with @nuxt\u002Ftest-utils\n- Testing composables with Nuxt context\n- Mocking Nuxt APIs (useFetch, useRoute)\n- Setting up Vitest configuration\n\n**Load `references\u002Fdeployment-cloudflare.md` when:**\n- Deploying to Cloudflare Pages or Workers\n- Configuring wrangler.toml\n- Setting up NuxtHub integration\n- Working with D1, KV, R2 bindings\n\n## Hydration Best Practices\n\n### What Causes Hydration Mismatches\n\n| Cause | Example | Fix |\n|-------|---------|-----|\n| Non-deterministic values | `Math.random()` | Use `useState` |\n| Browser APIs on server | `window.innerWidth` | Use `onMounted` |\n| Date\u002Ftime on server | `new Date()` | Use `useState` or `ClientOnly` |\n| Third-party scripts | Analytics | Use `ClientOnly` |\n\n### Fix Patterns\n\n**Non-deterministic Values:**\n```vue\n\u003C!-- WRONG -->\n\u003Cscript setup>\nconst id = Math.random()\n\u003C\u002Fscript>\n\n\u003C!-- CORRECT -->\n\u003Cscript setup>\nconst id = useState('random-id', () => Math.random())\n\u003C\u002Fscript>\n```\n\n**Browser APIs:**\n```vue\n\u003C!-- WRONG -->\n\u003Cscript setup>\nconst width = window.innerWidth  \u002F\u002F Crashes on server!\n\u003C\u002Fscript>\n\n\u003C!-- CORRECT -->\n\u003Cscript setup>\nconst width = ref(0)\nonMounted(() => {\n  width.value = window.innerWidth\n})\n\u003C\u002Fscript>\n```\n\n**ClientOnly Component:**\n```vue\n\u003Ctemplate>\n  \u003C!-- Wrap client-only content -->\n  \u003CClientOnly>\n    \u003CMyMapComponent \u002F>\n    \u003Ctemplate #fallback>\n      \u003Cdiv class=\"skeleton\">Loading map...\u003C\u002Fdiv>\n    \u003C\u002Ftemplate>\n  \u003C\u002FClientOnly>\n\u003C\u002Ftemplate>\n```\n\n**Conditional Rendering:**\n```vue\n\u003Cscript setup>\nconst showWidget = ref(false)\n\nonMounted(() => {\n  \u002F\u002F Only show after hydration\n  showWidget.value = true\n})\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CAnalyticsWidget v-if=\"showWidget\" \u002F>\n\u003C\u002Ftemplate>\n```\n\n## Performance Optimization\n\n### Lazy Loading Components\n\n```vue\n\u003Cscript setup>\n\u002F\u002F Lazy load heavy components\nconst HeavyChart = defineAsyncComponent(() =>\n  import('~\u002Fcomponents\u002FHeavyChart.vue')\n)\n\n\u002F\u002F With loading\u002Ferror states\nconst HeavyChart = defineAsyncComponent({\n  loader: () => import('~\u002Fcomponents\u002FHeavyChart.vue'),\n  loadingComponent: LoadingSpinner,\n  errorComponent: ErrorFallback,\n  delay: 200,\n  timeout: 10000\n})\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CSuspense>\n    \u003CHeavyChart :data=\"chartData\" \u002F>\n    \u003Ctemplate #fallback>\n      \u003CLoadingSpinner \u002F>\n    \u003C\u002Ftemplate>\n  \u003C\u002FSuspense>\n\u003C\u002Ftemplate>\n```\n\n### Lazy Hydration\n\n```vue\n\u003Cscript setup>\n\u002F\u002F Hydrate when visible in viewport\nconst LazyComponent = defineLazyHydrationComponent(\n  () => import('.\u002FHeavyComponent.vue'),\n  { hydrate: 'visible' }\n)\n\n\u002F\u002F Hydrate on user interaction\nconst InteractiveComponent = defineLazyHydrationComponent(\n  () => import('.\u002FInteractiveComponent.vue'),\n  { hydrate: 'interaction' }\n)\n\n\u002F\u002F Hydrate when browser is idle\nconst IdleComponent = defineLazyHydrationComponent(\n  () => import('.\u002FIdleComponent.vue'),\n  { hydrate: 'idle' }\n)\n\u003C\u002Fscript>\n```\n\n### Route Caching\n\n```typescript\n\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  routeRules: {\n    \u002F\u002F Static pages (prerendered at build)\n    '\u002F': { prerender: true },\n    '\u002Fabout': { prerender: true },\n\n    \u002F\u002F SWR caching (1 hour)\n    '\u002Fblog\u002F**': { swr: 3600 },\n\n    \u002F\u002F ISR (regenerate every hour)\n    '\u002Fproducts\u002F**': { isr: 3600 },\n\n    \u002F\u002F SPA mode (no SSR)\n    '\u002Fdashboard\u002F**': { ssr: false },\n\n    \u002F\u002F Static with CDN caching\n    '\u002Fstatic\u002F**': {\n      headers: { 'Cache-Control': 'public, max-age=31536000' }\n    }\n  }\n})\n```\n\n### Image Optimization\n\n```vue\n\u003Ctemplate>\n  \u003C!-- Automatic optimization with NuxtImg -->\n  \u003CNuxtImg\n    src=\"\u002Fimages\u002Fhero.jpg\"\n    alt=\"Hero image\"\n    width=\"800\"\n    height=\"400\"\n    loading=\"lazy\"\n    placeholder\n    format=\"webp\"\n  \u002F>\n\n  \u003C!-- Responsive images -->\n  \u003CNuxtPicture\n    src=\"\u002Fimages\u002Fproduct.jpg\"\n    alt=\"Product\"\n    sizes=\"sm:100vw md:50vw lg:400px\"\n    :modifiers=\"{ quality: 80 }\"\n  \u002F>\n\u003C\u002Ftemplate>\n```\n\n## Testing with Vitest\n\n### Setup\n\n```bash\nbun add -d @nuxt\u002Ftest-utils vitest @vue\u002Ftest-utils happy-dom\n```\n\n```typescript\n\u002F\u002F vitest.config.ts\nimport { defineVitestConfig } from '@nuxt\u002Ftest-utils\u002Fconfig'\n\nexport default defineVitestConfig({\n  test: {\n    environment: 'nuxt',\n    environmentOptions: {\n      nuxt: {\n        domEnvironment: 'happy-dom'\n      }\n    }\n  }\n})\n```\n\n### Component Testing\n\n```typescript\n\u002F\u002F tests\u002Fcomponents\u002FUserCard.test.ts\nimport { describe, it, expect } from 'vitest'\nimport { mountSuspended } from '@nuxt\u002Ftest-utils\u002Fruntime'\nimport UserCard from '~\u002Fcomponents\u002FUserCard.vue'\n\ndescribe('UserCard', () => {\n  it('renders user name', async () => {\n    const wrapper = await mountSuspended(UserCard, {\n      props: {\n        user: { id: 1, name: 'John Doe', email: 'john@example.com' }\n      }\n    })\n\n    expect(wrapper.text()).toContain('John Doe')\n    expect(wrapper.text()).toContain('john@example.com')\n  })\n\n  it('emits delete event', async () => {\n    const wrapper = await mountSuspended(UserCard, {\n      props: { user: { id: 1, name: 'John' } }\n    })\n\n    await wrapper.find('[data-test=\"delete-btn\"]').trigger('click')\n\n    expect(wrapper.emitted('delete')).toHaveLength(1)\n    expect(wrapper.emitted('delete')[0]).toEqual([1])\n  })\n})\n```\n\n### Mocking Composables\n\n```typescript\n\u002F\u002F tests\u002Fcomponents\u002FDashboard.test.ts\nimport { describe, it, expect, vi } from 'vitest'\nimport { mountSuspended, mockNuxtImport } from '@nuxt\u002Ftest-utils\u002Fruntime'\nimport Dashboard from '~\u002Fpages\u002Fdashboard.vue'\n\n\u002F\u002F Mock useFetch\nmockNuxtImport('useFetch', () => {\n  return () => ({\n    data: ref({ users: [{ id: 1, name: 'John' }] }),\n    pending: ref(false),\n    error: ref(null)\n  })\n})\n\ndescribe('Dashboard', () => {\n  it('displays users from API', async () => {\n    const wrapper = await mountSuspended(Dashboard)\n\n    expect(wrapper.text()).toContain('John')\n  })\n})\n```\n\n### Testing Server Routes\n\n```typescript\n\u002F\u002F tests\u002Fapi\u002Fusers.test.ts\nimport { describe, it, expect } from 'vitest'\nimport { $fetch, setup } from '@nuxt\u002Ftest-utils\u002Fe2e'\n\ndescribe('API: \u002Fapi\u002Fusers', async () => {\n  await setup({ server: true })\n\n  it('returns users list', async () => {\n    const users = await $fetch('\u002Fapi\u002Fusers')\n\n    expect(users).toHaveProperty('users')\n    expect(Array.isArray(users.users)).toBe(true)\n  })\n\n  it('creates a new user', async () => {\n    const result = await $fetch('\u002Fapi\u002Fusers', {\n      method: 'POST',\n      body: { name: 'Jane', email: 'jane@example.com' }\n    })\n\n    expect(result.user.name).toBe('Jane')\n  })\n})\n```\n\n## Deployment\n\n### Cloudflare Pages (Recommended)\n\n```bash\n# Build and deploy\nbun run build\nbunx wrangler pages deploy .output\u002Fpublic\n```\n\n```typescript\n\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  nitro: {\n    preset: 'cloudflare-pages'\n  }\n})\n```\n\n### Cloudflare Workers\n\n```typescript\n\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  nitro: {\n    preset: 'cloudflare-module'\n  }\n})\n```\n\n```toml\n# wrangler.toml\nname = \"my-nuxt-app\"\ncompatibility_date = \"2025-01-01\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n[[d1_databases]]\nbinding = \"DB\"\ndatabase_name = \"my-database\"\ndatabase_id = \"xxx-xxx-xxx\"\n\n[[kv_namespaces]]\nbinding = \"KV\"\nid = \"xxx-xxx-xxx\"\n```\n\n### Vercel\n\n```typescript\n\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  nitro: {\n    preset: 'vercel'\n  }\n})\n```\n\n### Netlify\n\n```typescript\n\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  nitro: {\n    preset: 'netlify'\n  }\n})\n```\n\n### NuxtHub (Cloudflare All-in-One)\n\n```bash\nbun add @nuxthub\u002Fcore\n```\n\n```typescript\n\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  modules: ['@nuxthub\u002Fcore'],\n\n  hub: {\n    database: true,  \u002F\u002F D1\n    kv: true,        \u002F\u002F KV\n    blob: true,      \u002F\u002F R2\n    cache: true      \u002F\u002F Cache API\n  }\n})\n```\n\n```typescript\n\u002F\u002F Usage in server routes\nexport default defineEventHandler(async (event) => {\n  const db = hubDatabase()\n  const kv = hubKV()\n  const blob = hubBlob()\n\n  \u002F\u002F Use like regular Cloudflare bindings\n  const users = await db.prepare('SELECT * FROM users').all()\n})\n```\n\n### Environment Variables\n\n```bash\n# .env (development)\nAPI_SECRET=dev-secret\nDATABASE_URL=http:\u002F\u002Flocalhost:8787\n\n# Production (Cloudflare)\nwrangler secret put API_SECRET\nwrangler secret put DATABASE_URL\n\n# Production (Vercel\u002FNetlify)\n# Set in dashboard or CLI\n```\n\n## Migration from Nuxt 3\n\n### Step 1: Update package.json\n\n```json\n{\n  \"devDependencies\": {\n    \"nuxt\": \"^4.0.0\"\n  }\n}\n```\n\n### Step 2: Enable Compatibility Mode\n\n```typescript\n\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  future: {\n    compatibilityVersion: 4\n  }\n})\n```\n\n### Step 3: Move Files to app\u002F\n\n```bash\n# Create app directory\nmkdir app\n\n# Move files\nmv components app\u002F\nmv composables app\u002F\nmv pages app\u002F\nmv layouts app\u002F\nmv middleware app\u002F\nmv plugins app\u002F\nmv assets app\u002F\nmv app.vue app\u002F\nmv error.vue app\u002F\n```\n\n### Step 4: Fix Shallow Reactivity\n\n```typescript\n\u002F\u002F If mutating data.value properties:\nconst { data } = await useFetch('\u002Fapi\u002Fuser', {\n  deep: true  \u002F\u002F Enable deep reactivity\n})\n\n\u002F\u002F Or replace entire value\ndata.value = { ...data.value, name: 'New Name' }\n```\n\n### Step 5: Update Default Values\n\n```typescript\n\u002F\u002F v3: data.value is null\n\u002F\u002F v4: data.value is undefined\n\n\u002F\u002F Update null checks\nif (data.value === null) \u002F\u002F v3\nif (!data.value)         \u002F\u002F v4 (works for both)\n```\n\n## Common Anti-Patterns\n\n### Client-Only Code on Server\n\n```typescript\n\u002F\u002F WRONG\nconst width = window.innerWidth\n\n\u002F\u002F CORRECT\nif (import.meta.client) {\n  const width = window.innerWidth\n}\n\n\u002F\u002F Or use onMounted\nonMounted(() => {\n  const width = window.innerWidth\n})\n```\n\n### Non-Deterministic SSR\n\n```typescript\n\u002F\u002F WRONG - Different on server vs client\nconst id = Math.random()\nconst time = Date.now()\n\n\u002F\u002F CORRECT - Use useState for consistency\nconst id = useState('id', () => Math.random())\nconst time = useState('time', () => Date.now())\n```\n\n### Missing Suspense for Async Components\n\n```vue\n\u003C!-- WRONG -->\n\u003CAsyncComponent \u002F>\n\n\u003C!-- CORRECT -->\n\u003CSuspense>\n  \u003CAsyncComponent \u002F>\n  \u003Ctemplate #fallback>\n    \u003CLoadingSpinner \u002F>\n  \u003C\u002Ftemplate>\n\u003C\u002FSuspense>\n```\n\n## Troubleshooting\n\n**Hydration Mismatch:**\n- Check for `window`, `document`, `localStorage` usage\n- Wrap in `ClientOnly` or use `onMounted`\n- Look for `Math.random()`, `Date.now()`, `crypto.randomUUID()`\n\n**Build Errors:**\n```bash\nrm -rf .nuxt .output node_modules\u002F.vite && bun install\n```\n\n**Deployment Fails:**\n- Check `nitro.preset` matches target\n- Verify environment variables are set\n- Check wrangler.toml bindings match code\n\n**Tests Failing:**\n- Ensure `@nuxt\u002Ftest-utils` is installed\n- Check vitest.config.ts has `environment: 'nuxt'`\n- Use `mountSuspended` for async components\n\n## Related Skills\n\n- **nuxt-core**: Project setup, routing, configuration\n- **nuxt-data**: Composables, data fetching, state\n- **nuxt-server**: Server routes, API patterns\n- **cloudflare-d1**: D1 database patterns\n\n---\n\n**Version**: 4.0.0 | **Last Updated**: 2025-12-28 | **License**: MIT\n","# Nuxt 4 Production Guide\n\nHydration, performance, testing, deployment, and migration patterns.\n\n## What's New in Nuxt 4\n\n### v4.2 Features (Latest)\n\n**1. Abort Control for Data Fetching**\n```typescript\nconst controller = ref\u003CAbortController>()\n\nconst { data } = await useAsyncData(\n  'users',\n  () => $fetch('\u002Fapi\u002Fusers', { signal: controller.value?.signal })\n)\n\nconst abortRequest = () => {\n  controller.value?.abort()\n  controller.value = new AbortController()\n}\n```\n\n**2. Async Data Handler Extraction**\n- 39% smaller client bundles\n- Data fetching logic extracted to server chunks\n- Automatic optimization (no config needed)\n\n**3. Enhanced Error Handling**\n- Dual error display: custom error page + technical overlay\n- Better error messages in development\n\n### v4.1 Features\n\n**1. Enhanced Chunk Stability**\n- Import maps prevent cascading hash changes\n- Better long-term caching\n\n**2. Lazy Hydration**\n```vue\n\u003Cscript setup>\nconst LazyComponent = defineLazyHydrationComponent(() =>\n  import('.\u002FHeavyComponent.vue')\n)\n\u003C\u002Fscript>\n```\n\n### Breaking Changes from v3\n\n| Change | v3 | v4 |\n|--------|----|----|\n| Source directory | Root | `app\u002F` |\n| Data reactivity | Deep | Shallow (default) |\n| Default values | `null` | `undefined` |\n| Route middleware | Client | Server |\n| App manifest | Opt-in | Default |\n\n## When to Load References\n\n**Load `references\u002Fhydration.md` when:**\n- Debugging \"Hydration node mismatch\" errors\n- Implementing ClientOnly components\n- Fixing non-deterministic rendering issues\n- Understanding SSR vs client rendering\n\n**Load `references\u002Fperformance.md` when:**\n- Optimizing Core Web Vitals scores\n- Implementing lazy loading and code splitting\n- Configuring caching strategies\n- Reducing bundle size\n\n**Load `references\u002Ftesting-vitest.md` when:**\n- Writing component tests with @nuxt\u002Ftest-utils\n- Testing composables with Nuxt context\n- Mocking Nuxt APIs (useFetch, useRoute)\n- Setting up Vitest configuration\n\n**Load `references\u002Fdeployment-cloudflare.md` when:**\n- Deploying to Cloudflare Pages or Workers\n- Configuring wrangler.toml\n- Setting up NuxtHub integration\n- Working with D1, KV, R2 bindings\n\n## Hydration Best Practices\n\n### What Causes Hydration Mismatches\n\n| Cause | Example | Fix |\n|-------|---------|-----|\n| Non-deterministic values | `Math.random()` | Use `useState` |\n| Browser APIs on server | `window.innerWidth` | Use `onMounted` |\n| Date\u002Ftime on server | `new Date()` | Use `useState` or `ClientOnly` |\n| Third-party scripts | Analytics | Use `ClientOnly` |\n\n### Fix Patterns\n\n**Non-deterministic Values:**\n```vue\n\u003C!-- WRONG -->\n\u003Cscript setup>\nconst id = Math.random()\n\u003C\u002Fscript>\n\n\u003C!-- CORRECT -->\n\u003Cscript setup>\nconst id = useState('random-id', () => Math.random())\n\u003C\u002Fscript>\n```\n\n**Browser APIs:**\n```vue\n\u003C!-- WRONG -->\n\u003Cscript setup>\nconst width = window.innerWidth  \u002F\u002F Crashes on server!\n\u003C\u002Fscript>\n\n\u003C!-- CORRECT -->\n\u003Cscript setup>\nconst width = ref(0)\nonMounted(() => {\n  width.value = window.innerWidth\n})\n\u003C\u002Fscript>\n```\n\n**ClientOnly Component:**\n```vue\n\u003Ctemplate>\n  \u003C!-- Wrap client-only content -->\n  \u003CClientOnly>\n    \u003CMyMapComponent \u002F>\n    \u003Ctemplate #fallback>\n      \u003Cdiv class=\"skeleton\">Loading map...\u003C\u002Fdiv>\n    \u003C\u002Ftemplate>\n  \u003C\u002FClientOnly>\n\u003C\u002Ftemplate>\n```\n\n**Conditional Rendering:**\n```vue\n\u003Cscript setup>\nconst showWidget = ref(false)\n\nonMounted(() => {\n  \u002F\u002F Only show after hydration\n  showWidget.value = true\n})\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CAnalyticsWidget v-if=\"showWidget\" \u002F>\n\u003C\u002Ftemplate>\n```\n\n## Performance Optimization\n\n### Lazy Loading Components\n\n```vue\n\u003Cscript setup>\n\u002F\u002F Lazy load heavy components\nconst HeavyChart = defineAsyncComponent(() =>\n  import('~\u002Fcomponents\u002FHeavyChart.vue')\n)\n\n\u002F\u002F With loading\u002Ferror states\nconst HeavyChart = defineAsyncComponent({\n  loader: () => import('~\u002Fcomponents\u002FHeavyChart.vue'),\n  loadingComponent: LoadingSpinner,\n  errorComponent: ErrorFallback,\n  delay: 200,\n  timeout: 10000\n})\n\u003C\u002Fscript>\n\n\u003Ctemplate>\n  \u003CSuspense>\n    \u003CHeavyChart :data=\"chartData\" \u002F>\n    \u003Ctemplate #fallback>\n      \u003CLoadingSpinner \u002F>\n    \u003C\u002Ftemplate>\n  \u003C\u002FSuspense>\n\u003C\u002Ftemplate>\n```\n\n### Lazy Hydration\n\n```vue\n\u003Cscript setup>\n\u002F\u002F Hydrate when visible in viewport\nconst LazyComponent = defineLazyHydrationComponent(\n  () => import('.\u002FHeavyComponent.vue'),\n  { hydrate: 'visible' }\n)\n\n\u002F\u002F Hydrate on user interaction\nconst InteractiveComponent = defineLazyHydrationComponent(\n  () => import('.\u002FInteractiveComponent.vue'),\n  { hydrate: 'interaction' }\n)\n\n\u002F\u002F Hydrate when browser is idle\nconst IdleComponent = defineLazyHydrationComponent(\n  () => import('.\u002FIdleComponent.vue'),\n  { hydrate: 'idle' }\n)\n\u003C\u002Fscript>\n```\n\n### Route Caching\n\n```typescript\n\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  routeRules: {\n    \u002F\u002F Static pages (prerendered at build)\n    '\u002F': { prerender: true },\n    '\u002Fabout': { prerender: true },\n\n    \u002F\u002F SWR caching (1 hour)\n    '\u002Fblog\u002F**': { swr: 3600 },\n\n    \u002F\u002F ISR (regenerate every hour)\n    '\u002Fproducts\u002F**': { isr: 3600 },\n\n    \u002F\u002F SPA mode (no SSR)\n    '\u002Fdashboard\u002F**': { ssr: false },\n\n    \u002F\u002F Static with CDN caching\n    '\u002Fstatic\u002F**': {\n      headers: { 'Cache-Control': 'public, max-age=31536000' }\n    }\n  }\n})\n```\n\n### Image Optimization\n\n```vue\n\u003Ctemplate>\n  \u003C!-- Automatic optimization with NuxtImg -->\n  \u003CNuxtImg\n    src=\"\u002Fimages\u002Fhero.jpg\"\n    alt=\"Hero image\"\n    width=\"800\"\n    height=\"400\"\n    loading=\"lazy\"\n    placeholder\n    format=\"webp\"\n  \u002F>\n\n  \u003C!-- Responsive images -->\n  \u003CNuxtPicture\n    src=\"\u002Fimages\u002Fproduct.jpg\"\n    alt=\"Product\"\n    sizes=\"sm:100vw md:50vw lg:400px\"\n    :modifiers=\"{ quality: 80 }\"\n  \u002F>\n\u003C\u002Ftemplate>\n```\n\n## Testing with Vitest\n\n### Setup\n\n```bash\nbun add -d @nuxt\u002Ftest-utils vitest @vue\u002Ftest-utils happy-dom\n```\n\n```typescript\n\u002F\u002F vitest.config.ts\nimport { defineVitestConfig } from '@nuxt\u002Ftest-utils\u002Fconfig'\n\nexport default defineVitestConfig({\n  test: {\n    environment: 'nuxt',\n    environmentOptions: {\n      nuxt: {\n        domEnvironment: 'happy-dom'\n      }\n    }\n  }\n})\n```\n\n### Component Testing\n\n```typescript\n\u002F\u002F tests\u002Fcomponents\u002FUserCard.test.ts\nimport { describe, it, expect } from 'vitest'\nimport { mountSuspended } from '@nuxt\u002Ftest-utils\u002Fruntime'\nimport UserCard from '~\u002Fcomponents\u002FUserCard.vue'\n\ndescribe('UserCard', () => {\n  it('renders user name', async () => {\n    const wrapper = await mountSuspended(UserCard, {\n      props: {\n        user: { id: 1, name: 'John Doe', email: 'john@example.com' }\n      }\n    })\n\n    expect(wrapper.text()).toContain('John Doe')\n    expect(wrapper.text()).toContain('john@example.com')\n  })\n\n  it('emits delete event', async () => {\n    const wrapper = await mountSuspended(UserCard, {\n      props: { user: { id: 1, name: 'John' } }\n    })\n\n    await wrapper.find('[data-test=\"delete-btn\"]').trigger('click')\n\n    expect(wrapper.emitted('delete')).toHaveLength(1)\n    expect(wrapper.emitted('delete')[0]).toEqual([1])\n  })\n})\n```\n\n### Mocking Composables\n\n```typescript\n\u002F\u002F tests\u002Fcomponents\u002FDashboard.test.ts\nimport { describe, it, expect, vi } from 'vitest'\nimport { mountSuspended, mockNuxtImport } from '@nuxt\u002Ftest-utils\u002Fruntime'\nimport Dashboard from '~\u002Fpages\u002Fdashboard.vue'\n\n\u002F\u002F Mock useFetch\nmockNuxtImport('useFetch', () => {\n  return () => ({\n    data: ref({ users: [{ id: 1, name: 'John' }] }),\n    pending: ref(false),\n    error: ref(null)\n  })\n})\n\ndescribe('Dashboard', () => {\n  it('displays users from API', async () => {\n    const wrapper = await mountSuspended(Dashboard)\n\n    expect(wrapper.text()).toContain('John')\n  })\n})\n```\n\n### Testing Server Routes\n\n```typescript\n\u002F\u002F tests\u002Fapi\u002Fusers.test.ts\nimport { describe, it, expect } from 'vitest'\nimport { $fetch, setup } from '@nuxt\u002Ftest-utils\u002Fe2e'\n\ndescribe('API: \u002Fapi\u002Fusers', async () => {\n  await setup({ server: true })\n\n  it('returns users list', async () => {\n    const users = await $fetch('\u002Fapi\u002Fusers')\n\n    expect(users).toHaveProperty('users')\n    expect(Array.isArray(users.users)).toBe(true)\n  })\n\n  it('creates a new user', async () => {\n    const result = await $fetch('\u002Fapi\u002Fusers', {\n      method: 'POST',\n      body: { name: 'Jane', email: 'jane@example.com' }\n    })\n\n    expect(result.user.name).toBe('Jane')\n  })\n})\n```\n\n## Deployment\n\n### Cloudflare Pages (Recommended)\n\n```bash\n# Build and deploy\nbun run build\nbunx wrangler pages deploy .output\u002Fpublic\n```\n\n```typescript\n\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  nitro: {\n    preset: 'cloudflare-pages'\n  }\n})\n```\n\n### Cloudflare Workers\n\n```typescript\n\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  nitro: {\n    preset: 'cloudflare-module'\n  }\n})\n```\n\n```toml\n# wrangler.toml\nname = \"my-nuxt-app\"\ncompatibility_date = \"2025-01-01\"\ncompatibility_flags = [\"nodejs_compat\"]\n\n[[d1_databases]]\nbinding = \"DB\"\ndatabase_name = \"my-database\"\ndatabase_id = \"xxx-xxx-xxx\"\n\n[[kv_namespaces]]\nbinding = \"KV\"\nid = \"xxx-xxx-xxx\"\n```\n\n### Vercel\n\n```typescript\n\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  nitro: {\n    preset: 'vercel'\n  }\n})\n```\n\n### Netlify\n\n```typescript\n\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  nitro: {\n    preset: 'netlify'\n  }\n})\n```\n\n### NuxtHub (Cloudflare All-in-One)\n\n```bash\nbun add @nuxthub\u002Fcore\n```\n\n```typescript\n\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  modules: ['@nuxthub\u002Fcore'],\n\n  hub: {\n    database: true,  \u002F\u002F D1\n    kv: true,        \u002F\u002F KV\n    blob: true,      \u002F\u002F R2\n    cache: true      \u002F\u002F Cache API\n  }\n})\n```\n\n```typescript\n\u002F\u002F Usage in server routes\nexport default defineEventHandler(async (event) => {\n  const db = hubDatabase()\n  const kv = hubKV()\n  const blob = hubBlob()\n\n  \u002F\u002F Use like regular Cloudflare bindings\n  const users = await db.prepare('SELECT * FROM users').all()\n})\n```\n\n### Environment Variables\n\n```bash\n# .env (development)\nAPI_SECRET=dev-secret\nDATABASE_URL=http:\u002F\u002Flocalhost:8787\n\n# Production (Cloudflare)\nwrangler secret put API_SECRET\nwrangler secret put DATABASE_URL\n\n# Production (Vercel\u002FNetlify)\n# Set in dashboard or CLI\n```\n\n## Migration from Nuxt 3\n\n### Step 1: Update package.json\n\n```json\n{\n  \"devDependencies\": {\n    \"nuxt\": \"^4.0.0\"\n  }\n}\n```\n\n### Step 2: Enable Compatibility Mode\n\n```typescript\n\u002F\u002F nuxt.config.ts\nexport default defineNuxtConfig({\n  future: {\n    compatibilityVersion: 4\n  }\n})\n```\n\n### Step 3: Move Files to app\u002F\n\n```bash\n# Create app directory\nmkdir app\n\n# Move files\nmv components app\u002F\nmv composables app\u002F\nmv pages app\u002F\nmv layouts app\u002F\nmv middleware app\u002F\nmv plugins app\u002F\nmv assets app\u002F\nmv app.vue app\u002F\nmv error.vue app\u002F\n```\n\n### Step 4: Fix Shallow Reactivity\n\n```typescript\n\u002F\u002F If mutating data.value properties:\nconst { data } = await useFetch('\u002Fapi\u002Fuser', {\n  deep: true  \u002F\u002F Enable deep reactivity\n})\n\n\u002F\u002F Or replace entire value\ndata.value = { ...data.value, name: 'New Name' }\n```\n\n### Step 5: Update Default Values\n\n```typescript\n\u002F\u002F v3: data.value is null\n\u002F\u002F v4: data.value is undefined\n\n\u002F\u002F Update null checks\nif (data.value === null) \u002F\u002F v3\nif (!data.value)         \u002F\u002F v4 (works for both)\n```\n\n## Common Anti-Patterns\n\n### Client-Only Code on Server\n\n```typescript\n\u002F\u002F WRONG\nconst width = window.innerWidth\n\n\u002F\u002F CORRECT\nif (import.meta.client) {\n  const width = window.innerWidth\n}\n\n\u002F\u002F Or use onMounted\nonMounted(() => {\n  const width = window.innerWidth\n})\n```\n\n### Non-Deterministic SSR\n\n```typescript\n\u002F\u002F WRONG - Different on server vs client\nconst id = Math.random()\nconst time = Date.now()\n\n\u002F\u002F CORRECT - Use useState for consistency\nconst id = useState('id', () => Math.random())\nconst time = useState('time', () => Date.now())\n```\n\n### Missing Suspense for Async Components\n\n```vue\n\u003C!-- WRONG -->\n\u003CAsyncComponent \u002F>\n\n\u003C!-- CORRECT -->\n\u003CSuspense>\n  \u003CAsyncComponent \u002F>\n  \u003Ctemplate #fallback>\n    \u003CLoadingSpinner \u002F>\n  \u003C\u002Ftemplate>\n\u003C\u002FSuspense>\n```\n\n## Troubleshooting\n\n**Hydration Mismatch:**\n- Check for `window`, `document`, `localStorage` usage\n- Wrap in `ClientOnly` or use `onMounted`\n- Look for `Math.random()`, `Date.now()`, `crypto.randomUUID()`\n\n**Build Errors:**\n```bash\nrm -rf .nuxt .output node_modules\u002F.vite && bun install\n```\n\n**Deployment Fails:**\n- Check `nitro.preset` matches target\n- Verify environment variables are set\n- Check wrangler.toml bindings match code\n\n**Tests Failing:**\n- Ensure `@nuxt\u002Ftest-utils` is installed\n- Check vitest.config.ts has `environment: 'nuxt'`\n- Use `mountSuspended` for async components\n\n## Related Skills\n\n- **nuxt-core**: Project setup, routing, configuration\n- **nuxt-data**: Composables, data fetching, state\n- **nuxt-server**: Server routes, API patterns\n- **cloudflare-d1**: D1 database patterns\n\n---\n\n**Version**: 4.0.0 | **Last Updated**: 2025-12-28 | **License**: MIT\n",{"name":5,"license":15,"metadata":49,"description":56},{"author":50,"version":51,"category":52,"framework":53,"last-verified":54,"framework-version":55},"Claude Skills Maintainers","4.0.0","Framework","Nuxt",1766880000000,"4.x","Nuxt 4 production optimization: hydration, performance, testing with Vitest,\ndeployment to Cloudflare\u002FVercel\u002FNetlify, and v4 migration.\n\nUse when: debugging hydration mismatches, optimizing performance and Core Web Vitals,\nwriting tests with Vitest, deploying to Cloudflare Pages\u002FWorkers\u002FVercel\u002FNetlify,\nor migrating from Nuxt 3 to Nuxt 4.\n\nKeywords: hydration, hydration mismatch, ClientOnly, SSR, performance,\nlazy loading, lazy hydration, Vitest, testing, deployment, Cloudflare Pages,\nCloudflare Workers, Vercel, Netlify, NuxtHub, migration, Nuxt 3 to Nuxt 4\n","main","def8531e65114c0fca8fb8551c1871ee0eed705c","skills\u002Fsecondsky\u002Fclaude-skills\u002Fnuxt-production-nuxt-v4",24,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub","https:\u002F\u002Fskillshub.wtf","https:\u002F\u002Fgithub.com\u002FComeOnOliver","AI & Blockchain Engineer\r\n","2026-06-24 22:07:19",{"source":8,"skillName":5,"commands":67,"prompt":77,"zipAvailable":78},[68,71,74],{"tool":69,"command":70},"npx","npx skills add ComeOnOliver\u002Fskillshub --skill nuxt-production",{"tool":72,"command":73},"bunx","bunx skills add ComeOnOliver\u002Fskillshub --skill nuxt-production",{"tool":75,"command":76},"pnpm","pnpm dlx skills add ComeOnOliver\u002Fskillshub --skill nuxt-production","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fsecondsky\u002Fclaude-skills\u002Fnuxt-production-nuxt-v4\u002FSKILL.md",true,[80,86,90,94,98,104],{"path":81,"resourceType":82,"resourceTypeDesc":83,"sizeBytes":84,"sourceHtmlUrl":85},"references\u002Fdeployment-cloudflare.md","REFERENCE","参考文档",13874,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fsecondsky\u002Fclaude-skills\u002Fnuxt-production-nuxt-v4\u002Freferences\u002Fdeployment-cloudflare.md",{"path":87,"resourceType":82,"resourceTypeDesc":83,"sizeBytes":88,"sourceHtmlUrl":89},"references\u002Fhydration.md",8599,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fsecondsky\u002Fclaude-skills\u002Fnuxt-production-nuxt-v4\u002Freferences\u002Fhydration.md",{"path":91,"resourceType":82,"resourceTypeDesc":83,"sizeBytes":92,"sourceHtmlUrl":93},"references\u002Fperformance.md",12087,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fsecondsky\u002Fclaude-skills\u002Fnuxt-production-nuxt-v4\u002Freferences\u002Fperformance.md",{"path":95,"resourceType":82,"resourceTypeDesc":83,"sizeBytes":96,"sourceHtmlUrl":97},"references\u002Ftesting-vitest.md",13457,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fsecondsky\u002Fclaude-skills\u002Fnuxt-production-nuxt-v4\u002Freferences\u002Ftesting-vitest.md",{"path":99,"resourceType":100,"resourceTypeDesc":101,"sizeBytes":102,"sourceHtmlUrl":103},"templates\u002Ftests\u002Fcomponents\u002FBlogPost.test.ts","SCRIPT","脚本",1200,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fsecondsky\u002Fclaude-skills\u002Fnuxt-production-nuxt-v4\u002Ftemplates\u002Ftests\u002Fcomponents\u002FBlogPost.test.ts",{"path":105,"resourceType":106,"resourceTypeDesc":107,"sizeBytes":108,"sourceHtmlUrl":109},"templates\u002Fwrangler.toml","OTHER","其他",1028,"https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fsecondsky\u002Fclaude-skills\u002Fnuxt-production-nuxt-v4\u002Ftemplates\u002Fwrangler.toml",[111,123,133,142,148,155],{"skillNo":112,"name":113,"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":114,"categories":115,"keywords":119,"publishedAt":44},"01M6FKJN13GMG4KY57J3QD8GY5","model-hierarchy-skill","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzscole\u002Fmodel-hierarchy-skill\u002Fmodel-hierarchy-skill\u002FSKILL.md",[116],{"categoryNo":117,"categoryName":118,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[120,121,122],"model","model hierarchy","model hierarchy skill",{"skillNo":124,"name":125,"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":126,"categories":127,"keywords":129,"publishedAt":44},"01M6FKJJJ6GCAMR4PPPRD12M5X","zoom-mcp","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-mcp\u002FSKILL.md",[128],{"categoryNo":117,"categoryName":118,"taxonomyType":21,"taxonomyTypeDesc":22},[130,131,132],"MCP","zoom","zoom mcp",{"skillNo":134,"name":135,"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":136,"categories":137,"keywords":138,"publishedAt":44},"01M6FKJE3KYT3KPEZMEEHYKA6K","zoom-apps-sdk","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fzoom-apps-sdk\u002FSKILL.md",[],[139,140,141,131],"sdk","zoom apps sdk","apps",{"skillNo":143,"name":144,"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":145,"categories":146,"keywords":147,"publishedAt":44},"01M6FKJ9EDH9Q5VWDF8HAJRSP0","windows","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwindows\u002FSKILL.md",[],[144],{"skillNo":149,"name":150,"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":151,"categories":152,"keywords":154,"publishedAt":44},"01M6FKJ666BEEFC3AE9GJ72Q93","whiteboard","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwhiteboard\u002FSKILL.md",[153],{"categoryNo":117,"categoryName":118,"taxonomyType":21,"taxonomyTypeDesc":22},[150],{"skillNo":156,"name":157,"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":158,"categories":159,"keywords":160,"publishedAt":44},"01M6FKJ21WFCDGTJQ2Q91T9DVW","websockets","https:\u002F\u002Fgithub.com\u002FComeOnOliver\u002Fskillshub\u002Fblob\u002Fmain\u002Fskills\u002Fzoom\u002Fskills\u002Fwebsockets\u002FSKILL.md",[],[157]]