Open-source project
antfu/vitesse-nuxt avatar
antfu/vitesse-nuxt

Vitesse for Nuxt 4: what the starter template fixes for you and what it quietly decides

Vitesse for Nuxt 4 🏔💚⚡️

1,908 stars243 forksTypeScriptMIT

At a glance

What is it?
antfu/vitesse-nuxt is a Nuxt 4 starter template that pins a specific stack (UnoCSS, Pinia, VitePWA, ColorMode, pnpm) so a new app starts with working conventions. The value is the saved decisions; the cost is that the conventions are not yours, and the repository publishes no tagged releases.
Who is it for?
Use vitesse-nuxt when you want a Nuxt 4 project running today with UnoCSS, Pinia, a layout system and an offline-capable PWA already wired, and when your team is prepared to own those choices afterwards. Skip it if your design system is CSS Modules, if you deploy to a platform other than the Netlify and Node paths the template configures, or if you need release provenance, because the repository has no GitHub releases and you should pin your own fork instead.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 45 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A starter template whose value is the decisions it already made

Vitesse for Nuxt 4 is a repository with no library API to learn. Its job is to hand you a Nuxt 4 project that already answers the questions every new app answers badly the first time: which CSS engine, which store, which module list, which package manager, which lint configuration.

The stack it commits to is visible in `package.json`. UnoCSS for atomic CSS, Pinia for state, `@vueuse/nuxt` for composition utilities, `@nuxtjs/color-mode` for dark mode, `@vite-pwa/nuxt` for offline support, `@nuxt/devtools`, `@nuxt/eslint` with `@antfu/eslint-config`, and `vue-tsc` for typechecking. `nuxt` and `vue` are both listed, and the project is `"type": "module"` with `"private": true`.

Everything above sits in `app/`, not a root `pages/` directory, and the README points at `./app/composables/user.ts` for the Pinia store and `./app/layouts` for the layout system. That directory shape is Nuxt 4's, and it is the first thing that will surprise someone arriving from an older Nuxt project.

The target user is a developer starting a Vue application, not a team migrating one. It is also not an open source library you would add as a dependency: it is a snapshot you copy, and from the moment you clone it the maintenance burden is yours.

Getting it: degit, pnpm, and a pinned package manager

The README gives four routes: an online preview, a StackBlitz link, the GitHub template generator, and a local clone. The local route is the one with commands:

bash
npx degit antfu/vitesse-nuxt my-nuxt-app
cd my-nuxt-app
pnpm i # If you don't have pnpm installed, run: npm install -g pnpm

`degit` is used rather than `git clone` so the copied tree carries no upstream history, which is what the README means by cleaner git history: your first commit is your own, not a squashed fork of someone else's.

The package manager is pinned precisely. `package.json` declares `"packageManager": "[email protected]"`, and the tree contains `pnpm-lock.yaml` and `pnpm-workspace.yaml`. There is no `package-lock.json` and no `yarn.lock`, so npm or yarn will not reproduce your dependency graph exactly.

The scripts tell you what shape of deployment is assumed

The script list in `package.json` is the clearest statement of intent in the repository:

json
"build": "nuxt build",
"generate": "nuxt generate",
"preview": "nuxt preview",
"start": "node .output/server/index.mjs",
"start:generate": "npx serve .output/public",
"lint": "eslint .",
"typecheck": "nuxt typecheck",
"dev:pwa": "VITE_PLUGIN_PWA=true nuxt dev"

Three deployment shapes are covered: a server build served by `node .output/server/index.mjs`, a fully static export from `nuxt generate` served with `npx serve .output/public`, and a preview through `nuxt preview`. `prepare` runs `nuxt prepare`, which generates the type scaffolding Nuxt needs before `vue-tsc` can check anything.

`dev:pwa` is the entry to understand: it sets `VITE_PLUGIN_PWA=true` explicitly, which implies the PWA behaviour, including the offline support and auto-update behaviour the README lists, is opt-in during development rather than always on.

UnoCSS plus icon sets, and why that pairing is a real choice

The styling layer is UnoCSS with a config file at `uno.config.ts`. The README highlights one capability in particular: icons from any icon set in pure CSS, powered by UnoCSS. In practice that means a class name resolved at build time to an icon from an installed collection, and `package.json` shows two collections installed: `@iconify-json/carbon` and `@iconify-json/twemoji`.

Shipping only the collections you use keeps that cost low. The trade-off is that atomic CSS puts your entire design vocabulary in class names on elements, and extracting a component library out of it later means rewriting markup rather than moving styles. Teams that already publish a component library with scoped CSS will feel this immediately.

Dark mode arrives through `@nuxtjs/color-mode`, described in the README as dark and light mode with auto detection. Auto detection is a client behaviour, so the first paint depends on how the module resolves the preference; if your brand requires a specific mode regardless of system setting, that has to be set explicitly rather than left to detection.

Deploying as a container exposes one port and one command

A `Dockerfile` is included at the repository root and it is a two stage build on `node:20-alpine`. The build stage enables corepack, copies `.npmrc package.json pnpm-lock.yaml pnpm-workspace.yaml` first so the dependency install is cached independently of application source, then runs `pnpm install --frozen-lockfile` and `pnpm build`.

The production stage copies only the `.output` directory forward:

dockerfile
FROM node:20-alpine AS production-stage

WORKDIR /app

COPY --from=build-stage /app/.output ./.output

EXPOSE 3000

CMD ["node", ".output/server/index.mjs"]

Two things follow from that. The image contains the server build only, so a static deployment via `nuxt generate` would not use this file as written. And the container listens on the default port Nuxt serves, exposed as 3000, with no environment variable overrides shown, so platform-provided port variables such as `PORT` are not accounted for in the template as given.

No tagged releases means no upgrade path, only a fork

The repository is not archived, and the last push was on 2026-09-08. It has, however, no GitHub releases at all. Without GitHub releases, the available reference points are the `main` branch and the online preview deployment.

The template also has to be deleted of upstream's baggage once you take it. The lint stack is opinionated and broad: `@antfu/eslint-config` plus `@nuxt/eslint`, with `eslint-plugin-format`, `eslint-plugin-slop`, `eslint-plugin-sonarjs` and the UnoCSS eslint config. That is a serious amount of rules arriving before your first line of application code, and the ones you disagree with will be your problem to suppress individually.

Editorial conclusion

Use vitesse-nuxt when you want a Nuxt 4 project running today with UnoCSS, Pinia, a layout system and an offline-capable PWA already wired, and when your team is prepared to own those choices afterwards. Skip it if your design system is CSS Modules, if you deploy to a platform other than the Netlify and Node paths the template configures, or if you need release provenance, because the repository has no GitHub releases and you should pin your own fork instead. Before the first commit, run `pnpm lint` and `pnpm typecheck`, then compare `nuxt.config.ts` and `uno.config.ts` against the defaults you would have written, since a starter is a set of opinions you are adopting whether or not you read them.

Frequently asked questions

How do I create a new project from vitesse-nuxt?

The README documents `npx degit antfu/vitesse-nuxt my-nuxt-app`, then `cd my-nuxt-app` and `pnpm i`. It also offers a GitHub template generator and a StackBlitz link.

What package manager does vitesse-nuxt require?

pnpm. `package.json` declares `"packageManager": "[email protected]"` and the repository ships `pnpm-lock.yaml` and `pnpm-workspace.yaml`.

How do I run vitesse-nuxt in production mode locally?

Run `pnpm build` and then `pnpm start`, which executes `node .output/server/index.mjs`. For a static export use `pnpm generate` with `pnpm start:generate`.

Is the PWA module active during `pnpm dev`?

The `dev` script is plain `nuxt dev`, while `dev:pwa` sets `VITE_PLUGIN_PWA=true` before running it, so PWA behaviour is opt-in in development.

Which state management and styling does the template set up?

State goes through Pinia, with an example store at `app/composables/user.ts`, and styling goes through UnoCSS configured in `uno.config.ts` with Carbon and Twemoji icon collections installed.

Official sources

  1. antfu/vitesse-nuxt on GitHub
  2. Issues
  3. License: MIT
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/antfu-vitesse-nuxt.svg)](https://hysenlabs.com/projects/antfu-vitesse-nuxt)

Was this useful?