# next-pwa-template: a progressive web app template with nothing spare

> Templates usually arrive with a decade of accumulated opinions, and the argument for a lean one is that you will delete the parts you do not want rather than the parts you never use. This one makes that argument explicitly: it separates the essentials from the nice-to-haves, tells you which is which, and ships a set of removables that are supposed to be easy to remove. The interesting details are in the manifest, where the formatting rules live, and in the version numbers, where they do not quite agree with the readme.

**mvllow/next-pwa-template** — Next.js progressive web app template

- Repository: https://github.com/mvllow/next-pwa-template
- Website: https://next-pwa-template.now.sh
- Stars: 562 · Forks: 64
- Language: TypeScript
- License: not declared
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/mvllow-next-pwa-template

## What fluffless means here

The template's own tagline is that it is a fluffless app template to inspire less, and the readme then makes the word precise.

Fluffless does not mean start with nothing. The goal of this template is to be an entry into maintainable apps.

That sentence is the whole pitch, and it is a better one than a template that promises to be minimal, because it distinguishes between a small project and a project with nothing in it. A template with nothing in it teaches you nothing and takes you an afternoon to set up. A template with a small, well-chosen set of pieces that are all load-bearing teaches you the shape of a modern web application and lets you delete pieces one at a time.

So the readme splits the contents into two groups, and the split is the most useful thing in the document.

The essentials are three items. TypeScript, made easy with the framework. A utility-first styling system for the styling. And a plugin for offline support.

The nice to haves are listed separately and more briefly, with the theming library named as an example of the kind of thing you can add, and the phrase low stress theming attached to it. A template that tells you which of its pieces are optional, and lets you choose your own for the optional ones, is a template that respects your judgement.

The features list at the top says the same thing from the other direction. There is a progressive web application without fluff, a night and day theme, nice-to-haves that are easily removable, a native-like mobile experience, and a description of the packaging that is a joke about wrapping a present.

And the tagline under the title makes the intent clear in a second way: it is a template meant to inspire less, that is, to inspire you to build less. The screenshot gallery is three images of the same placeholder application on a desktop in dark mode and on a phone in light and dark mode, which is the gallery of a template whose point is that you replace the content, not that you admire it.

The getting started section is three steps and that is the right length: use the template, replace the images directory with your own, and you are done. There is no configuration to work through, and the absence of steps is itself the design statement.

## The manifest, and where the formatting lives

The package manifest is where the real decisions are, and two of them are worth a paragraph each.

The first is the dependency set, and it is short. The framework, the offline plugin, the theming library, and the two React packages. That is four runtime dependencies for an application that works offline, themes itself, and runs on the server as well as in the browser. The development dependencies are the usual set for a styled and typed project: the type packages, the CSS processor and its prefixer, the linter and two configuration packages for it, the formatter and a plugin for it, the styling framework and a plugin for it, and the compiler.

The interesting entry among them is the safe area plugin for the styling framework. It exists to add the padding that a phone with a notch or a rounded corner needs, so that your content is not underneath the system chrome. That is a small dependency, and it is there because a progressive web application that is installed to the home screen has to live with the same screen furniture a native application does. It is also the kind of thing that is invisible in a template that does not have it, and the reason the mobile screenshots in the gallery look the way they do.

The second decision is where the formatting configuration lives. It is not in a separate file. It is a section in the package manifest, and it sets four things: no semicolons, single quotes, single quotes in JSX attributes, and tabs for indentation.

Putting it in the manifest is the right call for a template, because a template is a starting point that a person will copy, and every separate configuration file is a file that either gets copied along with the code or gets left behind and then fought with. One file that holds the scripts, the dependencies and the formatting rules is one file to keep.

The linter configuration is a separate file, and it is accompanied by a configuration package whose job is to stop the linter and the formatter from arguing with each other. That is a small detail, and it is the difference between a template that lints cleanly out of the box and one that produces a wall of warnings in the first minute.

There is also a type declaration file that the framework generates, an editor configuration, and a lock file for a specific package manager. The lock file matters: a template that ships a lock file is a template whose dependency versions are pinned to a set that is known to work together, rather than whatever the current latest happens to be on the day you clone it.

## The version numbers, and where they disagree

There is a small inconsistency in the repository that is worth pointing out, because it is the kind of thing that costs a newcomer an hour and that a careful reader can spot in a minute.

The readme's feature list says the template is a progressive web application using the thirteenth generation of the framework. The manifest pins the framework at a version in the fourteenth series. The linter configuration package is also from the thirteenth series, while the framework is in the fourteenth.

So the readme describes an older generation than the manifest installs, and the linter configuration lags behind the framework by one major version. None of this makes the template broken. The pinned versions are specific and deliberate, and the formatting configuration and the styling versions are all in a coherent set. But a reader who believes the readme will expect a particular set of APIs and a particular directory layout, and will find the newer one instead.

There is a second consequence worth noting. The repository has a pages directory rather than an application directory, which is the older of the two routing conventions in that framework. A template that ships the older convention alongside a newer framework version is a template that was updated for the framework and the framework's dependencies but not for a routing change, or one that deliberately stayed on the older convention.

Neither choice is wrong. But a template's job is partly to be predictable, and the predictability comes from the manifest being the single source of truth. The readme is a landing page; the manifest is the contract. Reading the manifest first and the readme second is the better order, and it is the order the template's own structure implies even though the readme does not say so.

The manifest is also where you find the four scripts, and they are the conventional four: a development server, a production build, a start of the built application, and a lint command. The version of the package itself is at zero point zero, which for a template is the correct thing and a small sign that the author does not think of it as a released library.

## The repository, and the structure of a template

The directory listing of a template is worth reading, because it is the shape of the application the author had in mind.

There is a components directory, which is where the reusable pieces live and which is the directory most projects will grow the most. There is a pages directory, the routing layer. There is a styles directory, which is unusual and worth pausing on: in a project where the styling is done with a utility-first framework, a separate styles directory usually holds the few things that cannot be expressed as utilities, such as the global rules, the font imports, and the base layer.

There is a public directory, which in a progressive web application is where the interesting files live. The manifest and the icons go there, because a progressive web application is a web application that the browser can install, and installation needs a manifest and an icon set. The getting started instructions tell you to replace the images directory with your own, and the readme's own illustration is an icon of five hundred and twelve pixels, which is the size the platforms expect for the larger of the two standard sizes. So the icon is a template artefact you are expected to replace, and the instruction is in the getting started section rather than buried.

There are three configuration files at the root: one for the framework itself, one for the CSS processor, and one for the styling framework. That is the conventional arrangement, and the reason there are three rather than one is that they are consumed by three different tools, each of which expects its own file.

The type configuration and the generated type declaration file are there for the same reason, and the lint configuration and the editor configuration are the other pair. A project that is going to be edited by several people needs a declaration of how the code is formatted, and a template that ships that declaration saves every contributor from making a pull request that fails on formatting.

And the readme is in a file with a lower case name, which is a trivial detail that tells you the project is not over-engineered, and that the author treats the readme as a file rather than as a product.

## The performance claim, and what a template owes you

The readme carries a badge claiming a perfect score on the lighthouse audit, and it links to the tool's own documentation rather than to a screenshot of a result. That is a better way to present the claim than a screenshot, because the link tells you what was measured and lets you run it yourself.

For a progressive web application template, that claim is not decoration. A progressive web application has to do several things that a normal web application does not: it has to serve a manifest, it has to register a service worker, and it has to handle the install prompt. Each of those can cost you points, and the usual failures are a service worker that blocks the first paint, a manifest that requests icons that do not exist, and a theme colour that is not defined. A template that scores full marks has already solved those, and a user who starts from it does not have to rediscover them.

The live demo is linked next to that, and it is a real deployment rather than a screenshot, which is the right way to demonstrate a progressive web application because the interesting parts, the install prompt and the offline behaviour, do not appear in a still image.

So what does a template owe its users? Three things, and this one does all three.

It owes them a working application, which it provides: the build, the start and the development scripts, the type checking, the linting, and the formatting rules.

It owes them a decision about what to keep, and this one provides that unusually well. The essentials and the nice to haves are separated in the readme, the removal is advertised as a feature rather than as a caveat, and the theming library is the one piece named as an example of something you might substitute.

And it owes them honesty about the versions, which is where this template falls short. The readme says one major version and the manifest installs another. A template is the one kind of project where the mismatch is most annoying, because the whole point is that you do not have to think about the setup, and a reader who trusts the prose over the manifest has to think about it.

Everything else about the project is aimed squarely at the same goal, which is that somebody can clone it, replace the images, and have something that works and can be installed on a phone, without reading a page of documentation first.

## Conclusion

next-pwa-template fits a developer who wants a working progressive web application skeleton with offline support and a theme switch already wired up, and who would rather delete what they do not need than work out what a large template is doing. It does not fit somebody who wants a bleeding edge application framework, since the pinned versions are a couple of generations behind. Verify first which major version of the framework you want, because the readme and the manifest disagree about it, that the offline behaviour is what you need, since the service worker is generated by a plugin rather than written by hand, and that the theme switch respects your system preference, because a theming library that always defaults to the light mode is a small but real source of complaints.

## FAQ

### What is the next-pwa-template project?

It is a Next.js progressive web app template described as fluffless, meaning it carries a small set of load-bearing pieces rather than every popular addition. The essentials are TypeScript, utility-first styling and offline support, with the theming library listed separately as a nice to have that you can substitute or remove.

### Which version of Next.js does the template use?

The manifest pins the framework at a version in the fourteenth series, while the readme's feature list still describes the thirteenth generation and the linter configuration package is from the thirteenth series as well. The manifest is the reliable source, since that is what a template installs, but the discrepancy is worth knowing about when you read the documentation.

### How does the template handle formatting and linting?

The formatting rules are a section in the package manifest rather than a separate file, and they set no semicolons, single quotes including in JSX attributes, and tabs. The linter has its own configuration file plus a package whose purpose is to stop the linter and the formatter from conflicting, so that a fresh clone lints cleanly.

### What makes the template a progressive web application?

The offline support plugin, which generates the service worker, and the icons and manifest in the public directory, which is why the getting started instructions tell you to replace the images with your own. The styling also includes a safe area plugin, so that an application installed to the home screen keeps its content clear of the screen furniture.

### How do I start using the template?

In three steps: use the template generator to create your own copy, replace the images directory in the public folder with your own assets, and you are done. There is no configuration to work through, and the project ships a lock file so the dependency versions you get are a set that is known to work together.

## Sources

- [Issues](https://github.com/mvllow/next-pwa-template/issues)
- [mvllow/next-pwa-template on GitHub](https://github.com/mvllow/next-pwa-template)
- [Project website](https://next-pwa-template.now.sh)
- [README](https://github.com/mvllow/next-pwa-template/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/mvllow-next-pwa-template
