Maintenance: Dependencies
August 23, 2026 ยท View on GitHub
How to update, investigate, and resolve dependency conflicts in templates and extensions.
Read after the top-level MAINTENANCE_RUNBOOK.md.
1. Investigating a dependency
Before bumping a version, verify that it exists and that its peer requirements are compatible.
# Does a specific version exist?
npm view <pkg>@<version>
# List recent versions
npm view <pkg> versions --json | tail -n 20
# Check peer dependencies
npm view <pkg>@<version> peerDependencies
# Check the whole dependency tree
npm view <pkg>@<version> dependencies
Example:
npm view storybook@10.4.6
npm view @storybook/addon-essentials versions --json | tail -n 20
npm view @storybook/nextjs@8.6.18 peerDependencies
If a version is missing, npm view returns a 404. That immediately tells you that the range in package.json is invalid.
2. Dependency resolution failures
2.1 npm error ETARGET
Meaning: The requested version does not exist on the registry.
Common cause: A template or extension pins a version that has not been published for every package in a monorepo.
Fix:
- Verify which package in the monorepo lacks the version.
- Either:
- Drop the package if it is no longer needed in the new major line.
- Pin to the latest common version across all related packages.
- Wait/research the new addon/package name in the new major line.
Case study (resolved): Storybook ^10.5.3 exists for storybook, @storybook/nextjs, @storybook/react, and @storybook/addon-links, but not for @storybook/addon-essentials, @storybook/addon-interactions, @storybook/blocks, or @storybook/test (these are built into storybook core in v10 and referenced as string-based addons in main.ts). The fix was to drop those packages and keep only the 4 that ship as npm packages. Resolved in feat/storybook-v10-migration. See issue #161 for research details.
2.2 npm error ERESOLVE
Meaning: npm cannot satisfy the dependency tree, usually because of a peer-dependency conflict.
Common cause: Two packages require different major versions of the same peer.
Fix strategies (in order of preference):
- Update both sides to a mutually compatible version. This is the cleanest fix.
- Downgrade the more aggressive requirement if the newer major is not strictly needed.
- Add
.npmrcwithlegacy-peer-deps=trueif the packages are known to work together despite the declared peer range. Several extensions already do this (seeMAINTENANCE_TEMPLATES.md). - Mark extensions as incompatible if they truly cannot coexist.
Case study (resolved): @storybook/nextjs@8.6.18 declared peer next@"^13.5.0 || ^14.0.0 || ^15.0.0", but nextjs-starter uses Next 16. The workaround was .npmrc with legacy-peer-deps=true. With @storybook/nextjs@^10.5.3 the peer range expanded to include Next 16, so the .npmrc was removed. Resolved in feat/storybook-v10-migration.
2.3 Peer dependency warnings that turn into errors
In newer npm versions, peer conflicts can fail installs even when the rest of the tree resolves. Treat peer conflicts as errors if CI breaks.
3. Updating dependencies
3.1 In an extension
- Edit
extensions/<slug>/package.json. - Use conservative ranges:
^x.y.z. - Avoid major-version bumps unless you have validated the breaking changes.
- Re-scaffold the extension with each compatible template and run validation.
3.2 In a template
Templates ship a static template/package.json. Update the versions there directly (the legacy package/index.js / dependencies.js generator is no longer used).
3.3 Major updates
A major dependency update is high-risk. For each major:
- Read the changelog or migration guide.
- Check peer dependency requirements.
- Test with the full matrix of the affected template.
- If breaking changes affect generated code, update template
.templatefiles or extension files.
4. Lockfiles
Generated projects do not commit lockfiles in this repo, but the validation relies on fresh npm install. If a transitive dependency starts breaking installs, consider:
- Pinning the transitive dependency in the extension
package.json. - Using
overridesincreate-node-appcore (see MAINTENANCE_SECURITY.md).
Generated projects will receive whatever the registry returns at install time, so try to avoid relying on transient registry states.
5. Dependabot PRs
5.1 Reviewing
gh pr list --repo Create-Node-App/create-node-app --author dependabot --state open
gh pr view <pr> --repo Create-Node-App/create-node-app
5.2 Rebasing if conflicted
gh pr comment <pr> --repo Create-Node-App/create-node-app --body "@dependabot rebase"
5.3 Merging
Only merge if CI passes. Security-related bumps take priority. If a Dependabot PR fails CI, treat it as a bug fix: reproduce, adjust the dependency range or lockfile, and push to the same PR rather than opening a duplicate.
6. Tools for complex resolution
# Inspect why a version was chosen
npm ls <pkg>
# Show outdated packages in a generated project
npm outdated
# Install with maximum logs
npm install --loglevel verbose
# Force legacy peer resolution (local sanity check)
npm install --legacy-peer-deps
7. Checklist
- The target version exists for every related package in the monorepo.
- Peer dependencies are satisfied or explicitly worked around.
- The change is scoped to the affected template/extension.
- Local validation passes.
- Full matrix passes for affected templates.
- If security-related, the CVE is actually addressed by the bump.