The Latest Next.js Version Is 16.3.4. This Repo Runs 16.2.9.
npm carries sixteen dist-tags for `next` and `latest` is only one of them. Which version to be on, measured from a repo that pins the framework and ships it to other people.
The latest stable Next.js is 16.3.4, published 2026-08-31 — that is what npm install next gives you today. But npm carries sixteen dist-tags for the next package, and latest is only one of them. This storefront pins 16.2.9, five patches and a minor behind, on purpose. Here is what "your Next.js version" actually means, and when the gap matters.
Ask npm, not a blog post
$ npm view next dist-tags
{
latest: '16.3.4',
canary: '16.4.0-canary.25',
preview: '16.3.0-preview.10',
beta: '16.0.0-beta.0',
rc: '15.0.0-rc.1',
backport: '15.5.25',
'next-15-3': '15.3.9',
'next-14': '14.2.35',
'next-13': '13.5.11',
...
}
Sixteen tags. Three of them describe the future (canary, preview, beta), one is a fossil (rc still points at a 15.0.0 release candidate), and the rest are maintenance lines for majors that are still receiving fixes — next-14 sits at 14.2.35, which is a lot of patch releases for a major two behind.
That is the first correction to "what is the latest version": the question has a different answer depending on which line you are on. If you are on 15.x, your latest is 15.5.25, not 16.3.4.
Check your own, three ways, because they can disagree:
$ node -e "console.log(require('./package.json').dependencies.next)" # what you asked for
16.2.9
$ node -e "console.log(require('./package-lock.json').packages['node_modules/next'].version)"
16.2.9 # what you got
$ npx next --version # what actually runs
The lockfile is the one that is true. package.json records a range; only the lockfile records a resolution.
What this repo's package.json actually says
"dependencies": {
"next": "16.2.9",
"react": "19.2.4",
"react-dom": "19.2.4",
"@next/mdx": "^16.3.0",
...
}
Three exact pins and ten caret ranges. The three pinned ones are the runtime — the framework and the renderer — and the reason they carry no ^ is that a caret on next means the version that builds your site can change between a teammate's npm install and yours, without anything in the repo recording that it did.
Then look at the fourth line. @next/mdx is a caret range, and it has resolved to 16.3.0 — a package from a release train a whole minor ahead of the framework it plugs into:
$ node -e "const l=require('./package-lock.json');for(const k of ['node_modules/next','node_modules/@next/mdx','node_modules/@next/env'])console.log(k,'->',l.packages[k].version)"
node_modules/next -> 16.2.9
node_modules/@next/mdx -> 16.3.0
node_modules/@next/env -> 16.2.9
@next/env — which next pulls in itself — moves in lockstep at 16.2.9. @next/mdx, which this project asked for with a caret, floated. Nothing is broken, but it is a good illustration of why "what Next.js version am I on" is a question about a tree rather than a number: the framework is pinned and one of its own scoped packages is not.
Why sit a minor behind on purpose
| Reason to upgrade now | Reason to wait |
|---|---|
| A security advisory names your version | The release is days old and the .1 has not landed yet |
| You need a feature that shipped in it | Your build is green and nothing on the roadmap needs it |
| Your major is approaching end of maintenance | The upgrade touches config you would have to re-verify |
| A dependency requires it | You ship source code other people have to merge |
That last row is the one most upgrade advice never has to consider, and it is the whole story here. This is a template marketplace: 110 of 139 framework editions in the catalog are Next.js, and every one of them is source code somebody bought, edited, and now maintains as their own project. Moving the framework under them is not a deploy, it is a merge conflict in someone else's repo.
The house rule in CLAUDE.md says so explicitly. A framework major is a MAJOR SemVer bump for a template:
MAJOR (
X.0.0) — breaking to adopt: removed/renamed pages, components, props, or routes; restructured folders; framework/runtime major upgrade (e.g. Next 16→17); changed required env/config; anything that would make a buyer merging the update hit conflicts or rework.
So "upgrade to the latest Next.js" costs a major version and, with it, a promise to every existing buyer that adopting the update is work. A patch — 16.2.9 to 16.3.4 — would be a PATCH bump on our side. The version arithmetic is not decoration; it is the message the buyer reads before deciding whether to pull.
Three version numbers, one product
For a shipped template, "the version" splits into three, and they are allowed to disagree:
- The framework version —
nextin the template repo'spackage.json. - The template's own version — that same file's
versionfield, which is the source of truth. Every template repo carries aCLAUDE.mdtelling whoever edits it to bump this per SemVer. - The released version — the catalog's
latestVersion, which is the mirror of what is actually sitting in the download bucket.
Number 2 and number 3 drift apart the moment somebody pushes to a template repo, because a push redeploys that template's live preview and changes nothing about the zip a buyer downloads. scripts/release/check-drift.ts exists to find that gap without cloning 139 repositories:
async function repoVersion(repo: string): Promise<string | null> {
const url = `https://raw.githubusercontent.com/${repo}/HEAD/package.json`;
try {
const res = await fetch(url);
if (!res.ok) return null;
const pkg = (await res.json()) as { version?: string };
return pkg.version ?? null;
} catch {
return null;
}
}
One raw-file fetch per edition, a three-part SemVer compare, and a list of products whose repo is ahead of the catalog. A product drifts if any of its edition repos is ahead — multi-edition products bump in lockstep, so a Next.js edition and a React edition of the same template always carry the same number.
Number 3 is load-bearing rather than cosmetic. src/lib/download.ts:286 resolves the zip path from it:
version = product.latestVersion;
Bump the catalog without uploading the zip and every buyer gets a 404. Upload the zip without bumping the catalog and every buyer keeps getting the old one. That is why the release procedure treats the two as a single step.
Today the catalog reads 110 products at 1.0.0 and one at 0.1.0 (asoc-ecommerce) — and the 0.x is not an oversight. Under SemVer, 0.y.z is the band where anything may change at any time, which is exactly the promise that product is currently making.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
package.json and npx next --version disagree | package.json holds a range; the lockfile holds the resolution | Trust the lockfile; npm ls next shows the installed tree |
| A teammate's build behaves differently on the same commit | A caret range resolved to different versions on two machines | Pin the framework exactly, and commit the lockfile |
npm install next@latest moved you across a major | latest follows the newest major, not your line | Install from the maintenance tag: npm i next@next-15-3 |
A @next/* scoped package is ahead of next | It was added with a caret; only next's own dependencies move in lockstep | Pin it too, or accept the float knowingly |
| An upgrade guide's steps do not match your install | You are reading the docs for a different major | Read the docs shipped in node_modules/next/dist/docs/ — they match what you have |
| "Latest version" articles contradict each other | They were written on a date, and the answer changes weekly | Ask the registry: npm view next dist-tags |
Frequently asked questions
What is the latest stable version of Next.js right now?
16.3.4, published 2026-08-31, according to npm's latest dist-tag as measured for this article. Ask npm view next version rather than trusting this sentence — it is true on the date above and decays from there, which is the honest limitation of every article that answers this question.
Should I pin next exactly, or use a caret?
Pin it exactly if the framework version is part of what you ship — a template, a starter, anything someone else builds on. Use a caret if you deploy the only copy and want patch fixes to arrive without a PR. Either way, commit the lockfile; it is what makes the answer reproducible.
Is it safe to run a version behind the latest?
For a minor, usually yes, provided your major is still maintained and no advisory names your version. next-14 sitting at 14.2.35 shows how long a major keeps receiving fixes. Falling behind by a major is the one that compounds, because the upgrade work grows and eventually the fixes stop.
How do I know a Next.js upgrade broke nothing?
The same way any other change is checked here: npm test && npm run lint && npm run format && npm run build. next build type-checks every component, which is where a framework upgrade's removed or renamed APIs surface first — a full production build catches more of an upgrade's damage than the dev server will.
Templates in this post
ASoc Zenith (a growth-marketing agency landing page), ASoc Aegis (a risk-management marketing site) and ASoc Ally (an AI support-chatbot landing page) each carry their own package.json version and their own changelog, so the number you see on the product page is the number in the zip.
Browse the full sets: Next.js landing page templates, Tailwind landing page templates. For what a version bump means when the code is licensed rather than hosted, see Website Template Copyright; for the CI that gates every one of these bumps, A Next.js CI Pipeline in 23 Lines.
