Software development

React or Vue, which one? Nuxt.js: why it is the framework I work with every day

React and Vue compared by someone who has used both: single-file components, reactivity, structure. Then Nuxt.js: routing, hybrid rendering, server and modules.

Fabio Folgori7 min read

A man walking through a mountain valley among pine trees, away from the screens
Photo by Kirill Fokin on Unsplash

When an agency asks me what to build a new project on, the question is usually "React or Vue?". My answer is a third name: Nuxt.js. Among developers it is less known than it deserves, so here is where the choice comes from: first why I prefer Vue to React, which I have also used in production, then why I rarely settle for Vue alone.

React and Vue: same goals, different ways

React and Vue solve the same problem: building component-based interfaces that update when data changes. Both use a virtual DOM, both have a solid ecosystem, both handle large projects. I wrote the structure and the frontend of a wallet shipped as a Chrome extension in React, TypeScript and Redux, so I am not speaking from hearsay. The difference that matters to me is in how you write code every day.

The single-file component

In Vue a component is a .vue file with three separate blocks: <template> for markup, <script setup> for logic, <style scoped> for styles limited to that component. Everything has its place, and when you open a file you know immediately where to look.

In React the component markup is commonly described with JSX, together with the logic that composes it; styles can live in separate files, CSS Modules or other systems. It is a consistent choice, and some people prefer it for exactly that reason. It has always bothered me: I prefer the explicit separation of Vue components. In both ecosystems readability also depends on component size and project conventions.

Small daily frictions

Then there is a detail that looks trivial and is not: in JSX the class attribute becomes className, for becomes htmlFor, inline styles become objects. In Vue the template is HTML, with directives (v-if, v-for, v-model) added where needed. I can paste a snippet from a prototype or a design handoff and it works; with JSX it has to be rewritten.

Reactivity

With Vue I declare state with ref or reactive and a derived value with computed: the framework tracks dependencies on its own and updates only what is needed. In React updates follow a different model and effects require attention to their dependencies. useMemo and useCallback are optimisations to evaluate, not requirements for every component; in projects that adopt the React Compiler part of the memoisation is automatic. Vue too requires attention to effects, dependencies and expensive updates. For the way I work, its model remains more immediate.

For all these reasons, between the two I chose Vue: not because React is worse, but because with Vue I write better, faster and with fewer mistakes. Having written code since 1999, I have learned that the tool you work well with matters more than the popularity charts.

Why I do not use Vue on its own

Vue is a framework for building interfaces. A real site needs many other things: addresses and routing, server-side rendering for SEO and speed, data fetching, metadata, languages, a server part for APIs. With plain Vue all of these have to be chosen, wired together and maintained by hand. Nuxt.js is Vue with all of this already integrated and coherent: I can do everything I would do with Vue, but with superpowers.

File-based routing

In the default structure of Nuxt 4, a file in app/pages/ defines a page; app/pages/servizi/[slug].vue defines a dynamic route. No router configuration to keep aligned. Layouts and navigation middleware follow the framework's conventions. Middleware can handle redirects, but authentication and authorisation must also be enforced on the server endpoints.

Hybrid rendering, page by page

Nuxt.js can render pages on the server at every request, generate them ahead of time as static HTML, or do both in the same project. With routeRules I decide route by route: content pages generated at build time, a private area rendered only in the browser, a listing refreshed with a cache that renews in the background. The engine underneath is the same.

A server included

Nuxt.js includes Nitro, a server engine: a file in server/api/ becomes an endpoint. On this site the AI chat, the sitemap and the RSS feeds are Nitro server routes. Nitro offers presets for several platforms, but the switch requires checking the available APIs, dependencies, storage, execution limits and configuration.

Data without duplicate requests

useFetch and useAsyncData fetch data on the server and pass it to the browser along with the page: during hydration the client does not repeat the same call. It sounds like a detail, but it is one of the most common mistakes in hand-built applications.

Modules instead of glue

Languages with @nuxtjs/i18n (with localised URLs: /servizi in Italian, /en/services in English), Markdown content with Nuxt Content, optimised fonts with @nuxt/fonts, SEO with useSeoMeta. Each module is added to the configuration and integrates with the rest, instead of being a library to wire up by hand.

Less boilerplate

Components and composables are auto-imported, TypeScript is configured from the start, Vite makes development instant. Heavy components load only when needed: the 3D scene on this home page, built with three.js, loads only in the browser and only where it appears.

Where I have used Nuxt.js

This site is built with Nuxt 4: Markdown content, two languages, static generation and publishing with GitHub and Netlify (I explain it in Deploying a site with GitHub and Netlify). Altura Vela is a custom management system in Nuxt 4 connected to a REST API, with a calendar, areas for members and skippers, contracts and payments. Fix and Sail is a Nuxt.js application on Strapi. Three very different projects, one foundation.

When Nuxt.js is not the right choice

  • The team only knows React, or the project is required to use it. If I have to choose React, I reason as I do for Vue: I do not use it alone but with the framework on top of it, so Next.js, the equivalent of Nuxt.js. The same reasons (file-based routing, hybrid rendering, a server part), the same discipline; imposing Vue would be a cost.
  • The site needs a rich panel used every day by many people. There WordPress often remains the most sensible choice, as I explain in From WordPress to Nuxt.js, GitHub and Netlify.
  • You need a library that only exists for React. It happens, especially with some very specific UI components: check before choosing.

SSR, hydration and private data

The first HTML and the first browser rendering must describe the same state. Random values, dates calculated in different time zones and browser reads during server rendering can produce hydration differences. I isolate the APIs available only in the browser and check the warnings during direct access to the pages.

With useFetch and useAsyncData the payload can avoid duplicate fetching during hydration, provided keys and options are consistent. I do not transfer secrets or fields the user must not see to the client: hiding them in the template does not remove them from the payload. Sensitive state must be isolated per request, with no shared singletons between users. Caching and prerendering must not be applied indiscriminately to personal responses.

These constraints matter more than the syntactic preference for Vue or React when designing a private area.

My take

Nuxt.js is at the centre of a set of choices that hold together: Vue and TypeScript for components, Tailwind v4 with design tokens in @theme for styling (I discuss it in Tailwind CSS: why I use it), versioned Markdown content, few modules and few dependencies, components loaded only where they are needed, every change with its own preview before going live. This site's chat, anchored to a single knowledge file, and the 404 page with the video game were born that way: small pieces of code that stay in their place. That is what I look for in a tool, more than its popularity.

Why work with me

Since 1999 I have delivered more than 300 projects, and as a freelancer I work with more than 30 agencies, from Rome and remotely. With Nuxt.js I build fast, multilingual sites that are easy to evolve, and custom management systems that grow without changing their technical foundation.

If you are weighing the stack for a new project, get in touch: in a call of about 20 minutes we can work out whether Nuxt.js is the right choice. The service is under Website development.

Frequently asked questions

Vue is a framework for building the interface: components, reactivity, templates. Nuxt.js is the framework built on top of Vue that adds everything a full site or application needs: file-based routing, server-side rendering or static generation, a server part for APIs, handling of SEO, data and modules.

Yes, in the sense that it plays the same role: Next.js is the reference framework for React, Nuxt.js the one for Vue. The main features are similar (file-based routing, hybrid rendering, a server part); the underlying library and the way components are written differ.

React has a larger ecosystem and more developers available. Vue and Nuxt.js are however mature, actively maintained and have been used in production for years. For a project, what matters more is that the code is tidy and documented: a well-written Vue component is easy to read even for someone coming from React.

Yes. With static generation a Nuxt.js site becomes a set of HTML files published on a CDN, with no server to maintain. The same foundations then support an application with private areas and APIs, without switching tools.

  • #nuxt
  • #vue
  • #react
  • #javascript
  • #architecture

More articles

// Contact

A project, a problem or just a question?

Agency, business or professional: choose how you'd rather talk to me. I reply as soon as I can, no strings attached.