--- name: ssr-best-practices description: Avoiding SSR context leaks, hydration mismatches, and proper composable usage --- # SSR Best Practices Patterns for avoiding common SSR pitfalls: context leaks, hydration mismatches, and composable errors. ## The "Nuxt Instance Unavailable" Error This error occurs when calling Nuxt composables outside the proper context. ### ❌ Wrong: Composable Outside Setup ```ts // composables/bad.ts // Called at module level - no Nuxt context! const config = useRuntimeConfig() export function useMyComposable() { return config.public.apiBase } ``` ### ✅ Correct: Composable Inside Function ```ts // composables/good.ts export function useMyComposable() { // Called inside the composable - has context const config = useRuntimeConfig() return config.public.apiBase } ``` ### Valid Contexts for Composables Nuxt composables work in: - ` ``` ### ✅ Correct: Use SSR-safe Alternatives ```vue ``` ### ❌ Wrong: Random/Time-based Values ```vue ``` ### ✅ Correct: Use useState for Consistency ```vue ``` ### ❌ Wrong: Conditional Rendering on Client State ```vue ``` ### ✅ Correct: Use CSS or ClientOnly ```vue ``` ## Browser-only Code ### Use `import.meta.client` ```vue ``` ### Use `onMounted` for DOM Access ```vue ``` ### Dynamic Imports for Browser Libraries ```vue ``` ## Server-only Code ### Use `import.meta.server` ```vue ``` ### Server Components ```vue ``` ## Async Composable Patterns ### ❌ Wrong: Await Before Composable ```vue ``` ### ✅ Correct: Get Context First ```vue ``` ## Plugin Best Practices ### Client-only Plugins ```ts // plugins/analytics.client.ts export default defineNuxtPlugin(() => { // Only runs on client initAnalytics() }) ``` ### Server-only Plugins ```ts // plugins/server-init.server.ts export default defineNuxtPlugin(() => { // Only runs on server initServerConnections() }) ``` ### Provide/Inject Pattern ```ts // plugins/api.ts export default defineNuxtPlugin(() => { const api = createApiClient() return { provide: { api, }, } }) ``` ```vue ``` ## Third-party Library Integration ### ❌ Wrong: Import at Top Level ```vue ``` ### ✅ Correct: Dynamic Import ```vue ``` ### Use ClientOnly Component ```vue ``` ## Debugging SSR Issues ### Check Rendering Context ```vue ``` ### Use Nuxt DevTools DevTools shows payload data and hydration state. ### Common Error Messages | Error | Cause | |-------|-------| | "Nuxt instance unavailable" | Composable called outside setup context | | "Hydration mismatch" | Server/client HTML differs | | "window is not defined" | Browser API used during SSR | | "document is not defined" | DOM access during SSR |