feat(skills): add Nuxt 4 patterns skill#643
feat(skills): add Nuxt 4 patterns skill#643yongggquannn wants to merge 15 commits intoaffaan-m:mainfrom
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds a new documentation skill file Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
📝 Coding Plan
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile SummaryThis PR adds Key remaining observations:
Confidence Score: 3/5
Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[Nuxt 4 Request] --> B{Route Rule?}
B -->|prerender: true| C[Static HTML served from CDN]
B -->|swr: N seconds| D[Stale-While-Revalidate Cache]
B -->|isr: N seconds| E[Incremental Static Regeneration]
B -->|ssr: false| F[SPA / Client-Only Bundle]
B -->|default SSR| G[Server-Side Render]
G --> H{Data Fetching}
H -->|useFetch / useAsyncData| I[Server fetches + serialises payload]
I --> J[Client hydrates from payload — no double fetch]
J --> K{Hydration Safety Check}
K -->|useState / useCookie| L[Server + Client state in sync ✓]
K -->|window / localStorage direct| M[Hydration Mismatch ✗]
K -->|useDark without cookie| N[Potential Mismatch ⚠]
L --> O[Interactive Page]
J --> P{Performance}
P -->|Lazy prefix| Q[Component JS deferred until rendered]
P -->|hydrate-on-visible/idle| R[Hydration deferred — reduces JS work]
P -->|NuxtImg + webp| S[Optimised images with priority hints]
P -->|useScript manual trigger| T[Third-party scripts load after consent]
Last reviewed commit: "fix: update type par..." |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
skills/nuxt-4-frontend-patterns/SKILL.md (2)
87-94: Clarify that this example would crash SSR, not just mismatch.The "Not good" example on line 89 (
v-if="window?.innerWidth > 768") would throw a ReferenceError during server-side rendering sincewindowis undefined. The optional chaining operator doesn't prevent this error in Vue template expressions. Consider updating the comment to reflect that this crashes SSR rather than just causing a hydration mismatch.📝 Suggested clarification
<template> - <!-- Not good: causes hydration mismatch --> + <!-- Not good: crashes on server (ReferenceError) --> <div v-if="window?.innerWidth > 768">Desktop</div>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@skills/nuxt-4-frontend-patterns/SKILL.md` around lines 87 - 94, The comment on the "Not good" example is incorrect: using v-if="window?.innerWidth > 768" in a Vue template will throw a ReferenceError during SSR because window is undefined (the optional chaining doesn't avoid the server-side evaluation). Update the comment to state this crashes SSR (not just a hydration mismatch) and suggest using CSS responsiveness (as shown) or a client-only guard such as checking window inside mounted/useMounted or a reactive isClient/isMounted flag (replace the v-if window expression with a client-side check or move it into mounted/composables).
1-515: Add a "How It Works" section to align with skill formatting guidelines.While the document provides excellent patterns and examples, it's missing an explicit "How It Works" section that explains the underlying concepts. Consider adding a section after "When to Activate" that covers:
- The SSR/hydration lifecycle (server render → hydration → client interactivity)
- When code runs on server vs. client
- Why hydration mismatches occur and their impact
- The role of route rules in the rendering pipeline
This would help developers new to Nuxt/SSR understand why these patterns are necessary before seeing what patterns to use.
As per coding guidelines, skills should be formatted with clear sections for "When to Use", "How It Works", and "Examples". The file currently has "When to Activate" (✓) and extensive examples (✓), but lacks the conceptual "How It Works" section.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@skills/nuxt-4-frontend-patterns/SKILL.md` around lines 1 - 515, Add a new "How It Works" section immediately after the existing "When to Activate" header that briefly explains the SSR/hydration lifecycle (server render → hydration → client interactivity), clarifies when code runs on server vs client (mention import.meta.client, onMounted, browser-only APIs), summarizes why hydration mismatches occur and their impact, and describes how route rules (referencing routeRules keys like prerender, swr, isr, ssr: false) affect the rendering pipeline; keep it concise, aligned with the "When to Use"/"Examples" structure, and reference composables used elsewhere (useState, useFetch, useAsyncData, useCookie) for context.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@skills/nuxt-4-frontend-patterns/SKILL.md`:
- Around line 258-266: The documentation example using useScriptGoogleAnalytics
lacks a note that the Nuxt Scripts module must be installed; update SKILL.md
near the VueUse section to add a short setup step instructing users to install
and enable the official Nuxt Scripts module (e.g., npm install `@nuxt/scripts` and
add to modules in nuxt.config) before using useScriptGoogleAnalytics, and
mention that the composable depends on `@nuxt/scripts` so the manual trigger
(scriptOptions: { trigger: 'manual' }) will work.
---
Nitpick comments:
In `@skills/nuxt-4-frontend-patterns/SKILL.md`:
- Around line 87-94: The comment on the "Not good" example is incorrect: using
v-if="window?.innerWidth > 768" in a Vue template will throw a ReferenceError
during SSR because window is undefined (the optional chaining doesn't avoid the
server-side evaluation). Update the comment to state this crashes SSR (not just
a hydration mismatch) and suggest using CSS responsiveness (as shown) or a
client-only guard such as checking window inside mounted/useMounted or a
reactive isClient/isMounted flag (replace the v-if window expression with a
client-side check or move it into mounted/composables).
- Around line 1-515: Add a new "How It Works" section immediately after the
existing "When to Activate" header that briefly explains the SSR/hydration
lifecycle (server render → hydration → client interactivity), clarifies when
code runs on server vs client (mention import.meta.client, onMounted,
browser-only APIs), summarizes why hydration mismatches occur and their impact,
and describes how route rules (referencing routeRules keys like prerender, swr,
isr, ssr: false) affect the rendering pipeline; keep it concise, aligned with
the "When to Use"/"Examples" structure, and reference composables used elsewhere
(useState, useFetch, useAsyncData, useCookie) for context.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 1d5bf154-7f60-42a4-b93f-ae2aff9418b3
📒 Files selected for processing (1)
skills/nuxt-4-frontend-patterns/SKILL.md
There was a problem hiding this comment.
2 issues found across 1 file
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="skills/nuxt-4-frontend-patterns/SKILL.md">
<violation number="1" location="skills/nuxt-4-frontend-patterns/SKILL.md:1">
P1: Malformed frontmatter (`## name` and missing closing `---`) can break skill metadata parsing/registration.</violation>
<violation number="2" location="skills/nuxt-4-frontend-patterns/SKILL.md:440">
P2: Debounced event-driven search example uses `useFetch` inside a runtime callback; this should use `$fetch` for client-triggered requests.</violation>
</file>
Since this is your first cubic review, here's how it works:
- cubic automatically reviews your code and comments on bugs and improvements
- Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
- Add one-off context when rerunning by tagging
@cubic-dev-aiwith guidance or docs links (includingllms.txt) - Ask questions if you need clarification on any suggestion
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Remove markdown heading prefix (##) from name field and add missing closing --- delimiter so the skill catalog parses the description correctly.
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="skills/nuxt-4-frontend-patterns/SKILL.md">
<violation number="1" location="skills/nuxt-4-frontend-patterns/SKILL.md:439">
P2: Debounced search example is race-prone: older async responses can overwrite newer query results.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
…proach for layout switching
There was a problem hiding this comment.
♻️ Duplicate comments (1)
skills/nuxt-4-frontend-patterns/SKILL.md (1)
258-266:⚠️ Potential issue | 🟡 MinorSetup instructions for
@nuxt/scriptsare still missing.The example uses
useScriptGoogleAnalyticsbut the document doesn't include installation/setup instructions for the@nuxt/scriptsmodule. Add a setup section (similar to VueUse at lines 372-386) showing:npm install `@nuxt/scripts`// nuxt.config.ts export default defineNuxtConfig({ modules: ['@nuxt/scripts'], })🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@skills/nuxt-4-frontend-patterns/SKILL.md` around lines 258 - 266, Add a short "Setup" subsection showing how to install and register the `@nuxt/scripts` module so the useScriptGoogleAnalytics example works: instruct to run npm install `@nuxt/scripts` and show adding modules: ['@nuxt/scripts'] to nuxt.config.ts (referencing the example that uses useScriptGoogleAnalytics and the manual scriptOptions trigger). Place this setup block near the VueUse setup section so readers can follow installation before the useScriptGoogleAnalytics snippet.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@skills/nuxt-4-frontend-patterns/SKILL.md`:
- Around line 258-266: Add a short "Setup" subsection showing how to install and
register the `@nuxt/scripts` module so the useScriptGoogleAnalytics example works:
instruct to run npm install `@nuxt/scripts` and show adding modules:
['@nuxt/scripts'] to nuxt.config.ts (referencing the example that uses
useScriptGoogleAnalytics and the manual scriptOptions trigger). Place this setup
block near the VueUse setup section so readers can follow installation before
the useScriptGoogleAnalytics snippet.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 1ae19968-33f3-44d7-8e25-20c760c1c6e1
📒 Files selected for processing (1)
skills/nuxt-4-frontend-patterns/SKILL.md
There was a problem hiding this comment.
1 issue found across 1 file (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="skills/nuxt-4-frontend-patterns/SKILL.md">
<violation number="1" location="skills/nuxt-4-frontend-patterns/SKILL.md:260">
P2: The new Google Analytics example depends on `@nuxt/scripts` (`useScriptGoogleAnalytics`) but the guide omits required setup, so the snippet can fail in a baseline Nuxt app.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
There was a problem hiding this comment.
2 issues found across 1 file (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="skills/nuxt-4-frontend-patterns/SKILL.md">
<violation number="1" location="skills/nuxt-4-frontend-patterns/SKILL.md:392">
P2: The guide labels `useLocalStorage`/theme composables as “SSR-safe” without clarifying first-render hydration risks, which can mislead readers into rendering client-derived values directly and reintroducing hydration mismatch.</violation>
<violation number="2" location="skills/nuxt-4-frontend-patterns/SKILL.md:448">
P2: Debounced search example can show stale results due to out-of-order async responses (no cancellation or sequencing).</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| @@ -0,0 +1,536 @@ | |||
| --- | |||
There was a problem hiding this comment.
P2: The guide labels useLocalStorage/theme composables as “SSR-safe” without clarifying first-render hydration risks, which can mislead readers into rendering client-derived values directly and reintroducing hydration mismatch.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At skills/nuxt-4-frontend-patterns/SKILL.md, line 392:
<comment>The guide labels `useLocalStorage`/theme composables as “SSR-safe” without clarifying first-render hydration risks, which can mislead readers into rendering client-derived values directly and reintroducing hydration mismatch.</comment>
<file context>
@@ -392,7 +389,7 @@ All VueUse composables are auto-imported — no manual imports needed.
<script setup lang="ts">
// Not good: raw localStorage causes hydration mismatch
-const theme = ref(localStorage.getItem('theme') || 'light')
+// const theme = ref(localStorage.getItem('theme') || 'light')
// Good: useLocalStorage is SSR-safe via @vueuse/nuxt
</file context>
There was a problem hiding this comment.
2 issues found across 1 file (changes from recent commits).
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="skills/nuxt-4-frontend-patterns/SKILL.md">
<violation number="1" location="skills/nuxt-4-frontend-patterns/SKILL.md:247">
P2: Nuxt Scripts composables are documented without the required `@nuxt/scripts` setup, so readers may hit missing composable/auto-import errors.</violation>
<violation number="2" location="skills/nuxt-4-frontend-patterns/SKILL.md:438">
P2: Debounced-search example leaves `error` sticky, so a past failure can permanently mask later successful results.</violation>
</file>
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
| ### Third-Party Script Management | ||
|
|
||
| ```vue | ||
| <script setup lang="ts"> |
There was a problem hiding this comment.
P2: Nuxt Scripts composables are documented without the required @nuxt/scripts setup, so readers may hit missing composable/auto-import errors.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At skills/nuxt-4-frontend-patterns/SKILL.md, line 247:
<comment>Nuxt Scripts composables are documented without the required `@nuxt/scripts` setup, so readers may hit missing composable/auto-import errors.</comment>
<file context>
@@ -243,7 +243,8 @@ Control when components become interactive — reduces JavaScript work on initia
-```typescript
+```vue
+<script setup lang="ts">
// Good: controlled loading with useScript
const { load, proxy } = useScriptGoogleAnalytics({
</file context>
d6a01ae to
046bc0e
Compare
| ```vue | ||
| <script setup lang="ts"> | ||
| const isDark = useDark() | ||
| const toggleDark = useToggle(isDark) | ||
| </script> | ||
|
|
||
| <template> | ||
| <button @click="toggleDark()"> | ||
| {{ isDark ? 'Light Mode' : 'Dark Mode' }} | ||
| </button> | ||
| </template> | ||
| ``` |
There was a problem hiding this comment.
useDark() potential hydration mismatch not documented
useDark() reads from localStorage and/or window.matchMedia('(prefers-color-scheme: dark)') on the client. On the server, neither is available, so isDark always resolves to the initial default (typically false). If the user's system or stored preference is dark, the server renders "Dark Mode" (button label) but the client hydrates with "Light Mode" — a hydration mismatch — which is exactly the class of bugs this document warns against in its Hydration Safety section.
A more robust pattern for SSR-safe dark mode is to persist preference in a cookie (readable on both server and client) and initialise useDark from it:
<script setup lang="ts">
// Read server-accessible cookie so SSR and client agree on initial value
const colorModeCookie = useCookie<'dark' | 'light'>('color-mode', { default: () => 'light' })
const isDark = computed({
get: () => colorModeCookie.value === 'dark',
set: (val) => { colorModeCookie.value = val ? 'dark' : 'light' },
})
const toggleDark = useToggle(isDark)
</script>At minimum, add a callout that useDark() can cause a hydration flash and pair it with <ClientOnly>, or recommend @nuxtjs/color-mode which handles this correctly.
| ```vue | ||
| <template> | ||
| <!-- Good: CSS handles layout — no hydration mismatch --> | ||
| <MobileNav class="md:hidden" /> | ||
| <DesktopNav class="hidden md:block" /> | ||
| </template> |
There was a problem hiding this comment.
CSS-only approach mounts both components simultaneously
The CSS-first pattern shown here renders both <MobileNav> and <DesktopNav> in the DOM at all times — only visibility is toggled with Tailwind classes. This means both components are instantiated, have their lifecycle hooks executed, fire their own data-fetching calls (useFetch/useAsyncData), and consume memory. For lightweight nav components this is fine, but as written this is presented as a universal good practice without caveating the trade-off.
Consider adding a note so developers know when this pattern is appropriate vs. when the useBreakpoints/ssrWidth approach (which does conditionally mount) is preferable:
<!-- Good: CSS handles layout — no hydration mismatch -->
<!-- Note: both components are mounted; prefer this only for lightweight components -->
<MobileNav class="md:hidden" />
<DesktopNav class="hidden md:block" />|
Thanks for the detailed Nuxt 4 patterns skill! The content quality is high -- hydration safety, route rules, VueUse integration, and performance patterns are all well-covered. This PR now likely has merge conflicts from recent merges that updated component counts in AGENTS.md and README.md. Could you rebase on the latest |
|
Superseded by rebased PR |
What Changed
Added a new nuxt-4-frontend-patterns skill covering production-grade Nuxt 4 / Vue 3 patterns including hydration safety, performance optimization, route rules, lazy loading, plugin best practices, data fetching (useFetch, useAsyncData, useState), and VueUse integration for SSR-safe applications.
Why This Change
Expands the ECC skill catalog with Nuxt 4 frontend patterns, giving users actionable guidance for building performant, SSR-safe Nuxt applications. This fills a gap in the existing skill set which had no Vue/Nuxt specific coverage.
Testing Done
node tests/run-all.js)Type of Change
fix:Bug fixfeat:New featurerefactor:Code refactoringdocs:Documentationtest:Testschore:Maintenance/toolingci:CI/CD changesSecurity & Quality Checklist
Documentation
Summary by cubic
Adds the new
nuxt-4-frontend-patternsskill with production-ready patterns for SSR-safe hydration, performance, data fetching, and VueUse in Nuxt 4/Vue 3. Also refines frontmatter and examples so the skill renders cleanly and is easy to scan.New Features
useState/useCookie, browser-only guards,ClientOnly.prerender,swr,isr,ssr: false), lazy loading/hydration, NuxtLink prefetch, NuxtImg.useFetch/useAsyncDatawith headers; prefer composables; parallel plugin loading;@vueuse/nuxtwith SSR-safe storage and CSS-first breakpoints.Bug Fixes
<script setup>, declared refs, resolved keyboard shortcut runtime errors.useAsyncDatacallback and fixed an improperuseFetch-in-callback pattern.useScriptexample and hardened it against ad blockers; strengthened debounced search.Written for commit 046bc0e. Summary will update on new commits.
Summary by CodeRabbit