diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 6f97a392b21a9..d7462e3488f93 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,6 +1,6 @@ # Learn how to add code owners here: # https://help.github.com/en/articles/about-code-owners -* @timneutkens @Timer @ijjk @lfades -/docs/ @timneutkens @Timer @ijjk @lfades @chibicode -/examples/ @timneutkens @Timer @ijjk @lfades @chibicode +* @timneutkens @Timer @ijjk @lfades @divmain +/docs/ @timneutkens @Timer @ijjk @lfades @divmain @leerob +/examples/ @timneutkens @Timer @ijjk @lfades @divmain @leerob diff --git a/.github/ISSUE_TEMPLATE/1.bug_report.yml b/.github/ISSUE_TEMPLATE/1.bug_report.yml index d6b3957f5a83b..6da3f732c59d8 100644 --- a/.github/ISSUE_TEMPLATE/1.bug_report.yml +++ b/.github/ISSUE_TEMPLATE/1.bug_report.yml @@ -3,65 +3,73 @@ about: Create a bug report for the Next.js core title: '' labels: 'template: bug' issue_body: true -inputs: - - type: description +body: + - type: markdown attributes: value: Thanks for taking the time to file a bug report! Please fill out this form as completely as possible. - - type: description + - type: markdown attributes: value: If you leave out sections there is a high likelihood it will be moved to the GitHub Discussions "Help" section. - - type: description + - type: markdown attributes: value: 'Please first verify if your issue exists in the Next.js canary release line: `npm install next@canary`.' - - type: description + - type: markdown attributes: value: 'next@canary is the beta version of Next.js. It includes all features and fixes that are pending to land on the stable release line.' - type: input attributes: label: What version of Next.js are you using? description: 'For example: 10.0.1' + validations: required: true - type: input attributes: label: What version of Node.js are you using? description: 'For example: 12.0.0' + validations: required: true - type: input attributes: label: What browser are you using? description: 'For example: Chrome, Safari' + validations: required: true - type: input attributes: label: What operating system are you using? description: 'For example: macOS, Windows' + validations: required: true - type: input attributes: label: How are you deploying your application? description: 'For example: next start, next export, Vercel, Other platform' + validations: required: true - type: textarea attributes: label: Describe the Bug description: A clear and concise description of what the bug is. + validations: required: true - type: textarea attributes: label: Expected Behavior description: A clear and concise description of what you expected to happen. + validations: required: true - type: textarea attributes: label: To Reproduce description: Steps to reproduce the behavior, please provide a clear code snippets that always reproduces the issue or a GitHub repository. Screenshots can be provided in the issue body below. + validations: required: true - - type: description + - type: markdown attributes: value: Before posting the issue go through the steps you've written down to make sure the steps provided are detailed and clear. - - type: description + - type: markdown attributes: value: Contributors should be able to follow the steps provided in order to reproduce the bug. - - type: description + - type: markdown attributes: value: These steps are used to add integration tests to ensure the same issue does not happen again. Thanks in advance! diff --git a/.github/ISSUE_TEMPLATE/2.example_bug_report.yml b/.github/ISSUE_TEMPLATE/2.example_bug_report.yml index 25da453dfd7a5..be3ea542b5196 100644 --- a/.github/ISSUE_TEMPLATE/2.example_bug_report.yml +++ b/.github/ISSUE_TEMPLATE/2.example_bug_report.yml @@ -3,64 +3,73 @@ about: Create a bug report for the examples title: '' labels: 'type: example,template: bug' issue_body: true -inputs: - - type: description +body: + - type: markdown attributes: value: Thanks for taking the time to file a examples bug report! Please fill out this form as completely as possible. - - type: description + - type: markdown attributes: value: If you leave out sections there is a high likelihood it will be moved to the GitHub Discussions "Help" section. - type: input attributes: label: What example does this report relate to? description: 'For example: with-styled-components' + validations: required: true - type: input attributes: label: What version of Next.js are you using? description: 'For example: 10.0.1' + validations: required: true - type: input attributes: label: What version of Node.js are you using? description: 'For example: 12.0.0' + validations: required: true - type: input attributes: label: What browser are you using? description: 'For example: Chrome, Safari' + validations: required: true - type: input attributes: label: What operating system are you using? description: 'For example: macOS, Windows' + validations: required: true - type: input attributes: label: How are you deploying your application? description: 'For example: next start, next export, Vercel, Other platform' + validations: required: true - type: textarea attributes: label: Describe the Bug description: A clear and concise description of what the bug is. + validations: required: true - type: textarea attributes: label: Expected Behavior description: A clear and concise description of what you expected to happen. + validations: required: true - type: textarea attributes: label: To Reproduce description: Steps to reproduce the behavior, please provide a clear code snippets that always reproduces the issue or a GitHub repository. Screenshots can be provided in the issue body below. + validations: required: true - - type: description + - type: markdown attributes: value: Before posting the issue go through the steps you've written down to make sure the steps provided are detailed and clear. - - type: description + - type: markdown attributes: value: Contributors should be able to follow the steps provided in order to reproduce the bug. - - type: description + - type: markdown attributes: value: Thanks in advance! diff --git a/.github/ISSUE_TEMPLATE/3.feature_request.yml b/.github/ISSUE_TEMPLATE/3.feature_request.yml index c4fbcccf7078f..8f2ee2da1fc8d 100644 --- a/.github/ISSUE_TEMPLATE/3.feature_request.yml +++ b/.github/ISSUE_TEMPLATE/3.feature_request.yml @@ -3,25 +3,28 @@ about: Create a feature request for the Next.js core title: '' labels: 'template: story' issue_body: true -inputs: - - type: description +body: + - type: markdown attributes: value: Thanks for taking the time to file a feature request! Please fill out this form as completely as possible. - - type: description + - type: markdown attributes: value: 'Feature requests will be converted to the GitHub Discussions "Ideas" section.' - type: textarea attributes: label: Describe the feature you'd like to request description: A clear and concise description of what you want and what your use case is. + validations: required: true - type: textarea attributes: label: Describe the solution you'd like description: A clear and concise description of what you want to happen. + validations: required: true - type: textarea attributes: label: Describe alternatives you've considered description: A clear and concise description of any alternative solutions or features you've considered. + validations: required: true diff --git a/.github/workflows/build_test_deploy.yml b/.github/workflows/build_test_deploy.yml index 176952e1e6a65..1bd1f3252a537 100644 --- a/.github/workflows/build_test_deploy.yml +++ b/.github/workflows/build_test_deploy.yml @@ -181,7 +181,7 @@ jobs: - run: yarn install --check-files if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }} - - run: xvfb-run node run-tests.js test/integration/{link-ref,production,basic,async-modules,font-optimization,ssr-ctx}/test/index.test.js test/acceptance/*.test.js + - run: xvfb-run node run-tests.js test/integration/{fallback-modules,link-ref,production,basic,async-modules,font-optimization,ssr-ctx}/test/index.test.js test/acceptance/*.test.js if: ${{ steps.docs-change.outputs.DOCS_CHANGE != 'docs only change' }} testLegacyReact: diff --git a/.vscode/launch.json b/.vscode/launch.json index 3a6858c2fd0dc..4fb1ca11305e3 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -25,6 +25,17 @@ "port": 9229, "outFiles": ["${workspaceFolder}/packages/next/dist/**/*"] }, + { + "name": "Launch app build trace", + "type": "node", + "request": "launch", + "cwd": "${workspaceFolder}", + "runtimeExecutable": "yarn", + "runtimeArgs": ["run", "trace-debug", "build", "test/integration/basic"], + "skipFiles": ["/**"], + "port": 9229, + "outFiles": ["${workspaceFolder}/packages/next/dist/**/*"] + }, { "name": "Launch app production", "type": "node", diff --git a/bench/capture-trace.js b/bench/capture-trace.js new file mode 100644 index 0000000000000..52ef690bff76b --- /dev/null +++ b/bench/capture-trace.js @@ -0,0 +1,66 @@ +const http = require('http') +const fs = require('fs') + +const PORT = 9411 +const HOST = '0.0.0.0' + +const traces = [] + +const onReady = () => console.log(`Listening on http://${HOST}:${PORT}`) +const onRequest = async (req, res) => { + if ( + req.method !== 'POST' || + req.url !== '/api/v2/spans' || + (req.headers && req.headers['content-type']) !== 'application/json' + ) { + res.writeHead(200) + return res.end() + } + + try { + const body = JSON.parse(await getBody(req)) + for (const traceEvent of body) { + traces.push(traceEvent) + } + res.writeHead(200) + } catch (err) { + console.warn(err) + res.writeHead(500) + } + + res.end() +} + +const getBody = (req) => + new Promise((resolve, reject) => { + let data = '' + req.on('data', (chunk) => { + data += chunk + }) + req.on('end', () => { + if (!req.complete) { + return reject('Connection terminated before body was received.') + } + resolve(data) + }) + req.on('aborted', () => reject('Connection aborted.')) + req.on('error', () => reject('Connection error.')) + }) + +const main = () => { + const args = process.argv.slice(2) + const outFile = args[0] || `./trace-${Date.now()}.json` + + process.on('SIGINT', () => { + console.log(`\nSaving to ${outFile}...`) + fs.writeFileSync(outFile, JSON.stringify(traces, null, 2)) + process.exit() + }) + + const server = http.createServer(onRequest) + server.listen(PORT, HOST, onReady) +} + +if (require.main === module) { + main() +} diff --git a/docs/api-reference/next.config.js/headers.md b/docs/api-reference/next.config.js/headers.md index 73623b08a2893..9fbb7641b1ea6 100644 --- a/docs/api-reference/next.config.js/headers.md +++ b/docs/api-reference/next.config.js/headers.md @@ -227,6 +227,17 @@ module.exports = { }, ], }, + { + // this gets converted to /(en|fr|de)/(.*) so will not match the top-level + // `/` or `/fr` routes like /:path* would + source: '/(.*)', + headers: [ + { + key: 'x-hello', + value: 'worlld', + }, + ], + }, ] }, } diff --git a/docs/api-reference/next.config.js/redirects.md b/docs/api-reference/next.config.js/redirects.md index 4ee91c3fc48f9..ca85b9402fd1c 100644 --- a/docs/api-reference/next.config.js/redirects.md +++ b/docs/api-reference/next.config.js/redirects.md @@ -152,6 +152,13 @@ module.exports = { locale: false, permanent: false, }, + { + // this gets converted to /(en|fr|de)/(.*) so will not match the top-level + // `/` or `/fr` routes like /:path* would + source: '/(.*)', + destination: '/another', + permanent: false, + }, ] }, } diff --git a/docs/api-reference/next.config.js/rewrites.md b/docs/api-reference/next.config.js/rewrites.md index a6f4efcfcf364..ac07e009862a4 100644 --- a/docs/api-reference/next.config.js/rewrites.md +++ b/docs/api-reference/next.config.js/rewrites.md @@ -244,6 +244,12 @@ module.exports = { destination: '/en/another', locale: false, }, + { + // this gets converted to /(en|fr|de)/(.*) so will not match the top-level + // `/` or `/fr` routes like /:path* would + source: '/(.*)', + destination: '/another', + }, ] }, } diff --git a/docs/api-reference/next/router.md b/docs/api-reference/next/router.md index 7b65b5273983d..fb0819a500a0c 100644 --- a/docs/api-reference/next/router.md +++ b/docs/api-reference/next/router.md @@ -50,6 +50,7 @@ The following is the definition of the `router` object returned by both [`useRou - `locales`: `String[]` - All supported locales (if enabled). - `defaultLocale`: `String` - The current default locale (if enabled). - `isReady`: `boolean` - Whether the router fields are updated client-side and ready for use. Should only be used inside of `useEffect` methods and not for conditionally rendering on the server. +- `isPreview`: `boolean` - Whether the application is currently in [preview mode](/docs/advanced-features/preview-mode.md). Additionally, the following methods are also included inside `router`: @@ -71,6 +72,7 @@ router.push(url, as, options) - `url` - The URL to navigate to - `as` - Optional decorator for the URL that will be shown in the browser. Before Next.js 9.5.3 this was used for dynamic routes, check our [previous docs](https://nextjs.org/docs/tag/v9.5.2/api-reference/next/link#dynamic-routes) to see how it worked - `options` - Optional object with the following configuration options: + - `scroll`: Scroll to the top of the page after a navigation. Defaults to `true` - [`shallow`](/docs/routing/shallow-routing.md): Update the path of the current page without rerunning [`getStaticProps`](/docs/basic-features/data-fetching.md#getstaticprops-static-generation), [`getServerSideProps`](/docs/basic-features/data-fetching.md#getserversideprops-server-side-rendering) or [`getInitialProps`](/docs/api-reference/data-fetching/getInitialProps.md). Defaults to `false` > You don't need to use `router.push` for external URLs. [window.location](https://developer.mozilla.org/en-US/docs/Web/API/Window/location) is better suited for those cases. diff --git a/docs/api-routes/dynamic-api-routes.md b/docs/api-routes/dynamic-api-routes.md index 702c822b101af..8bbf65affef99 100644 --- a/docs/api-routes/dynamic-api-routes.md +++ b/docs/api-routes/dynamic-api-routes.md @@ -17,10 +17,7 @@ For example, the API route `pages/api/post/[pid].js` has the following code: ```js export default function handler(req, res) { - const { - query: { pid }, - } = req - + const { pid } = req.query res.end(`Post: ${pid}`) } ``` @@ -69,10 +66,7 @@ An API route for `pages/api/post/[...slug].js` could look like this: ```js export default function handler(req, res) { - const { - query: { slug }, - } = req - + const { slug } = req.query res.end(`Post: ${slug.join(', ')}`) } ``` diff --git a/docs/api-routes/response-helpers.md b/docs/api-routes/response-helpers.md index aef95d69e53ed..61baff4d5f1e3 100644 --- a/docs/api-routes/response-helpers.md +++ b/docs/api-routes/response-helpers.md @@ -26,3 +26,5 @@ The included helpers are: - `res.json(json)` - Sends a JSON response. `json` must be a valid JSON object - `res.send(body)` - Sends the HTTP response. `body` can be a `string`, an `object` or a `Buffer` - `res.redirect([status,] path)` - Redirects to a specified path or URL. `status` must be a valid [HTTP status code](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes). If not specified, `status` defaults to "307" "Temporary redirect". + +To view an example using types, check out the [TypeScript documentation](/docs/basic-features/typescript.md#api-routes). diff --git a/docs/authentication.md b/docs/authentication.md index 591cddb311d94..ab4335f931ba6 100644 --- a/docs/authentication.md +++ b/docs/authentication.md @@ -114,16 +114,16 @@ Now that we've discussed authentication patterns, let's look at specific provide Examples If you have an existing database with user data, you'll likely want to utilize an open-source solution that's provider agnostic. - If you need email/password log-in, use [`next-iron-session`](https://github.com/vercel/next.js/tree/canary/examples/with-iron-session). -- If you need to persist session data on the server, use [`next-auth`](https://github.com/vercel/next.js/tree/canary/examples/with-next-auth). -- If you need to support social login (Google, Facebook, etc.), use [`next-auth`](https://github.com/vercel/next.js/tree/canary/examples/with-next-auth). -- If you want to use [JWTs](https://jwt.io/), use [`next-auth`](https://github.com/vercel/next.js/tree/canary/examples/with-next-auth). +- If you need to persist session data on the server, use [`next-auth`](https://github.com/nextauthjs/next-auth-example). +- If you need to support social login (Google, Facebook, etc.), use [`next-auth`](https://github.com/nextauthjs/next-auth-example). +- If you want to use [JWTs](https://jwt.io/), use [`next-auth`](https://github.com/nextauthjs/next-auth-example). Both of these libraries support either authentication pattern. If you're interested in [Passport](http://www.passportjs.org/), we also have examples for it using secure and encrypted cookies: diff --git a/docs/deployment.md b/docs/deployment.md index 43eaba507ece6..ad9fc0151c73c 100644 --- a/docs/deployment.md +++ b/docs/deployment.md @@ -6,7 +6,7 @@ description: Deploy your Next.js app to production with Vercel and other hosting ## Vercel (Recommended) -The easiest way to deploy Next.js to production is to use the **[Vercel platform](https://vercel.com)** from the creators of Next.js. [Vercel](https://vercel.com) is an all-in-one platform with Global CDN supporting static & Jamstack deployment and Serverless Functions. +The easiest way to deploy Next.js to production is to use the **[Vercel platform](https://vercel.com)** from the creators of Next.js. [Vercel](https://vercel.com) is a cloud platform for static sites, hybrid apps, and Serverless Functions. ### Getting started @@ -78,6 +78,59 @@ Make sure your `package.json` has the `"build"` and `"start"` scripts: `next build` builds the production application in the `.next` folder. After building, `next start` starts a Node.js server that supports [hybrid pages](/docs/basic-features/pages.md), serving both statically generated and server-side rendered pages. +### Docker Image + +Next.js can be deployed to any hosting provider that supports [Docker](https://www.docker.com/) containers. You can use this approach when deploying to container orchestrators such as [Kubernetes](https://kubernetes.io/) or [HashiCorp Nomad](https://www.nomadproject.io/), or when running inside a single node in any cloud provider. + +Here is a multi-stage `Dockerfile` using `node:alpine` that you can use: + +```Dockerfile +# Install dependencies only when needed +FROM node:alpine AS deps +# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed. +RUN apk add --no-cache libc6-compat +WORKDIR /app +COPY package.json yarn.lock ./ +RUN yarn install --frozen-lockfile + +# Rebuild the source code only when needed +FROM node:alpine AS builder +WORKDIR /app +COPY . . +COPY --from=deps /app/node_modules ./node_modules +RUN yarn build + +# Production image, copy all the files and run next +FROM node:alpine AS runner +WORKDIR /app + +ENV NODE_ENV production + +# You only need to copy next.config.js if you are NOT using the default configuration +# COPY --from=builder /app/next.config.js ./ +COPY --from=builder /app/public ./public +COPY --from=builder /app/.next ./.next +COPY --from=builder /app/node_modules ./node_modules + +RUN addgroup -g 1001 -S nodejs +RUN adduser -S nextjs -u 1001 +RUN chown -R nextjs:nodejs /app/.next +USER nextjs + +EXPOSE 3000 + +# Next.js collects completely anonymous telemetry data about general usage. +# Learn more here: https://nextjs.org/telemetry +# Uncomment the following line in case you want to disable telemetry. +# RUN npx next telemetry disable + +CMD ["node_modules/.bin/next", "start"] +``` + +Make sure to place this Dockerfile in the root folder of your project. + +You can build your container with `docker build . -t my-next-js-app` and run it with `docker run -p 3000:3000 my-next-js-app`. + ### Static HTML Export If you’d like to do a static HTML export of your Next.js app, follow the directions on [our documentation](/docs/advanced-features/static-html-export.md). diff --git a/examples/custom-server-actionhero/config/servers/web.js b/examples/custom-server-actionhero/config/servers/web.js index 366377985b150..b0131395423b0 100644 --- a/examples/custom-server-actionhero/config/servers/web.js +++ b/examples/custom-server-actionhero/config/servers/web.js @@ -9,7 +9,7 @@ exports['default'] = { secure: false, // Passed to https.createServer if secure=true. Should contain SSL certificates serverOptions: {}, - // Should we redirect all traffic to the first host in this array if hte request header doesn't match? + // Should we redirect all traffic to the first host in this array if the request header doesn't match? // i.e.: [ 'https://www.site.com' ] allowedRequestHosts: process.env.ALLOWED_HOSTS ? process.env.ALLOWED_HOSTS.split(',') diff --git a/examples/with-chakra-ui-typescript/package.json b/examples/with-chakra-ui-typescript/package.json index 38e187867007a..9c78c72758114 100644 --- a/examples/with-chakra-ui-typescript/package.json +++ b/examples/with-chakra-ui-typescript/package.json @@ -7,12 +7,12 @@ "start": "next start" }, "dependencies": { - "@chakra-ui/icons": "^1.0.0", - "@chakra-ui/react": "^1.0.0", - "@chakra-ui/theme-tools": "1.0.0", - "@emotion/react": "11.1.1", - "@emotion/styled": "11.0.0", - "framer-motion": "^2.9.4", + "@chakra-ui/icons": "^1.0.5", + "@chakra-ui/react": "^1.3.3", + "@chakra-ui/theme-tools": "1.0.4", + "@emotion/react": "11.1.5", + "@emotion/styled": "11.1.5", + "framer-motion": "^3.5.2", "next": "latest", "react": "^17.0.1", "react-dom": "^17.0.1" diff --git a/examples/with-context-api/README.md b/examples/with-context-api/README.md index 65ca4dfdfaa9a..0307f1fadb59a 100644 --- a/examples/with-context-api/README.md +++ b/examples/with-context-api/README.md @@ -4,7 +4,7 @@ This example shows how to use react context api in our app. It provides an example of using `pages/_app.js` to include the context api provider and then shows how both the `pages/index.js` and `pages/about.js` can both share the same data using the context api consumer. -We start of by creating two contexts. One that actually never changes (`CounterDispatchContext`) and one that changes more often (`CounterStateContext`). +We start off by creating two contexts. One that actually never changes (`CounterDispatchContext`) and one that changes more often (`CounterStateContext`). The `pages/index.js` shows how to, from the home page, increment and decrement the context data by 1 (a hard code value in the context provider itself). diff --git a/examples/with-emotion/README.md b/examples/with-emotion/README.md index a46123c4f027c..bb4ea630bafcc 100644 --- a/examples/with-emotion/README.md +++ b/examples/with-emotion/README.md @@ -1,8 +1,8 @@ # Emotion Example Extract and inline critical css with -[emotion](https://github.com/emotion-js/emotion/tree/master/packages/emotion), -[emotion-server](https://github.com/emotion-js/emotion/tree/master/packages/emotion-server), +[@emotion/css](https://github.com/emotion-js/emotion/tree/master/packages/css), +[@emotion/server](https://github.com/emotion-js/emotion/tree/master/packages/server), [@emotion/react](https://github.com/emotion-js/emotion/tree/master/packages/react), and [@emotion/styled](https://github.com/emotion-js/emotion/tree/master/packages/styled). diff --git a/examples/with-google-analytics/.env.local.example b/examples/with-google-analytics/.env.local.example new file mode 100644 index 0000000000000..b83076a91cfd1 --- /dev/null +++ b/examples/with-google-analytics/.env.local.example @@ -0,0 +1 @@ +NEXT_PUBLIC_GA_ID=123 diff --git a/examples/with-google-analytics/lib/gtag.js b/examples/with-google-analytics/lib/gtag.js index 3ea8bf79c3f30..49507f8b959f5 100644 --- a/examples/with-google-analytics/lib/gtag.js +++ b/examples/with-google-analytics/lib/gtag.js @@ -1,4 +1,4 @@ -export const GA_TRACKING_ID = '' +export const GA_TRACKING_ID = process.env.NEXT_PUBLIC_GA_ID // https://developers.google.com/analytics/devguides/collection/gtagjs/pages export const pageview = (url) => { diff --git a/examples/with-i18n-rosetta/locales/de.json b/examples/with-i18n-rosetta/locales/de.json index 5bd93d0cfbf7c..01923111ef72c 100644 --- a/examples/with-i18n-rosetta/locales/de.json +++ b/examples/with-i18n-rosetta/locales/de.json @@ -2,7 +2,7 @@ "intro": { "welcome": "Willkommen, {{username}}!", "text": "Ich hoffe, du findest das nützlich.", - "description": "Das Beispiel zeigt, wie man die Sprache für SSG und SSG optimierte Seiten wechselt." + "description": "Das Beispiel zeigt, wie man die Sprache für SSG und SSR optimierte Seiten wechselt." }, "dashboard": { "description": "Das Beispiel zeigt, wie man die Sprache nur Frontendseitig verändert. Nützlich für Dashboards wo SEO nicht relevant ist." diff --git a/examples/with-mysql/.env.local.example b/examples/with-mysql/.env.local.example index cf9f1b954e397..2062d45cde42c 100644 --- a/examples/with-mysql/.env.local.example +++ b/examples/with-mysql/.env.local.example @@ -4,3 +4,4 @@ MYSQL_HOST= MYSQL_DATABASE= MYSQL_USERNAME= MYSQL_PASSWORD= +MYSQL_PORT= diff --git a/examples/with-mysql/lib/db.ts b/examples/with-mysql/lib/db.ts index 13c458563f4a6..ede9544eca0f4 100644 --- a/examples/with-mysql/lib/db.ts +++ b/examples/with-mysql/lib/db.ts @@ -6,6 +6,7 @@ export const db = mysql({ database: process.env.MYSQL_DATABASE, user: process.env.MYSQL_USERNAME, password: process.env.MYSQL_PASSWORD, + port: process.env.MYSQL_PORT, }, }) diff --git a/examples/with-mysql/scripts/migrate-db.js b/examples/with-mysql/scripts/migrate-db.js index 022f0e1591528..66d529d7df6bc 100644 --- a/examples/with-mysql/scripts/migrate-db.js +++ b/examples/with-mysql/scripts/migrate-db.js @@ -13,6 +13,7 @@ const db = mysql({ database: process.env.MYSQL_DATABASE, user: process.env.MYSQL_USERNAME, password: process.env.MYSQL_PASSWORD, + port: process.env.MYSQL_PORT, }, }) diff --git a/examples/with-next-auth/.env.local.example b/examples/with-next-auth/.env.local.example deleted file mode 100644 index 67a1f8532131a..0000000000000 --- a/examples/with-next-auth/.env.local.example +++ /dev/null @@ -1,13 +0,0 @@ -NEXTAUTH_URL=http://localhost:3000 -NEXTAUTH_TWITTER_ID= -NEXTAUTH_TWITTER_SECRET= -NEXTAUTH_GITHUB_ID= -NEXTAUTH_GITHUB_SECRET= -NEXTAUTH_GOOGLE_ID= -NEXTAUTH_GOOGLE_SECRET= -NEXTAUTH_FACEBOOK_ID= -NEXTAUTH_FACEBOOK_SECRET= -NEXTAUTH_EMAIL_SERVER=smtp://username:password@smtp.example.com:587 -NEXTAUTH_EMAIL_FROM=NextAuth -NEXTAUTH_DATABASE_URL=sqlite://localhost/:memory:?synchronize=true - diff --git a/examples/with-next-auth/README.md b/examples/with-next-auth/README.md index 160660eacf7e2..7c2b46575c514 100644 --- a/examples/with-next-auth/README.md +++ b/examples/with-next-auth/README.md @@ -1,29 +1,3 @@ # NextAuth.js Example -Next.js example with [`next-auth`](https://github.com/iaincollins/next-auth), an open source, easy to use, and secure by default authentication library. - -## How to use - -Copy the `.env.local.example` file in this directory to `.env.local` (which will be ignored by Git): - -```bash -cp .env.local.example .env.local -``` - -Then, you'll need to fill at least one of the authentication providers by adding the required secrets for it, be that in the form of OAuth keys/secrets from a provider (Google, Twitter, etc.) or an SMTP connection string to enable email authentication. - -More details about the providers can be found [here](https://next-auth.js.org/configuration/providers), and for a more complete introduction to `next-auth` check out their [introduction guide](https://next-auth.js.org/getting-started/introduction) - -It is vital that you know the deployment URL and define it in the environment file. - -Execute [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example: - -```bash -npx create-next-app --example with-next-auth with-next-auth-app -# or -yarn create next-app --example with-next-auth with-next-auth-app -``` - -Deploy it to the cloud with [Vercel](https://vercel.com/new?utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)). - -**Note:** For production you need to know in advance the domain (deployment URL) of your application, as it would be required for OAuth to work, once you have it set it to the `NEXTAUTH_URL` environment variable under the settings of your Vercel project. +The official example is maintained by the NextAuth.js team. You can find it at this url: https://github.com/nextauthjs/next-auth-example diff --git a/examples/with-next-auth/components/footer.js b/examples/with-next-auth/components/footer.js deleted file mode 100644 index 991b6045f1bb9..0000000000000 --- a/examples/with-next-auth/components/footer.js +++ /dev/null @@ -1,17 +0,0 @@ -import styles from './footer.module.css' - -const Footer = () => ( -
-
- -
-) - -export default Footer diff --git a/examples/with-next-auth/components/footer.module.css b/examples/with-next-auth/components/footer.module.css deleted file mode 100644 index e97fe32cbc927..0000000000000 --- a/examples/with-next-auth/components/footer.module.css +++ /dev/null @@ -1,14 +0,0 @@ -.footer { - margin-top: 2rem; -} - -.navigation { - margin-bottom: 2rem; - padding: 0; - list-style: none; -} - -.navigationItem { - display: inline-block; - margin-right: 1rem; -} diff --git a/examples/with-next-auth/components/nav.js b/examples/with-next-auth/components/nav.js deleted file mode 100644 index b231cb36f67f8..0000000000000 --- a/examples/with-next-auth/components/nav.js +++ /dev/null @@ -1,61 +0,0 @@ -import { signin, signout, useSession } from 'next-auth/client' -import styles from './nav.module.css' - -/** - * The approach used in this component shows how to built a sign in and sign out - * component that works on pages which support both client and server side - * rendering, and avoids any flash incorrect content on initial page load. - **/ -const Nav = () => { - const [session, loading] = useSession() - - return ( - - ) -} - -export default Nav diff --git a/examples/with-next-auth/components/nav.module.css b/examples/with-next-auth/components/nav.module.css deleted file mode 100644 index 10d41f1401f25..0000000000000 --- a/examples/with-next-auth/components/nav.module.css +++ /dev/null @@ -1,79 +0,0 @@ -.loading, -.loaded { - position: relative; - top: 0; - opacity: 1; - overflow: auto; - border-radius: 0 0 0.6rem 0.6rem; - padding: 0.4rem 0.8rem; - margin: 0; - background-color: #f5f5f5; - transition: all 0.2s ease-in-out; -} - -.loading { - top: -2rem; - opacity: 0; -} - -.signedIn, -.notSignedIn { - position: absolute; - padding: 0.6rem 0 0.4rem 0; - left: 1rem; - right: 7rem; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; - display: inherit; - z-index: 1; -} - -.signedIn { - left: 3.8rem; -} - -.avatar { - border-radius: 2rem; - float: left; - height: 2.2rem; - width: 2.2rem; - background-color: white; - background-size: cover; - border: 2px solid #ddd; -} - -.signinButton, -.signoutButton { - float: right; - margin-right: -0.4rem; - font-weight: 500; - background-color: #1eb1fc; - color: #fff; - border: 1px solid #1eb1fc; - border-radius: 2rem; - cursor: pointer; - font-size: 1rem; - line-height: 1rem; - padding: 0.5rem 1rem; - position: relative; - z-index: 10; -} - -.signinButton:hover { - background-color: #1b9fe2; - border-color: #1b9fe2; - color: #fff; -} - -.signoutButton { - background-color: #fff; - border-color: #bbb; - color: #555; -} - -.signoutButton:hover { - background-color: #fff; - border-color: #aaa; - color: #333; -} diff --git a/examples/with-next-auth/package.json b/examples/with-next-auth/package.json deleted file mode 100644 index 4e6a01f2a16a5..0000000000000 --- a/examples/with-next-auth/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "with-next-auth", - "version": "1.0.0", - "scripts": { - "dev": "next", - "build": "next build", - "start": "next start" - }, - "license": "MIT", - "dependencies": { - "next": "latest", - "next-auth": "^3.1.0", - "react": "^16.13.1", - "react-dom": "^16.13.1", - "sqlite3": "^5.0.0" - } -} diff --git a/examples/with-next-auth/pages/_app.js b/examples/with-next-auth/pages/_app.js deleted file mode 100644 index 9e349c356c363..0000000000000 --- a/examples/with-next-auth/pages/_app.js +++ /dev/null @@ -1,13 +0,0 @@ -import { Provider } from 'next-auth/client' -import '../styles.css' - -const App = ({ Component, pageProps }) => { - const { session } = pageProps - return ( - - - - ) -} - -export default App diff --git a/examples/with-next-auth/pages/api/auth/[...nextauth].js b/examples/with-next-auth/pages/api/auth/[...nextauth].js deleted file mode 100644 index 473b3340ad774..0000000000000 --- a/examples/with-next-auth/pages/api/auth/[...nextauth].js +++ /dev/null @@ -1,126 +0,0 @@ -import NextAuth from 'next-auth' -import Providers from 'next-auth/providers' - -const options = { - // @link https://next-auth.js.org/configuration/providers - providers: [ - Providers.Email({ - // SMTP connection string or nodemailer configuration object https://nodemailer.com/ - server: process.env.NEXTAUTH_EMAIL_SERVER, - // Email services often only allow sending email from a valid/verified address - from: process.env.NEXTAUTH_EMAIL_FROM, - }), - // When configuring oAuth providers make sure you enabling requesting - // permission to get the users email address (required to sign in) - Providers.Google({ - clientId: process.env.NEXTAUTH_GOOGLE_ID, - clientSecret: process.env.NEXTAUTH_GOOGLE_SECRET, - }), - Providers.Facebook({ - clientId: process.env.NEXTAUTH_FACEBOOK_ID, - clientSecret: process.env.NEXTAUTH_FACEBOOK_SECRET, - }), - Providers.Twitter({ - clientId: process.env.NEXTAUTH_TWITTER_ID, - clientSecret: process.env.NEXTAUTH_TWITTER_SECRET, - }), - Providers.GitHub({ - clientId: process.env.NEXTAUTH_GITHUB_ID, - clientSecret: process.env.NEXTAUTH_GITHUB_SECRET, - }), - ], - - // @link https://next-auth.js.org/configuration/databases - database: process.env.NEXTAUTH_DATABASE_URL, - - // @link https://next-auth.js.org/configuration/options#session - session: { - // Use JSON Web Tokens for session instead of database sessions. - // This option can be used with or without a database for users/accounts. - // Note: `jwt` is automatically set to `true` if no database is specified. - // jwt: true, - // Seconds - How long until an idle session expires and is no longer valid. - // maxAge: 30 * 24 * 60 * 60, // 30 days - // Seconds - Throttle how frequently to write to database to extend a session. - // Use it to limit write operations. Set to 0 to always update the database. - // Note: This option is ignored if using JSON Web Tokens - // updateAge: 24 * 60 * 60, // 24 hours - }, - - // @link https://next-auth.js.org/configuration/options#jwt - jwt: { - // A secret to use for key generation - you should set this explicitly - // Defaults to NextAuth.js secret if not explicitly specified. - // secret: 'INp8IvdIyeMcoGAgFGoA61DdBglwwSqnXJZkgz8PSnw', - // Set to true to use encryption. Defaults to false (signing only). - // encryption: true, - // You can define your own encode/decode functions for signing and encryption - // if you want to override the default behaviour. - // encode: async ({ secret, token, maxAge }) => {}, - // decode: async ({ secret, token, maxAge }) => {}, - }, - - // @link https://next-auth.js.org/configuration/callbacks - callbacks: { - /** - * Intercept signIn request and return true if the user is allowed. - * - * @link https://next-auth.js.org/configuration/callbacks#sign-in-callback - * @param {object} user User object - * @param {object} account Provider account - * @param {object} profile Provider profile - * @return {boolean} Return `true` (or a modified JWT) to allow sign in - * Return `false` to deny access - */ - signIn: async (user, account, profile) => { - return true - }, - - /** - * @link https://next-auth.js.org/configuration/callbacks#session-callback - * @param {object} session Session object - * @param {object} user User object (if using database sessions) - * JSON Web Token (if not using database sessions) - * @return {object} Session that will be returned to the client - */ - session: async (session, user) => { - //session.customSessionProperty = 'bar' - return Promise.resolve(session) - }, - - /** - * @link https://next-auth.js.org/configuration/callbacks#jwt-callback - * @param {object} token Decrypted JSON Web Token - * @param {object} user User object (only available on sign in) - * @param {object} account Provider account (only available on sign in) - * @param {object} profile Provider profile (only available on sign in) - * @param {boolean} isNewUser True if new user (only available on sign in) - * @return {object} JSON Web Token that will be saved - */ - jwt: async (token, user, account, profile, isNewUser) => { - //const isSignIn = (user) ? true : false - // Add auth_time to token on signin in - //if (isSignIn) { token.auth_time = Math.floor(Date.now() / 1000) } - return Promise.resolve(token) - }, - }, - - // You can define custom pages to override the built-in pages - // The routes shown here are the default URLs that will be used. - // @link https://next-auth.js.org/configuration/pages - pages: { - //signIn: '/api/auth/signin', - //signOut: '/api/auth/signout', - //error: '/api/auth/error', // Error code passed in query string as ?error= - //verifyRequest: '/api/auth/verify-request', // (used for check email message) - //newUser: null // If set, new users will be directed here on first sign in - }, - - // Additional options - // secret: 'abcdef123456789' // Recommended (but auto-generated if not specified) - // debug: true, // Use this option to enable debug messages in the console -} - -const Auth = (req, res) => NextAuth(req, res, options) - -export default Auth diff --git a/examples/with-next-auth/pages/index.js b/examples/with-next-auth/pages/index.js deleted file mode 100644 index 818c27551cd6b..0000000000000 --- a/examples/with-next-auth/pages/index.js +++ /dev/null @@ -1,30 +0,0 @@ -import Nav from '../components/nav' -import Footer from '../components/footer' - -const NextAuth = () => ( - <> -