news May 07, 2026 · 7 views · 3 min read

Optimize Vue and Nuxt with 13 Essential AI Coding Rules

Discover 13 crucial rules for creating AI-generated, composable, and server-side ready components in Vue.js and Nuxt.js. These guidelines ensure your codebase stays modern and efficient, aligning with the latest Vue 3 and Nuxt 3 standards.

Introduction

In the rapidly evolving world of web development, staying up-to-date with the latest practices is crucial. For developers working with Vue.js and Nuxt.js, adhering to modern coding standards is essential to ensure efficiency and performance. Here, we explore 13 key rules that guide AI in generating composable, server-side rendering (SSR) ready components, tailored for Vue 3 and Nuxt 3.

1. Embrace the Composition API

Use the Composition API with <script setup> exclusively. Avoid the Options API, as it does not scale well with new features and complicates TypeScript usage. Mixins are deprecated in favor of composables, which offer better type checking.

<script setup lang="ts">
const props = defineProps<{ userId: string }>()
const { data: user } = await useFetch(`/api/users/${props.userId}`)
</script>

2. Composables: Functionality Without Rendering

Composables should function as nouns, like useUser() or useCart(), returning reactive states without handling rendering. Always return refs to maintain reactivity.

// composables/useUser.ts
export function useUser(id: Ref<string>) {
  const { data, pending, error } = useFetch(() => `/api/users/${id.value}`)
  return { user: data, pending, error }
}

3. Maintain Reactivity

Opt for ref for primitive values and reactive only for stable object structures. Avoid destructuring reactive, which disrupts reactivity.

4. Use Pinia for State Management

Adopt Pinia with setup-store syntax, creating one store per domain. This approach eliminates the need for Vuex's complex mutations and modules.

// stores/cart.ts
export const useCartStore = defineStore('cart', () => {
  const items = ref<CartItem[]>([])
  const total = computed(() => items.value.reduce((s, i) => s + i.price, 0))
  function add(item: CartItem) { items.value.push(item) }
  return { items, total, add }
})

5. Optimize Data Fetching

Fetch data on the server using useFetch or useAsyncData to improve initial load times instead of using onMounted.

<script setup lang="ts">
const route = useRoute()
const { data: post } = await useAsyncData(
  `post-${route.params.id}`,
  () => $fetch(`/api/posts/${route.params.id}`)
)
</script>

6. Secure Server Routes

Place server routes in server/api/, using Zod for validation and ensuring end-to-end typing.

// server/api/posts.post.ts
import { z } from 'zod'
const Body = z.object({ title: z.string().min(1).max(120) })

export default defineEventHandler(async (event) => {
  const session = await requireUserSession(event)
  const body = Body.parse(await readBody(event))
  return await db.post.create({ data: { ...body, userId: session.user.id } })
})

7. Enforce TypeScript Strictness

Use <script setup lang="ts"> with strict TypeScript settings to catch potential errors early.

8. Clean Template Practices

Avoid using v-if and v-for on the same element, and ensure keys are stable IDs.

9. Respect Prop Immutability

Props should remain read-only. Use events or defineModel() for two-way data binding when necessary.

10. Utilize Auto-Imports

Leverage Nuxt's auto-import feature for cleaner code and fewer merge conflicts.

11. Manage Error and Loading States

Implement a root error.vue and use <NuxtLoadingIndicator> for better UX during loading.

12. Prioritize Testing

Adopt Vitest and @vue/test-utils, focusing on real component mounting and role-based querying.

13. Enhance Performance

Use <NuxtImage>, <NuxtLink>, and lazy-load heavy components to optimize performance.

Conclusion

Discussion

0 Comments

Leave a Comment

Comments are moderated and will appear after approval.