Blogs
Nuxt UI: Unapologetically complete
ModulesWeb development moves very fast these days and honestly, picking the right UI setup can either make your life chill or total chaos. What Nuxt UI offers is basically a UI plug-and-play kit for Nuxt and Vue apps. It smashes together Tailwind CSS, Reka UI, and a ton of useful components into one neat package so you don’t end up gluing 5 different libraries like a mad scientist.
So… what even is Nuxt UI?
It’s an open-source UI library with 100+ ready-to-use and tweakable components, built with Nuxt in mind so it just feels natural, like it belongs there. No alien dependencies, no weird setup rituals. Just vibes.
Why it’s so popularYou get EVERYTHING in one box
Buttons, forms, modals, dashboards, icons: all styled, all accessible, all ready. Here’s a bigger list:Inputs, selects, toggles, checkboxes
Nav bars, sidebars, tabs, tables
Modals, popovers, toast alerts
Entire landing page and dashboard layouts
Even chat UI bits if you’re feeling fancy
And yes, keyboard and screen reader support are built-in. You love to see it.
Accessibility isn’t your problem anymore
Proper ARIA tags, focus handling, keyboard support, all done. You don’t have to manually fight for your app to be usable for everyone, it just is by default.TypeScript actually works with it
Which means no more guessing what props a component wants. Your editor will hold your hand:Auto-complete
Type checking
Fewer “why is this broken in production” moments
Theming is very easy
It uses CSS variables for all design tokens, so switching stuff like colors or dark mode is a breeze. No complex design token spreadsheets, just change a value and boom, your app looks different everywhere.First class support for Nuxt
Auto-imports? Yes. SSR support? Obviously. Plays nice with all Nuxt optimizations? For sure.
It even works smoothly with popular Nuxt addons like:Content module
Color mode for dark/light toggle
Iconify for like 200k icons
i18n for multi-language stuff
Just install the module and add it to your config file and that’s literally it. No extra config for Tailwind, icons, theme, etc. It handles all that jazz for you so you can go make stuff that matters.
It's better than the usual “install 10 packages” approach
Normally when starting a Nuxt app, you have to:Install Tailwind
Install icons
Install a headless UI kit
Install dark mode helpers
Install form validation tools
Pray they all get along
Wire it all together manually
Cry a little
Which means:Fewer updates to keep track of
Everything actually matches design-wise
Smaller final bundle because it auto tree-shakes
You start shipping faster than your coffee cools
So to sum it up, Nuxt UI is desirable because it saves time. It was made with developer experience in mind and everything looks clean with proper defaults. Do won’t have NPM dependency headaches from it and it let’s you focus on building your app without stress.
So the question isn't whether Nuxt UI is worth using, but rather: can you afford not to use it?Nuxt Hints: A new core module dropped right before the end of the year
ModulesIf you’ve ever worked with Server Side Rendered applications, you’ve quickly realized hydration errors can be a pain. What’s even more painful is finding where the errors come from and how to resolve them. Well, look no further! The new nuxt/hints module can be just the right tool for you to use!
Nuxt Hints gives real-time feedback on your app’s performance, accessibility, and security and it does it directly inside your browser via the devtools. While you could still manually audit your site (e.g. running external tooling, code reviews, etc.), with nuxt/hints you get actionable insights as you build. You spot slow-loading third-party scripts, hydration mismatches, or suboptimal layouts for web vitals.
Before diving deeper into it, let’s make some things clear:Nuxt Hints integrates directly into the Nuxt DevTools, so the insights are not based on production information (but they can still be very useful). Moreover, this module probably becomes more useful for bigger and more complex projects.
What to expect from nuxt/hints
Once you installed the module (and added it to your nuxt config file), just run your application normally and open DevTools. Click on the Hints icon and the hints panel will appear, summarizing detected issues:
Real-time Web Vitals metrics (LCP, INP, CLS) + element-level attribution & advice for improvement.
Hydration mismatch detection: side-by-side diff between server-rendered HTML and client-hydrated HTML to help debug mismatches. What’s really valuable here is that you can click on the component that’s causing the issue and jump directly to the source code to check out the implementation!
Third-party script auditing: lists external scripts, shows their performance/impact, and gives security/performance warning or suggestions.
Lastly, Nuxt Hints is still in its early days. As it matures beyond alpha, this module has the potential to become an integral part of DevTool or it could go a totally different way.
For any modern Nuxt project, Hints is a “nice to have” guardrail. It helps you catch common issues early, avoid regressions, and keep quality high without leaving your editor.Special Nuxt Features on an opt-in basis
NuxtNuxt is configured with sensible but extendable defaults. TheÂ
nuxt.config.ts file supports an opt-inÂfeatures namespace to enable or disable specific runtime behaviors, alongside aÂfuture namespace to adopt upcoming framework defaults and experimental multi-app support. It is located at the root of a Nuxt project and can be used to add custom scripts, register modules or change rendering modes.In this article, we’re going to check some “extra” options that go further and could help unlock new possibilities.
Features
The features block controls optional runtime behaviors in your application:
devLogs
Streams SSR server logs to the browser during development.
Default: true in dev
Can be set to 'silent' to suppress logs
export default defineNuxtConfig({ features: { devLogs: true // | 'silent' } })
inlineStylesInlines component CSS into rendered HTML (Vite only).
Default:Â (id) => id.includes('.vue')
Can be set to false or a callback for per-component control
export default defineNuxtConfig({ features: { inlineStyles: false // | (id) => boolean } })
noScriptsDisables injection of Nuxt client scripts and JS resource hints.
Options:
true or 'production' – disable in production
'all' – disable in both dev & prod
false – leave enabled
export default defineNuxtConfig({ features: { noScripts: true, // or 'production' | 'all' | false }, })
FutureEnable upcoming defaults and experimental core changes under future:
compatibilityVersion
Opt into defaults of a future major release (e.g., v5)
export default defineNuxtConfig({ future: { compatibilityVersion: 5 } })
multiAppEarly access to experimental multi-app support within a single Nuxt instance
export default defineNuxtConfig({ future: { multiApp: true } })
Experimental FeaturesasyncContext
Enables native async context to be accessible for nested composables in Nuxt and Nitro, reducing "Nuxt instance is unavailable" errors
export default defineNuxtConfig({ experimental: { asyncContext: true, }, })
buildCacheCaches Nuxt build artifacts based on a hash of the configuration and source files for faster rebuilds
export default defineNuxtConfig({ experimental: { buildCache: true, }, })
cookieStoreEnables CookieStore support to listen for cookie updates and refresh useCookie ref values:
export default defineNuxtConfig({ experimental: { cookieStore: true, }, })
purgeCachedDataNuxt will automatically purge cached data from useAsyncData and nuxtApp.static.data to prevent memory leaks. But you can decide to clean up Nuxt static and asyncData caches on route navigation.
export default defineNuxtConfig({ experimental: { purgeCachedData: false, // enabled by default }, })Exploring Server Components in Nuxt
NuxtAs developers, we know how important it is to reduce the amount of JavaScript we ship to the browser. And since Nuxt has been around, it has showed how powerful SSR can be for building performant applications.
Nuxt offers experimental features like Server Components to take our game to the next level but before using them, it’s important to take a look back at how hydration works and how Nuxt handles Server Side Rendering.
When you build a typical Nuxt application with SSR enabled, here's what happens:
On the Server:
Vue renders your components to static HTML
The server generates the complete DOM structure
This HTML is sent to the browser immediately
On the Client (Hydration):
The browser receives static HTML and displays it instantly
JavaScript bundles download in the background
Vue "hydrates" the static HTML by creating the virtual DOM, matching it to existing DOM nodes, and attaching event listeners
The page becomes fully interactive
This hydration process is necessary but comes with overhead. Every component needs to be downloaded as JavaScript, executed on the client, and "woken up" to become interactive. The JavaScript for your entire application must be downloaded and parsed even if most of it renders static content.
How Sever Components can helpServer components (also called component islands in Nuxt) fundamentally change this equation. They allow you to mark specific components to only render on the server and never hydrate on the client. They have some key benefits:
Reduced JavaScript Bundle Size:Â Server components and their dependencies are completely excluded from the client bundle. If you have a component that uses a heavy markdown parser or syntax highlighter, that entire library stays on the server.
Zero Hydration Overhead:Â Since server components don't hydrate, there's no virtual DOM creation, no event listener attachment, and no reconciliation work on the client. The component is truly static HTML.
Secure Server-Only Logic:Â You can safely include database queries, API keys, or other sensitive operations directly in server components without worrying about exposing them to the client.
Works with Static Sites:Â Despite the name, server components work perfectly with static site generation (SSG). Nuxt prerenders them at build time, so you can use them even on static hosting platforms like GitHub Pages or Netlify.
When and where to use them
Server components shine in specific scenarios where you have expensive rendering logic but don't need client-side interactivity. For example:
Syntax Highlighting and Code Blocks:Â Libraries like Shiki can add significant weight to your bundle. A syntax highlighter component is perfect as a server component since the highlighted code is just static HTML.
Markdown Rendering:Â Parsing and rendering markdown with MDC syntax or other parsers can be done entirely on the server. The rendered HTML is sent to the client without shipping the parser.
Static Footers and Headers:Â Navigation bars, footers, or any layout component that displays static content are excellent candidates. They add zero JavaScript but still render correctly.
Content from APIs:Â If you're fetching data from a CMS or database to display read-only content, server components eliminate the need to ship that fetching logic to the client.
Implementing Server ComponentsIn Nuxt 4, server components are still experimental but increasingly stable. Here's how to use them:
// nuxt.config.ts export default defineNuxtConfig({ experimental: { componentIslands: true } }Simply add theÂ
.server.vue suffix to your component file:components/ HighlightedCode.server.vue SiteFooter.server.vue MarkdownRenderer.server.vueUse it like any component:
<template> <div> <HighlightedCode :code="myCode" language="typescript" /> <SiteFooter /> </div> </template>
That's it! No special syntax in your template. The component renders on the server, and Nuxt sends only the HTML to the client.A final note
While reducing JavaScript bundle size is the most tangible benefit, server components offer something deeper:Â architectural clarity. They force you to think about data flow, component boundaries, and where state truly lives. This discipline makes your applications more maintainable. When you see aÂ
.server.vue component, you immediately know it has no client-side dependencies, no reactivity, no event handlers. It's self-documenting architecture.The convergence of server and client rendering represents the maturation of the JavaScript ecosystem. We're moving past the "SSR vs CSR" debates toward hybrid approaches that acknowledge both have their place.
Serverless functions in Nuxt: backend power without a backend
NuxtServerless functions are tiny pieces of code that run on demand in the cloud. You don’t provision servers or infrastructure, or write scaling rules. Cloud providers handle the underlying infrastructure, automatically scaling resources based on demand.Â
They’re perfect for lightweight APIs, form handlers, webhooks, simple auth endpoints, and glue code.
How Nuxt does it (Nitro + H3)Nuxt has built-in support for serverless functions via Nitro (its server engine). Nitro compiles your server code to many targets (Node, Vercel, Netlify, Cloudflare Workers, etc.) and runs on top of H3, a tiny, fast HTTP framework.
You write your server-side logic inside the
server/api/folder. Each file becomes an API endpoint automatically.// server/api/hello.ts export default defineEventHandler(() => { return { message: 'Hello from serverless' } })
This function will respond toGET /api/hellowith a JSON object. That’s it. Visit` /api/hello` in your browser or useFetch() from your frontend, and you get:{ "message": "Hello from serverless" }
Calling Your APIs from the FrontendYou can use
useFetch(),useAsyncData(), or$fetch()to call these functions in your Vue components or pages.<script setup> const { data } = await useFetch('/api/hello') </script> <template> <p>{{ data.message }}</p> </template>
DeploymentNuxt works with Vercel, Netlify, Cloudflare, etc. Just push your code and your functions will auto-deploy as serverless endpoints.
Vercel → Serverless Functions
Netlify → Netlify Functions
Cloudflare → Workers
You don’t need to configure anything manually — just push your code.
Quick Tips to Not Shoot Yourself in the FootDon’t trust inputs, always validate.
Use environment variables for anything secret.
Keep functions small and focused.
Handle errors properly.
Don’t block the event loop with long-running tasks (offload to queues if needed).
Common Use CasesForm submissions
Email sending
API proxies
Auth endpoints
Data fetching or caching
Webhooks
With Nuxt and Nitro, serverless functions are just regular files that do backend magic. No setup, no stress. Whether you need a contact form endpoint, a webhook handler, or a simple API proxy, you can build it in minutes.No server management required.
Data Fetching Game in Nuxt: Advanced Level
NuxtNuxt's
useFetchanduseAsyncDatacomposables are already powerful, but they got some seriously handy options that can level up how you handle data in your app.Here are a few advanced options that make a real difference in performance, UX, and network efficiency:
1.dedupe: Avoid Duplicate RequestsNuxt by default cancels any request with the same key before starting a new one. This means if you have multiple components that fetch the same data, you’ll see unnecessary requests and a lot of canceled ones. With the option
dedupe: 'defer’if an identical request is already pending, Nuxt won’t refetch and waits for the current one to finish.Âconst { data } = await useFetch('/api/products', { dedupe: 'defer' // default value: cancel });
2.retryandretryDelay: Resilience for Unstable EndpointsNot all users have stable connection or fast Wi-Fi. For flaky APIs, edge functions, or when you want to add basic fault tolerance without custom logic, you can use Nuxt’s
retrymechanism.const { data } = await useAsyncData('user', () => $fetch('/api/user'), { retry: 3, // number of retries after first request fails retryDelay: 1000 // milliseconds delay between retries });
3.delay: Stagger Fetches for Smoother UXThis option adds a delay before making the request. You can use it to debounce fetches triggered by user input (though better handled via watch + debounce). It’s’ useful when you want to avoid flashing loading states for super quick page transitions.
const { data } = await useFetch('/api/settings', { delay: 300. // milliseconds before starting fetch });Pro tip:
Always provide a key if you're using immediate: false, lazy, or working with reactive URLs to ensure deduplication and caching behave predictably.
These options let you finely tune your app's data layer for performance, UX, and network behavior. Mastering them in useFetch and useAsyncData helps you write cleaner, more efficient, and more resilient Nuxt apps.
Nuxt Essentials: A Practical Cheatsheet for Beginners & Returners
NuxtNuxt’s been around for a while -built on top of Vue- and with Nuxt 4 just around the corner, it’s a good time to revisit some of the basics. If you're new to Nuxt (or Vue), or just catching up after a break, here’s what people are actually talking about when they say things like 'Vite', 'Pinia', or 'Nitro'.
Folder structure in NuxtFolder
Purpose
pages/
Auto-routes based on file names
components/
Vue components
layouts/
Custom layouts
middleware/
Functions run before rendering page
plugins/
Inject functions/libraries
composables/
Auto-imported composables
Key tools in Nuxt ecosystemTool
Purpose
Nitro
Server engine (used for SSR, server APIs, middleware)
Vite
Frontend bundler (use for Dev server, build optimization)
Pinia
State management system
Now let's get into detail (only a bit)
Plugins:Plugins in Nuxt are a way to extend your app’s functionality by injecting features, libraries, or custom logic into the app context. They run before your Vue components are created. They run globally and are available everywhere without having to import it manually each time.
In Nuxt 3, you can create a plugin like:// /plugins/myPlugin.ts export default defineNuxtPlugin(nuxtApp => { nuxtApp.provide('hello', () => 'Hello from plugin!') })
And use it like:const hello = inject('hello')
Composables:In short: Composables = Reusable logic using Composition API
Let's look at a simple composable example:// composables/useCounter.ts export const useCounter = () => { const count = ref(0) const increment = () => count.value++ return { count, increment } }
You can use it in your vue component like:<script setup> const { count, increment } = useCounter() </script> <template> <button @click="increment">Clicked {{ count }} times</button> </template>
Middleware:// middleware/auth.global.ts export default defineNuxtRouteMiddleware((to, from) => { const user = useUser() if (!user.value) return navigateTo('/login') })
What is Nitro?Nitro is a lightweight universal server engine built by the Nuxt team. It’s what powers SSR (Server-Side Rendering), API routes, and deployment adapters in Nuxt 3.
Nitro: Next Generation Server Toolkit
What is Vite?Vite is a (blazing fast) modern frontend bundler with tree shaking, instant dev start and fast Hot Module Replacement.
Vite: the build tool for web
What's Pinia then?Pinia is the official state management library for Vue 3, and by extension, Nuxt 3.
Think of Pinia as Vuex’s leaner, friendlier successor. You define a store using "defineStore()" and use it in components without boilerplate.
It's lightweight and modular and there's first-class support for it in Nuxt (meaning it's officially integrated, fully supported, and works seamlessly out of the box)
The store for Vue.js
I've heard of Rollup and Rolldown, what are they?Rollup is a JavaScript module bundler (like Webpack or Vite's underlying engine for builds), known for being simple, fast, and tree-shake-friendly. It takes all your import/export JavaScript (or TypeScript) files, bundles them into one or more optimized output files.
In our context, Vite uses Rollup under the hood for production builds.
Rolldown is a newer project, currently under development (time of writing this article: June/July 2025).It's a Rollup-compatible bundler written in Rust, aiming to be blazing fast (like esbuild or Turbopack).
Powering Netherland’s largest real estate platform
VueAs published on "the official State of Vue.js report of 2025" earlier this year, I did a case study to showcase how Funda (real estate platform in the NL) makes use of Vue and Nuxt.
Little intro about Funda?
Funda is the Netherlands' leading real estate listing platform, serving millions of users daily. With hundreds of thousands of property listings and approximately 5 million daily searches, the platform demands exceptional performance, scalability, and search capabilities. Given the possible combination of search parameters and filters to cater to the users’ needs, this isn’t a trivial task. In addition, search engine optimization (SEO) is critical for ensuring visibility in property searches and maintaining a competitive edge for brokers.
How did we use Vue and Nuxt? And why?
Our web application combines modern technologies throughout its stack. For the frontend, we rely on Nuxt 3 with TypeScript and use Tailwind CSS as our CSS framework of choice, which also helps us write consistent styles according to our design system. The backend relies on the .NET framework, incorporating Elasticsearch to handle search functionality. The entire solution is hosted on the Microsoft Azure cloud platform.Beyond that, essential performance defaults, such as automatic code-splitting by route or predefined cache headers for assets, helped us get a good baseline. The built-in filesystem-based routing structure is also a big plus, as it makes navigation between listings and pages much simpler than solely using Vue Router (which is possible in Nuxt, too, if needed).
One key feature that makes domain-driven design possible is Nuxt's layer system. This allows us to split our codebase into multiple layers representing a domain. Each layer can have its own BFF and export its components. This makes it easy to separate concerns and keep the codebase clean and maintainable. Further, the layer system makes it easy to auto-import composables, components, and utilities, which is a big plus. Eventually, we benefit from further enhancements the Nuxt team ships consistently, from performance to developer experience improvements.
Nuxt 4 is coming out, what does it mean?
NuxtNuxt 3 was released in November 2022, about four years after Nuxt 2 originally launched. That’s four long years of development, beta cycles, and a full rewrite using Vue 3, Vite, and Nitro. The result? A versatile framework with a modern stack and delightful developer experience that got the frontend community excited.
Then in 2024, we started hearing rumors that Nuxt 4 was coming in June (but which June? Aha!).Flash forward to June 2025, and Nuxt 4 (alpha) is officially here — with a stable release promised by the end of the month. Cue the holy music.
What to expect from Nuxt 4?
You can read all about the new project structure and enhanced data fetching in official Nuxt articles (link) but what I want to highlight is how stress-free the migration from Nuxt 3 to Nuxt 4 is going to be.
We all remember the dark days of rewriting our Nuxt 2 projects to work with Nuxt 3. That was painful. But this time? Not the case.
As Daniel Roe has mentioned on multiple occasions, Nuxt 4 is not about “hype”, it’s about consistency and developer experience.
Nuxt 3 already felt solid and stable over the past couple years (and usage has been growing) Nuxt 4 just takes that solid foundation and makes it even more polished and thoughtfully engineered.
But Nuxt 4 is not a Pandora’s box for many of us. The new features were already available via compatibility mode, which makes the adaptation more straightforward, smooth and predictable.
But - Nuxt 5 is coming soon!
Yup, Nuxt 5 is already in the conversation. It’s possible we’ll have another major upgrade in 6 month or so, pending Nitro v3. And the question becomes whether to migrate a Nuxt 3 package to Nuxt 4 now or wait for Nuxt 5?
I think it’s definitely worth migrating to Nuxt 4 now. There is no major architectural overhaul and most modules require minimal changes to be compatible.Moreover, Core Nuxt modules are already using Nuxt 4 conventions and the community reception has been very positive so far.
PS. I really enjoyed watching this video from Alexander Lichter: TWO Major Nuxt versions coming? All you need to know about Nuxt 4 and Nuxt 5