Skip to content
Community content. Review instructions before giving them to an AI agent — treat modules like open-source code.

Vue Nuxt Conventions

Vue and Nuxt conventions: Composition API defaults, composables for shared logic, props-down-events-up data flow, computed over methods for derived data, single-file component structure, and Nuxt server routes and data fetching.

Mby @markdownersPublished August 21, 2026 · ~3 min read

0 downloads · Used by 0 stacks

Default to the Composition API with <script setup> for every new component, extract any stateful logic used by more than one component into a composable, and let data flow down through props and back up through events — never the reverse.

Composition API by default

  • Write new components with <script setup> and the Composition API rather than the Options API — it colocates related logic (a piece of state and the functions that use it) instead of splitting it across data/methods/computed blocks, and composes better via composables.
  • Only reach for the Options API when maintaining existing Options-API code in the same style, or when a specific library requires it — never mix both APIs within the same component.
  • Type props and emits explicitly (defineProps<T>(), defineEmits<T>()) rather than relying on runtime-only prop declarations, so prop misuse is caught at compile time.

Composables for shared logic

  • Extract any reactive stateful logic shared by two or more components (a debounced search, a media query, paginated fetching) into a use*-named composable in a composables/ directory, not copy-pasted ref/watch blocks per component.
  • Return only the reactive state and functions a composable's consumers actually need, not internal implementation details — a composable's return object is its public API.
  • A composable should manage its own cleanup (onUnmounted for subscriptions/listeners it sets up) so consumers don't need to remember to tear it down.

Props down, events up

  • Pass data into a child exclusively through props and let a child communicate back exclusively through emitted events — never have a child directly mutate a prop it received, and never reach into a child's internals from a parent via a template ref to change its state.
  • Use v-model (or multiple v-model:x bindings) for genuine two-way bound fields instead of manually wiring a prop plus an update: event by hand.
  • When several sibling components need to share state, lift that state to their common parent (or a composable/store) rather than having siblings communicate through a chain of event bubbling.

Computed over methods for derived data

  • Use a computed property for any value derived from reactive state (a filtered list, a formatted total) so it's cached and only recalculates when its dependencies change — a method called from the template recalculates on every render regardless of whether its inputs changed.
  • Never assign to a computed's dependencies from inside the computed getter itself, and never give a computed side effects — a computed must be a pure derivation; side effects belong in a watch or an event handler.
  • Prefer a computed over a watch plus a separate ref whenever the value can be expressed as a pure function of existing state — a watch that mirrors one ref into another is usually a computed in disguise.

Single-file component structure

  • Order a single-file component consistently: <script setup> first, then <template>, then <style scoped> — pick one order for the whole codebase and keep it uniform so components are navigable by habit.
  • Scope styles to the component (<style scoped> or CSS modules) by default; reach for global styles only for genuinely app-wide concerns (resets, design tokens), not per-component overrides.
  • Keep a single-file component focused on one piece of UI; extract a subtree into its own component once its template exceeds roughly what fits on one screen or it accumulates unrelated concerns.

Nuxt server routes and data fetching

  • Put server-only logic (calls that need secrets, direct database access) in server/api/ routes, never in a page/component that would ship that logic or its secrets to the client bundle.
  • Use Nuxt's data-fetching composables (useFetch/useAsyncData) for data needed at render time instead of manual onMounted plus a fetch call — they integrate with SSR, dedupe requests, and avoid a client-side loading waterfall after hydration.
  • Key every useFetch/useAsyncData call explicitly when the same composable is called with varying parameters (e.g., a route param) so Nuxt doesn't serve a cached response for the wrong parameters.
Badge

Link back to this module from your own README.

Get it on Markdowners
[![Get it on Markdowners](https://markdowners.com/mdstack-badge.svg)](https://markdowners.com/m/markdowners/vue-nuxt-conventions)

Comments (0)

Sign in to comment. Sign in

No comments yet. Be the first to add one.

Discussions about this module

No discussions about this module yet.

Start a discussion