# Improve Content Security Policy Documentation
This PR comprehensively improves the Next.js Content Security Policy
(CSP) documentation to address community feedback from Reddit and GitHub
discussions about gaps in the current documentation.
## Changes Made
### 1. Enhanced Nonce Flow Explanation
- Added detailed section explaining how Next.js automatically detects
and applies nonces during server-side rendering
- Clarified the 3-step process: middleware generation → Next.js
extraction → automatic application
- Explained that developers don't need to manually add nonces to every
script tag
### 2. Static vs Dynamic Rendering Documentation
- Added comprehensive section explaining performance implications of
using nonces
- Documented that nonces force all pages into dynamic rendering
- Explained trade-offs: slower page loads, increased server load, no CDN
caching
- Added guidance on when to use nonces vs alternatives
### 3. Experimental SRI (Subresource Integrity) Documentation
- Documented the experimental `sri.algorithm` configuration option
- Explained hash-based CSP as an alternative to nonces that preserves
static generation
- Included configuration examples and benefits/limitations
- Noted that SRI is webpack-only, App Router only, and experimental
### 4. Development vs Production Considerations
- Added section addressing environment-specific CSP requirements
- Documented need for `'unsafe-eval'` in development for HMR
- Provided conditional CSP examples based on NODE_ENV
### 5. Comprehensive Troubleshooting Section
- Added solutions for error pages that don't work with strict CSP
- Documented third-party script integration with CSP
- Included common CSP violation fixes
- Added examples for both App Router and Pages Router
### 6. Practical Examples
- Static site with hash-based CSP using SRI
- Dynamic site with nonce-based CSP
- Mixed approach for different page types
- Environment-aware CSP configuration
### 7. Enhanced Pages Router Documentation
- Added `_document.tsx` nonce access example
- Improved `getServerSideProps` examples
- Added third-party script integration examples
## Community Feedback Addressed
This PR directly addresses the Reddit thread feedback about:
- ❌ "it is not clear that the nonce is then picked up by the rest of the
pages" → ✅ Added detailed nonce flow explanation
- ❌ "it is not clear that the pages therefore are not statically
generated anymore" → ✅ Added static vs dynamic rendering section
- ❌ "The solution of being able to provide the sha256 hashes... is not
supported, and it is not mentioned in the documentation" → ✅ Added
experimental SRI documentation
- ❌ Poor documentation of strict CSP implementation → ✅ Added
comprehensive examples and troubleshooting
## Technical Details
- **File Modified**: `docs/01-app/02-guides/content-security-policy.mdx`
- **Lines Added**: 642 insertions
- **Maintains**: Existing documentation structure and Next.js
conventions
- **Supports**: Both App Router and Pages Router with appropriate
switcher components
## Testing
- Verified all code examples use correct Next.js APIs and patterns
- Ensured documentation follows existing Next.js docs structure
- Confirmed all referenced configuration options exist in the codebase
- Validated that experimental features are properly marked as such
---
**Link to Devin run**:
https://app.devin.ai/sessions/e7e5fa95dc0146b3ab79aac72c53ed13
**Requested by**: lee@vercel.com
---------
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: lee@vercel.com <lee@vercel.com>
Co-authored-by: Joseph Chamochumbi <joseph.chamochumbi@vercel.com>
## What?
Update examples `.gitignore` files for parity with [Yarn's official
recommendations](https://v3.yarnpkg.com/getting-started/qa#which-files-should-be-gitignored),
accounting for Yarn's modern Plug-n-Play functionality.
## Why?
New projects initialized with `create-next-app` presently add various
extraneous files from the Yarn cache to the initial commit. This is most
notable in the case of the Next SWC binary, which may exceed 100M in
some environments (empirically, 64-bit Darwin and WSL2 Ubuntu, and very
probably other unix/linux environments), and prevent users from pushing
their new projects to free GitHub repositories without rewriting the
commit history to exclude the extraneous files, or unnecessarily setting
up Git LFS to include them.
## How?
I have errored on the side of exclusion to enable users to push their
CNA projects to GitHub as-is and for parity with other package managers,
while still providing the opportunity to opt in to additional
functionality provided by modern Yarn.
These changes follow the recommendations for
**non**-[Zero-Install](https://yarnpkg.com/features/caching#zero-installs)
configurations, as Zero-Install functionality is an extension on top of
the base package manager experience, and may necessitate additional
configuration and present additional complications for unsuspecting
users, so I think it's best left up to the user to opt-in. On account of
the majority of publicly available Next.js-based projects comprising
general consumer-facing websites, it is my belief that the majority of
Next projects would not benefit from Yarn's Zero-Install functionality,
and that explicitly facilitating it by default would break status quo
with all other non-Yarn CNA projects.
Contrary to the example `.gitignore`s provided by Yarn, I've excluded
the `.yarn/sdks` directory as it contains IDE-specific tooling; I feel
it would be presumptuous for an environmentally-agnostic tool to target
and provide package-manager-specific tooling for specific editors. This
too should be left to the user to opt-in to and provide for their
project if they deem necessary.
I have retained the current `.gitignore`'s exclusion of the `/.pnp`
directory for backwards compatibility with older versions of Yarn (the
files therein have since been reallocated to the `.yarn` directory
addressed by these changes, but I am not clear on when that delineation
occurred or the prevalence of Yarn installations which depend on the
former convention). Maintaining the exclusion here, in the worst case,
implies additional downloads (on an order of magnitude merely similar to
using npm from the outset) rather than failure.
CC: @samcx
### Adding or Updating Examples
- [x] The "examples guidelines" are followed from our contributing doc
https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md
- [x] Make sure the linting passes by running `pnpm build && pnpm lint`.
See
https://github.com/vercel/next.js/blob/canary/contributing/repository/linting.md
Co-authored-by: Sam Ko <sam@vercel.com>
### What?
Remove unsafe-inline from with-strict-csp example in the script-src
### Why?
The main purpose of having strict CSP headers is to improve the web app
security posture. On securityheaders.com the grade is capped to A if
script-src contains 'unsafe-inline'. In order to reach A+. it needs to
be removed.
### How?
Edit the script-src in the with-strict-csp-app example
Co-authored-by: JJ Kasper <jj@jjsweb.site>
Fixes issue where a freshly cloned example will not work in development
mode due to `unsafe-eval` being blocked by the CSP.
Currently, the example will not work in development. Running the example
with `run dev` will produce EvalError errors in console which prevent
the app from functioning. This error also prevents any `<Script>`
components with `afterInteractive` from being loaded. These issues do
not occur in production where `eval` is not used.
This PR:
- Fixes the issue by allowing `unsafe-eval` if the environment is not
`production`.
- Improves the `script-src` value by [allowing backwards compatibility
with
browsers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#strict-dynamic)
that do not support `strict-dynamic` (`https: http: 'unsafe-inline'`
will be ignored by browsers that support `strict-dynamic`).
Some further details are available here:
https://github.com/vercel/next.js/issues/55638. This PR is not a fix for
the issue however.
- Fixes https://github.com/vercel/next.js/issues/61316
Co-authored-by: Sam Ko <sam@vercel.com>
## Description
This PR ensures that the default prettier config is used for examples
and templates.
This config is compatible with `prettier@3` as well (upgrading prettier
is bigger change that can be a future PR).
## Changes
- Updated `.prettierrc.json` in root with `"trailingComma": "es5"` (will
be needed upgrading to prettier@3)
- Added `examples/.prettierrc.json` with default config (this will
change every example)
- Added `packages/create-next-app/templates/.prettierrc.json` with
default config (this will change every template)
## Related
- Fixes#54402
- Closes#54409
### Reason for making this change
https://yarnpkg.com/getting-started/qa#:~:text=yarn%2Finstall%2Dstate.,your%20workspaces%20all%20over%20again.
In the official documentation of `yarn`, it is stated that `.yarn/install-state.gz` is an optimization file that developer shouldn't ever have to commit. However, currently, when running `create-next-app`, `.yarn/install-state.gz` is being commited.
### Remaining work
I apologize for only modifying one template initially to initiate the discussion first.
If this change is agreed upon, it should be synchronized with other `.gitignore` templates. Would it be possible to follow a similar approach as in https://github.com/vercel/next.js/pull/47241? I would appreciate any assistance in syncing this change.
There's been some confusion on the correct way to add a `nonce`, so took the opportunity here to:
- Add a new docs page for Content Security Policy
- Explained how to generate a `nonce` with Middleware
- Showed how to consume the `nonce` in a route with `headers`
- Updated the `with-strict-csp` example
- Update the `nonce` error message page
- Backlinked to the new page in a few places in the docs
This PR updates the minimum version of React used by examples from 17.0.2 to 18.2.0.
Fixes#41975
## Bug
- [x] Related issues linked using `fixes #41975`
- [ ] Integration tests added
- [ ] Errors have a helpful link attached, see `contributing.md`
## Feature
- [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have a helpful link attached, see `contributing.md`
## Documentation / Examples
- [x] Make sure the linting passes by running `pnpm build && pnpm lint`
- [x] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md)
Closes#40366
Rebass is not dependent on `styled-components` anymore. See:
https://rebassjs.org/migrating/#v4-breaking-changesCloses#40367
Document has been converted (#39871) from class, so `this.props` threw
an error.
## Bug
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have helpful link attached, see `contributing.md`
## Feature
- [ ] Implements an existing feature request or RFC. Make sure the
feature request has been accepted for implementation before opening a
PR.
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have helpful link attached, see `contributing.md`
## Documentation / Examples
- [ ] Make sure the linting passes by running `pnpm lint`
- [ ] The examples guidelines are followed from [our contributing
doc](https://github.com/vercel/next.js/blob/canary/contributing.md#adding-examples)
## Changes
- Migrate class based `_document`s to functional documents
- Removed `_document.js` where default
- Removed `MyDocument.getInitialProps` where default
## Motivation
This removes some boilerplate and prepares examples for server components.
## Documentation / Examples
- [x] Make sure the linting passes by running `pnpm lint`
- [x] The examples guidelines are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing.md#adding-examples)
This PR updates the docs and examples for `create-next-app` to include pnpm usage.
The following script was used to update every example README:
```js
const fs = require('fs')
const examples = fs.readdirSync('./examples')
for (let example of examples) {
const filename = `./examples/${example}/README.md`
const markdown = fs.readFileSync(filename, 'utf8')
const regex = new RegExp(`^yarn create next-app --example (.*)$`, 'gm')
const output = markdown.replace(regex, (yarn, group) => {
const pnpm = `pnpm create next-app -- --example ${group}`
return `${yarn}\n# or\n${pnpm}`
})
fs.writeFileSync(filename, output)
}
```
* Add licences to all example/package.json that lack them
* Revert "Add licences to all example/package.json that lack them"
This reverts commit 5d4e25012f.
* Update check-examples to remove `license` field from examples
* Remove `license` from all examples.
This was mentioned in vercel/next.js#27121 but it looks like it didn't end up being in the merge?
Co-authored-by: JJ Kasper <jj@jjsweb.site>
Clean up package.json files in the `examples` directory:
- Add `private: true`
- Remove `version` (because they are irrelevant for packages that are not meant to be published)
- Remove `name` (because they are optional for packages that are not meant to be published, and when someone clones an example, they often rename it and the property becomes stale)
- Remove `author`
- Remove `description`
- Remove `license`
Also remove `with-dynamic-app-layout` example completely, since it does the same as `layout-component` (https://github.com/vercel/next.js/pull/27121#discussion_r668178408).
## Documentation / Examples
- [x] Make sure the linting passes
[With next 11 requiring react 17](https://nextjs.org/blog/next-11#upgrade-guide), most of the examples
need to be updated, so the following snippet updated all the examples to
a compatible react version.
```bash
cd examples/
fd -g 'package.json' | xargs sed -r -i 's/"react": ".*"/"react": "^17.0.2"/
fd -g 'package.json' | xargs sed -r -i 's/"react-dom": ".*"/"react-dom": "^17.0.2"/'
# exclude experimental react version
git checkout with-reason-relay/package.json
```
This PR adds a `Preview` section and a `Open in StackBlitz` button to various examples. I have tested all examples and omitted the ones that require third party API keys, or didn't work. Some examples don't work locally either.
Here's an example:

## Bug
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
## Feature
- [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Documentation added
- [x] Examples updated
- [ ] Telemetry added. In case of a feature if it's used or not.
## Documentation / Examples
- [x] Make sure the linting passes
**What's the problem this PR addresses?**
A decent amount of the examples don't have a `name` field in `package.json` that matches their folder name, meaning they either lack a name or the names are duplicated.
I was testing Yarn 2 workspaces using the entire examples directory and needed to get rid of the duplicates.
**How did you fix it?**
Updated the names to match the names of their folders
* Find/Replace "Deploy it to the cloud..."
* Find/Replace "Deploy it to the cloud..." (no colon)
* Find/Replace "Deploy it to the cloud..." for firebase
* Convert remaining ones
* Storybook deployment
* Update with-stripe-typescript
* Update contributing.md
* Remove `now`
* Update examples/with-stripe-typescript/README.md
Co-Authored-By: Luis Alvarez D. <luis@zeit.co>