nuxt-movies: a Nuxt template that ships its own test harness
🍿 A TMDB client built with Nuxt
At a glance
- What is it?
- The official Nuxt Movies starter has become a reference implementation: a TMDB client with Playwright, Vitest, i18n, UnoCSS and a separate proxy, pinned to a nightly Nuxt build.
- Who is it for?
- nuxt-movies earns its place less as a movie browser than as a working reference for how a Nuxt 4 application is put together, because every layer a real project needs is present and configured rather than described. Three things are worth copying: a separate proxy directory so TMDB credentials never reach the browser, the paired unit and end-to-end test commands, and the nuxt-nightly pin that tells you exactly which framework build the app targets.
- 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 28 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 7, 2026, and from our analysis. They are not legal advice.
Editorial analysis
A starter whose README leads with screenshots
The README opens with a logo image and a heading that says Nuxt Movies with tests, then describes the app in a single line: a movies demo built using Nuxt, Vue, UnoCSS, Nuxt Image, The Movie Database API and TypeScript. A live preview is linked and four screenshots follow, covering the home page, a media details page, a discovery page and a mobile layout.
There is no feature list because this is a template rather than a product. What a reader is being offered is a working application to copy. The repository has 2225 stars, 450 forks and only 8 open issues, and the fork count relative to stars is high, which is the signature of something people clone and adapt rather than merely read.
Credits are given at the bottom. The project is based on `jasonujmaalvis/vue-movies` and `tastejs/nuxt-movies`, and there is an explicit note that the project uses the TMDB API but is not endorsed or certified by TMDB. The TMDB logo and attribution are included in the assets, which is what that API's terms require of an application displaying its data.
The setup path runs through pnpm and corepack
The Setup section is four commands and it encodes two decisions. The first is corepack, which is how the project pins its package manager rather than trusting whatever happens to be installed:
# Enable pnpm
$ corepack enable
# Install dependencies
$ pnpm install
# Start dev server with hot reload at localhost:3000
$ pnpm devThe second is that the lockfile is `pnpm-lock.yaml` and there is a `pnpm-workspace.yaml` in the tree, so this is set up as a pnpm workspace. That matters because the repository contains a `proxy/` directory with its own dev server, and the workspace file is what lets both be managed from one root.
The proxy gets its own script in package.json, named `dev:proxy`, which changes into the proxy directory and runs its dev server there. The README links to `proxy/README` rather than documenting it inline, which is the correct division of labour for a component with its own conventions.
That proxy exists for a specific reason: the TMDB API needs a key, and a key in browser-side code is a key anyone can read. The tree also holds `server/`, `shared/` and `.env.example`, and the environment file contains a single line setting `BASE_URL` to `http://localhost:3000`. So the architecture is a Nuxt app that talks to its own server layer, with a separate proxy process for the API, and configuration supplied through environment variables rather than committed values.
Tests are the reason this template differs from a demo
The heading says with tests and package.json backs it up. There are five test scripts, and they pair a fast suite with a slow one at each level:
"test:unit": "vitest",
"test:unit-coverage": "vitest --coverage",
"test:unit-web": "vitest --coverage --ui",
"test:e2e": "playwright test",
"test:e2e-ui": "playwright test --ui",Vitest runs unit tests, with coverage and a browser UI as separate opt-in variants. Playwright runs end to end tests, also with a UI mode. The configuration files are both present at the root, `vitest.config.ts` and `playwright.config.ts`, alongside a `tests/` directory.
One script is unusual enough to call out: `test:codegen` runs Playwright's codegen tool against localhost, and does so through `bunx` rather than Node. That is a small sign of how much tooling in this stack is still settling.
The supporting dependencies explain what the unit tests run in. `happy-dom` is present, so component tests render in a DOM shim rather than a real browser. `@vue/test-utils` provides the Vue mounting helpers, `@nuxt/test-utils` handles Nuxt-specific fixtures, and `lru-cache` alongside `oxc-parser` suggest there is parsing work happening in the tested code rather than the tests being thin render checks. Most templates ship one smoke test; this one ships a configured pair of runners, which is the part worth taking.
Pinned to a nightly Nuxt build, on Node 24
The single most informative line in package.json is the framework dependency:
"nuxt": "npm:[email protected]",That is an npm alias redirecting to the `nuxt-nightly` package at a specific nightly version, and the version string carries a build counter and what looks like a commit short hash. So the application is not on a released Nuxt. It is on one particular nightly build, and the version is reproducible because the identifier is exact.
The `devEngines` block matches that attitude:
"runtime": {
"name": "node",
"version": "^24.0.0",
"onFail": "download"
}Node ^24.0.0 and pnpm 11.1.2, both with `onFail: download`, meaning the tooling will fetch the required version rather than erroring on a mismatch. TypeScript is at ^6.0.2 and ESLint at ^10.9.1.
The honest reading is that this repository tracks the leading edge of Nuxt rather than a stable release, and the nightly pin is a deliberate choice for a reference project whose job is to show the current state of the framework. The cost is obvious: nothing here tells you that a given nightly will still install, and TypeScript 6 and ESLint 10 are also not the settled versions most projects are on. Both facts are in the file, and a reader has to decide which side of that trade they are on.
i18n, colour mode and the UnoCSS layer
The feature set beyond TMDB is conventional Nuxt application work, and the tree shows each piece as a separate configured file. `i18n.config.ts` and an `internationalization/` directory cover translations, with `@nuxtjs/i18n` at ^10.6.0. `@nuxtjs/color-mode` at ^4.0.1 handles light and dark switching. `@nuxt/image` at ^2.1.0 handles image optimisation.
Styling is UnoCSS rather than Tailwind, configured through `unocss.config.ts` with the `@unocss/nuxt` module at a version number in the high sixties. The icon setup is worth noting because it shows a pattern: rather than one icon package, there are four `@iconify-json` packages covering Carbon, Phosphor, simple-icons and Twemoji. That is a per-icon-family install, which keeps the bundle small and makes the icon choice visible in the dependency list.
ESLint is configured through `eslint.config.js` using `@antfu/eslint-config` at ^9.5.1. Other entry points in the tree are `app/` for the Vue application, `server/` for server routes, `shared/` for code used by both, `public/` for static assets, and `vercel.json` for deployment. That directory split is the Nuxt 4 layout, and a `.nuxtrc` file sits at the root alongside a `.vscode/` directory.
So the answer to what this project demonstrates is: a Nuxt 4 application with the current directory conventions, layered styling, translation, colour mode and a proxy for third-party API access. The movies are the excuse.
What to take from it and what to leave
The value of this repository is that it is complete. Almost every template stops at a working page and leaves testing, linting and deployment to the reader. This one ships a script for each of those, and the presence of `typecheck` as a first-class command means type errors get caught without anyone deciding to check.
The obvious first thing to take is the proxy arrangement, which solves the API key problem properly and keeps the browser from talking to TMDB directly. The second is the test script layout, where the same suite can run bare, with coverage or with a browser UI, and the end-to-end equivalent mirrors it. The third is the icon and theming structure, both of which are decisions that have to be made eventually.
What to leave is the nightly pin, or at least to think about it before copying it. The versions in this package.json describe a moment in the framework's development rather than a supported combination, and a project that needs to build next month cannot depend on that. The same applies to TypeScript 6, which a stable release line may not have caught up with.
The metadata gives a final signal. There are no releases at all, which is consistent with a template consumed by cloning rather than installing, and the last push was 2026-09-09 on a repository that is not archived. There is no version history to pin, which is both the reason a nightly dependency is tolerable here and the reason it would not be in your own project.
Editorial conclusion
nuxt-movies earns its place less as a movie browser than as a working reference for how a Nuxt 4 application is put together, because every layer a real project needs is present and configured rather than described. Three things are worth copying: a separate proxy directory so TMDB credentials never reach the browser, the paired unit and end-to-end test commands, and the nuxt-nightly pin that tells you exactly which framework build the app targets. The caveat is that a nightly dependency is unstable by definition, so read the pinned hash before treating the versions in package.json as guidance. For a TMDB client specifically, the demo works and credits its two upstream sources. For a starting point, take the layout and the tooling setup, then pin Nuxt to a release before you build on it.
Frequently asked questions
How do I run the nuxt-movies project locally?
Enable pnpm through corepack, run pnpm install, then pnpm dev to start the dev server with hot reload at localhost:3000. The separate proxy process has its own command, dev:proxy.
Which Nuxt version does this template use?
package.json pins nuxt to the nuxt-nightly package at build 4.6.0-29812804.e29b3dd9 through an npm alias, rather than to a released Nuxt version.
How are tests run in nuxt-movies?
Vitest handles unit tests and Playwright handles end to end tests, each with a plain, a coverage and a UI mode. Config files for both are at the repository root.
Why is there a separate proxy directory?
The app talks to The Movie Database through its own server layer and a separate proxy process, so the TMDB API key stays off the client. The README links to proxy/README rather than repeating it.
Official sources
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.
[](https://hysenlabs.com/projects/nuxt-movies)