Clean Nuxt code is not about formatting. It is about predictable structure, safe reactivity, and clear boundaries between your app, server, and shared code. Here is the practical checklist I follow on every Vue 3 / Nuxt 3–4 project.
Components & reactivity
- Use
<script setup lang="ts">everywhere. It is the most concise, fully typed Composition API syntax and the default for modern Nuxt. - Destructure props safely. In modern Vue, destructuring from
definePropskeeps reactivity, but if you need a default that stays reactive, lean on reactive props destructure ortoRef— never read a destructured prop expecting it to be a plain copy. - Use
defineModel()for two-way binding instead of the oldprop + emit('update:..')boilerplate. - Keep business logic out of templates. Templates describe the UI; move conditions and transformations into computed values or composables.
- Keep components small and focused. If a component owns several responsibilities, split it.
State & stores (Pinia)
- Do not destructure a Pinia store directly — you lose reactivity. Use
storeToRefs()for state and getters, and destructure actions only. - Keep stores domain-based (one store per business domain) instead of one giant global store.
Reusing logic the Nuxt way
- Pull reusable logic into composables (
useX) instead of duplicating it across components. - Use auto-imports, but keep names clear. Auto-import is powerful; explicit, descriptive names keep it from becoming magic.
- Use the
shared/directory for code used by both the app and the server so universal helpers live in one place. - Separate app code from server code. Server-only logic lives under
server/and must never leak into the client bundle.
Data fetching & types
- Be deliberate with
useFetchvsuseAsyncData. Reach foruseFetchfor simple requests anduseAsyncDatawhen you need custom keys, transforms, or to control caching. - Type your API responses. Define interfaces for what the backend returns instead of leaning on
any. - Validate important data (forms, query params, webhook payloads) with a schema such as Zod before you trust it.
Project conventions
- Prefer feature-based folders for large apps over splitting purely by file type.
- Use explicit component names so they are easy to find and debug.
- Standardise formatting and linting (ESLint + Prettier) so style is automatic, not a review topic.
- Read runtime config correctly — keep secrets server-side and expose only what the client truly needs via
runtimeConfig.public. - Prefer readable code over clever code.
Remember: clean code is not about rules. It is about clarity, maintainability, and making the next developer's life easier.


