2026 landscape

Vue 3.5 and the ecosystem

The Vue features that matter for SSR, the status of 3.6, the modules an interviewer expects you to know by name, and the CLI commands you should use without thinking.

Vue 3.5 is the version Nuxt 4 runs on, and three of its additions exist specifically to make server rendering less painful. Knowing them by name, and knowing which problem each solves, is a cheap way to sound current.

Know — Vue 3.5 for SSR

  • useId() produces identifiers that are stable across server and client. The correct fix for generated id, for and aria-* attributes, which were one of the classic hydration mismatches (hydration).
  • useTemplateRef() replaces the "declare a ref whose name matches the attribute" convention with an explicit call, which is clearer and works with dynamic names.
  • Lazy hydration strategies power Nuxt's hydrate-on-visible / -idle / -interaction / -media-query / hydrate-after / hydrate-when / hydrate-never on Lazy* components (performance).
  • data-allow-mismatch whitelists an expected mismatch on one element, with values text, children, class, style, attribute (no value allows all). The escape hatch for a deliberately client-formatted timestamp.
  • Reactive props destructure makes const { count } = defineProps() keep reactivity, which removes a common source of subtle bugs in shipped components.
  • Vue 3.6 and Vapor mode are in release candidates. Say "release candidate" rather than describing it as shipped, and check the tags before the interview.

Know — the ecosystem by name

PackageOne line
@nuxt/uicomponent library on Tailwind, v4; pulls in icons, fonts and color mode
@nuxt/contentfile-based content with a SQLite-backed query layer, v3
@nuxt/imageresponsive images, modern formats, <NuxtImg> / <NuxtPicture>
@nuxt/fontsself-hosted web fonts with fallback metric overrides (the CLS fix)
@nuxt/scriptsthird-party scripts with load triggers and facades
@nuxt/iconicon component with server and client bundles
@nuxt/eslintproject-aware flat ESLint config, including the Nuxt-specific rules
@nuxt/test-utilsfixture E2E plus the Vitest nuxt environment
@nuxt/devtoolsin-app inspector: payload, components, hooks, timings
@pinia/nuxtstate management; createPinia() per app instance on the server
@nuxtjs/i18nrouting-aware internationalisation; cooperates through hooks
nuxt-auth-utilssession helpers and providers for auth
@nuxtjs/tailwindcssTailwind integration; with Tailwind v4 the CSS-first setup often replaces it
nuxt-securitysecurity headers and CSP
@nuxtjs/color-modelight and dark handling used by many UI layers

Know — the CLI worth muscle memory

npx nuxt upgrade --dedupe   # upgrade Nuxt and flatten duplicate installs
npx nuxt module add <name>  # install and register a module
npx nuxt typecheck          # vue-tsc against the generated tsconfigs
npx nuxt analyze            # client and server bundle treemaps
npx nuxt prepare            # regenerate .nuxt types (what postinstall runs)
npx nuxt info               # environment report to paste into a bug report
npx nuxt devtools enable    # toggle DevTools for a project

How it works

The three Vue 3.5 APIs, in the shape a layer author uses them:

layers/base/app/components/Team/Field.vue
<script setup lang="ts">
const { label, hint } = defineProps<{ label: string, hint?: string }>()

// Stable across server and client: no hydration mismatch on the label/input association.
const id = useId()
const input = useTemplateRef<HTMLInputElement>('input')

defineExpose({ focus: () => input.value?.focus() })
</script>

<template>
  <div class="field">
    <label :for="id">{{ label }}</label>
    <input :id="id" ref="input">
    <!-- A deliberately client-formatted value: whitelist the mismatch instead of wrapping in ClientOnly -->
    <p v-if="hint" data-allow-mismatch="text" class="hint">{{ hint }}</p>
  </div>
</template>
Gotcha· Naming a version you did not check

"Vue 3.6 with Vapor mode is out" is the kind of statement an interviewer can disprove from their phone. Say what you know ("3.5 is what Nuxt 4 uses; 3.6 was in release candidates last I looked") and it reads as rigour rather than ignorance.

Verify before the interview:

The current stable Vue version and whether 3.6 (Vapor mode) has shipped. Check the tags the week of the interview.

docs ↗

Exercise

Exercise
  • Replace a hand-rolled id in one of your components with useId() and confirm the server HTML and the client render agree.
  • Open the Nuxt modules directory and, for each package in the table above, write one sentence on when you would reach for it. Say them out loud; this is a warm-up question in most interviews.
  • Run nuxt info on the playground and read every line. Knowing what it reports makes you faster at triaging consumer bug reports.

Be able to say

Be able to say· Which Vue 3.5 features matter for server rendering?

"Four. useId gives identifiers that agree between server and client, which removes a whole class of hydration mismatches in shipped form components. Lazy hydration strategies let a component render on the server but hydrate on visibility, idle or interaction, which moves hydration CPU off the critical path. data-allow-mismatch whitelists a mismatch you genuinely expect, such as a client-formatted timestamp, instead of reaching for <ClientOnly> and losing the server render. And reactive props destructure removes a common source of subtle bugs in library components. Vue 3.6 with Vapor mode was still in release candidates when I last checked."