install
source · Clone the upstream repo
git clone https://github.com/Intense-Visions/harness-engineering
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/claude-code/nuxt-composables-pattern" ~/.claude/skills/intense-visions-harness-engineering-nuxt-composables-pattern && rm -rf "$T"
manifest:
agents/skills/claude-code/nuxt-composables-pattern/SKILL.mdsource content
Nuxt Composables Pattern
Fetch data and coordinate async state across server and client using Nuxt's built-in composables
When to Use
- You need to fetch data in a Nuxt page or component with SSR/SSG support
- You want to avoid duplicate requests (server fetches, client rehydrates)
- You are choosing between
,useFetch
, anduseAsyncDatauseLazyFetch - You need access to the Nuxt application instance (
) for plugins or runtime configuseNuxtApp
Instructions
- Use
as the default for HTTP requests — it wrapsuseFetch
+useAsyncData
and handles SSR deduplication automatically:$fetch
// pages/posts/[id].vue const { data: post, pending, error } = await useFetch(`/api/posts/${route.params.id}`);
- Use
when the async operation is not a simple HTTP call (e.g., database query via a server composable, computed key based on reactive state):useAsyncData
const { data: user } = await useAsyncData( 'user-profile', // unique cache key — required () => fetchUserProfile(userId.value), { watch: [userId] } // re-fetch when userId changes );
- Use
/useLazyFetch
to defer data loading — the page renders immediately anduseLazyAsyncData
is true until data arrives:pending
// Good for non-critical data below the fold const { data: comments, pending } = useLazyFetch('/api/comments');
-
Always provide a unique string key to
. Keys collide across components — use route params or namespacing to avoid cache pollution.useAsyncData -
Use
directly only in event handlers (button clicks, form submissions) — not at the top of$fetch
, which would bypass SSR deduplication:setup()
// Good: event handler async function submitForm() { await $fetch('/api/contact', { method: 'POST', body: formData.value }); } // Bad: top-level setup — use useFetch instead const data = await $fetch('/api/posts'); // runs on both server AND client
- Transform responses inline with the
option to avoid storing raw API shapes:transform
const { data: posts } = await useFetch('/api/posts', { transform: (raw) => raw.items.map((p) => ({ id: p.id, title: p.title })), });
- Access Nuxt internals with
:useNuxtApp()
const { $toast, $i18n, ssrContext } = useNuxtApp();
Details
Nuxt's data fetching composables solve a fundamental SSR problem: if you use plain
fetch() or axios in setup(), the request fires on the server during SSR and again on the client during hydration — doubling your API calls. useFetch and useAsyncData solve this by serializing the server-fetched data into the HTML payload and rehydrating it on the client without a second network request.
Key differences:
| Composable | Use case | Blocks navigation |
|---|---|---|
| Simple HTTP calls | Yes (await) |
| Custom async logic, reactive keys | Yes (await) |
| Non-blocking HTTP | No |
| Non-blocking custom async | No |
| Event handlers only | N/A |
Cache key design:
useAsyncData keys are global within a Nuxt app instance. Two components using useAsyncData('posts', ...) will share data. This is often desired (shared cache) but causes bugs when the same key is used with different fetch functions. Pattern: <entity>-<id> or <page>-<section>.
Error handling:
const { data, error } = await useFetch('/api/posts'); if (error.value) { throw createError({ statusCode: 500, message: 'Failed to load posts' }); }
Refreshing data:
const { data, refresh } = await useFetch('/api/posts'); // Later: await refresh();
Source
https://nuxt.com/docs/getting-started/data-fetching
Process
- Read the instructions and examples in this document.
- Apply the patterns to your implementation, adapting to your specific context.
- Verify your implementation against the details and edge cases listed above.
Harness Integration
- Type: knowledge — this skill is a reference document, not a procedural workflow.
- No tools or state — consumed as context by other skills and agents.
Success Criteria
- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.