diff --git a/.env.production b/.env.production
index d25eb7dd4..e403f96b6 100644
--- a/.env.production
+++ b/.env.production
@@ -1 +1 @@
-NEXT_PUBLIC_GA_TRACKING_ID = 'UA-41298772-4'
\ No newline at end of file
+NEXT_PUBLIC_GA_TRACKING_ID = 'G-B1E83PJ3RT'
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/0-bug.yml b/.github/ISSUE_TEMPLATE/0-bug.yml
new file mode 100644
index 000000000..56d2e8540
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/0-bug.yml
@@ -0,0 +1,34 @@
+name: "🐛 Report a bug"
+description: "Report a problem on the website."
+title: "[Bug]: "
+labels: ["bug: unconfirmed"]
+body:
+ - type: textarea
+ attributes:
+ label: Summary
+ description: |
+ A clear and concise summary of what the bug is.
+ placeholder: |
+ Example bug report:
+ When I click the "Submit" button on "Feedback", nothing happens.
+ validations:
+ required: true
+ - type: input
+ attributes:
+ label: Page
+ description: |
+ What page(s) did you encounter this bug on?
+ placeholder: |
+ https://react.dev/
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Details
+ description: |
+ Please provide any additional details about the bug.
+ placeholder: |
+ Example details:
+ The "Submit" button is unresponsive. I've tried refreshing the page and using a different browser, but the issue persists.
+ validations:
+ required: false
diff --git a/.github/ISSUE_TEMPLATE/1-typo.yml b/.github/ISSUE_TEMPLATE/1-typo.yml
new file mode 100644
index 000000000..c86557a11
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/1-typo.yml
@@ -0,0 +1,34 @@
+name: "🤦 Typo or mistake"
+description: "Report a typo or mistake in the docs."
+title: "[Typo]: "
+labels: ["type: typos"]
+body:
+ - type: textarea
+ attributes:
+ label: Summary
+ description: |
+ A clear and concise summary of what the mistake is.
+ placeholder: |
+ Example:
+ The code example on the "useReducer" page includes an unused variable `nextId`.
+ validations:
+ required: true
+ - type: input
+ attributes:
+ label: Page
+ description: |
+ What page is the typo on?
+ placeholder: |
+ https://react.dev/
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Details
+ description: |
+ Please provide a explanation for why this is a mistake.
+ placeholder: |
+ Example mistake:
+ In the "useReducer" section of the "API Reference" page, the code example under "Writing a reducer function" includes an unused variable `nextId` that should be removed.
+ validations:
+ required: false
diff --git a/.github/ISSUE_TEMPLATE/2-suggestion.yml b/.github/ISSUE_TEMPLATE/2-suggestion.yml
new file mode 100644
index 000000000..ac0b480fe
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/2-suggestion.yml
@@ -0,0 +1,34 @@
+name: "💡 Suggestions"
+description: "Suggest a new page, section, or edit for an existing page."
+title: "[Suggestion]: "
+labels: ["type: documentation"]
+body:
+ - type: textarea
+ attributes:
+ label: Summary
+ description: |
+ A clear and concise summary of what we should add.
+ placeholder: |
+ Example:
+ Add a new page for how to use React with TypeScript.
+ validations:
+ required: true
+ - type: input
+ attributes:
+ label: Page
+ description: |
+ What page is this about?
+ placeholder: |
+ https://react.dev/
+ validations:
+ required: false
+ - type: textarea
+ attributes:
+ label: Details
+ description: |
+ Please provide a explanation for what you're suggesting.
+ placeholder: |
+ Example:
+ I think it would be helpful to have a page that explains how to use React with TypeScript. This could include a basic example of a component written in TypeScript, and a link to the TypeScript documentation.
+ validations:
+ required: true
diff --git a/.github/ISSUE_TEMPLATE/3-framework.yml b/.github/ISSUE_TEMPLATE/3-framework.yml
new file mode 100644
index 000000000..a47295e1e
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/3-framework.yml
@@ -0,0 +1,116 @@
+name: "📄 Suggest new framework"
+description: "I am a framework author applying to be included as a recommended framework."
+title: "[Framework]: "
+labels: ["type: framework"]
+body:
+ - type: markdown
+ attributes:
+ value: |
+ ## Apply to be included as a recommended React framework
+
+ _This form is for framework authors to apply to be included as a recommended [React framework](https://react.dev/learn/start-a-new-react-project). If you are not a framework author, please contact the authors before submitting._
+
+ Our goal when recommending a framework is to start developers with a React project that solves common problems like code splitting, data fetching, routing, and HTML generation without any extra work later. We believe this will allow users to get started quickly with React, and scale their app to production.
+
+ While we understand that many frameworks may want to be featured, this page is not a place to advertise every possible React framework or all frameworks that you can add React to. There are many great frameworks that offer support for React that are not listed in our guides. The frameworks we recommend have invested significantly in the React ecosystem, and collaborated with the React team to be compatible with our [full-stack React architecture vision](https://react.dev/learn/start-a-new-react-project#which-features-make-up-the-react-teams-full-stack-architecture-vision).
+
+ To be included, frameworks must meet the following criteria:
+
+ - **Free & open-source**: must be open source and free to use.
+ - **Well maintained**. must be actively maintained, providing bug fixes and improvements.
+ - **Active community**: must have a sufficiently large and active community to support users.
+ - **Clear onboarding**: must have clear install steps to install the React version of the framework.
+ - **Ecosystem compatibility**: must support using the full range of libraries and tools in the React ecosystem.
+ - **Self-hosting option**: must support an option to self-host applications without losing access to features.
+ - **Developer experience**. must allow developers to be productive by supporting features like Fast Refresh.
+ - **User experience**. must provide built-in support for common problems like routing and data-fetching.
+ - **Compatible with our future vision for React**. React evolves over time, and frameworks that do not align with React’s direction risk isolating their users from the main React ecosystem over time. To be included on this page we must feel confident that the framework is setting its users up for success with React over time.
+
+ Please note, we have reviewed most of the popular frameworks available today, so it is unlikely we have not considered your framework already. But if you think we missed something, please complete the application below.
+ - type: input
+ attributes:
+ label: Name
+ description: |
+ What is the name of your framework?
+ validations:
+ required: true
+ - type: input
+ attributes:
+ label: Homepage
+ description: |
+ What is the URL of your homepage?
+ validations:
+ required: true
+ - type: input
+ attributes:
+ label: Install instructions
+ description: |
+ What is the URL of your getting started guide?
+ validations:
+ required: true
+ - type: dropdown
+ attributes:
+ label: Is your framework open source?
+ description: |
+ We only recommend free and open source frameworks.
+ options:
+ - 'No'
+ - 'Yes'
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Well maintained
+ description: |
+ Please describe how your framework is actively maintained. Include recent releases, bug fixes, and improvements as examples.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Active community
+ description: |
+ Please describe your community. Include the size of your community, and links to community resources.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Clear onboarding
+ description: |
+ Please describe how a user can install your framework with React. Include links to any relevant documentation.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Ecosystem compatibility
+ description: |
+ Please describe any limitations your framework has with the React ecosystem. Include any libraries or tools that are not compatible with your framework.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Self-hosting option
+ description: |
+ Please describe how your framework supports self-hosting. Include any limitations to features when self-hosting. Also include whether you require a server to deploy your framework.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Developer Experience
+ description: |
+ Please describe how your framework provides a great developer experience. Include any limitations to React features like React DevTools, Chrome DevTools, and Fast Refresh.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: User Experience
+ description: |
+ Please describe how your framework helps developers create high quality user experiences by solving common use-cases. Include specifics for how your framework offers built-in support for code-splitting, routing, HTML generation, and data-fetching in a way that avoids client/server waterfalls by default. Include details on how you offer features such as SSG and SSR.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: Compatible with our future vision for React
+ description: |
+ Please describe how your framework aligns with our future vision for React. Include how your framework will evolve with React over time, and your plans to support future React features like React Server Components.
+ validations:
+ required: true
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 000000000..63e310e0b
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,7 @@
+contact_links:
+ - name: 📃 Bugs in React
+ url: https://github.com/facebook/react/issues/new/choose
+ about: This issue tracker is not for bugs in React. Please file React issues here.
+ - name: 🤔 Questions and Help
+ url: https://reactjs.org/community/support.html
+ about: This issue tracker is not for support questions. Please refer to the React community's help and discussion forums.
diff --git a/.github/workflows/analyze.yml b/.github/workflows/analyze.yml
index 87dcfdc73..b1ef428d0 100644
--- a/.github/workflows/analyze.yml
+++ b/.github/workflows/analyze.yml
@@ -11,18 +11,26 @@ jobs:
analyze:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
- name: Set up node
- uses: actions/setup-node@v1
+ uses: actions/setup-node@v4
with:
node-version: '20.x'
+ cache: yarn
+ cache-dependency-path: yarn.lock
- - name: Install dependencies
- uses: bahmutov/npm-install@v1.7.10
+ - name: Restore cached node_modules
+ uses: actions/cache@v4
+ with:
+ path: "**/node_modules"
+ key: node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
+
+ - name: Install deps
+ run: yarn install --frozen-lockfile
- name: Restore next build
- uses: actions/cache@v2
+ uses: actions/cache@v4
id: restore-build-cache
env:
cache-name: cache-next-build
@@ -41,7 +49,7 @@ jobs:
run: npx -p nextjs-bundle-analysis@0.5.0 report
- name: Upload bundle
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
with:
path: .next/analyze/__bundle_analysis.json
name: bundle_analysis.json
@@ -73,7 +81,7 @@ jobs:
run: ls -laR .next/analyze/base && npx -p nextjs-bundle-analysis compare
- name: Upload analysis comment
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
with:
name: analysis_comment.txt
path: .next/analyze/__bundle_analysis_comment.txt
@@ -82,7 +90,7 @@ jobs:
run: echo ${{ github.event.number }} > ./pr_number
- name: Upload PR number
- uses: actions/upload-artifact@v2
+ uses: actions/upload-artifact@v4
with:
name: pr_number
path: ./pr_number
diff --git a/.github/workflows/site_lint.yml b/.github/workflows/site_lint.yml
index 34ca6d7b8..36f7642c9 100644
--- a/.github/workflows/site_lint.yml
+++ b/.github/workflows/site_lint.yml
@@ -14,14 +14,22 @@ jobs:
name: Lint on node 20.x and ubuntu-latest
steps:
- - uses: actions/checkout@v1
+ - uses: actions/checkout@v4
- name: Use Node.js 20.x
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v4
with:
node-version: 20.x
+ cache: yarn
+ cache-dependency-path: yarn.lock
- - name: Install deps and build (with cache)
- uses: bahmutov/npm-install@v1.8.32
+ - name: Restore cached node_modules
+ uses: actions/cache@v4
+ with:
+ path: "**/node_modules"
+ key: node_modules-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
+
+ - name: Install deps
+ run: yarn install --frozen-lockfile
- name: Lint codebase
run: yarn ci-check
diff --git a/.gitignore b/.gitignore
index d8bec488b..7bf71dbc5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,3 +36,6 @@ yarn-error.log*
# external fonts
public/fonts/**/Optimistic_*.woff2
+
+# rss
+public/rss.xml
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 0e861af35..4c7e5ec74 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -79,6 +79,7 @@ Ignore this rule if you're specifically describing an experimental proposal. Mak
- Use semicolons.
- No space between function names and parens (`method() {}` not `method () {}`).
- When in doubt, use the default style favored by [Prettier](https://prettier.io/playground/).
+- Always capitalize React concepts such as Hooks, Effects, and Transitions.
### Highlighting
diff --git a/README.md b/README.md
index 89bdc2b73..ad906dcfa 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@ This repo contains the source code and documentation powering [ml.react.dev](htt
### Prerequisites
1. Git
-1. Node: any 12.x version starting with v12.0.0 or greater
+1. Node: any version starting with v16.8.0 or greater
1. Yarn: See [Yarn website for installation instructions](https://yarnpkg.com/lang/en/docs/install/)
1. A fork of the repo (for any contributions)
1. A clone of the [ml.react.dev repo](https://github.com/reactjs/ml.react.dev) on your local machine
diff --git a/colors.js b/colors.js
index acf8214ee..872f33cac 100644
--- a/colors.js
+++ b/colors.js
@@ -11,7 +11,7 @@ module.exports = {
tertiary: '#5E687E', // gray-50
'tertiary-dark': '#99A1B3', // gray-30
link: '#087EA4', // blue-50
- 'link-dark': '#149ECA', // blue-40
+ 'link-dark': '#58C4DC', // blue-40
syntax: '#EBECF0', // gray-10
wash: '#FFFFFF',
'wash-dark': '#23272F', // gray-90
@@ -23,6 +23,8 @@ module.exports = {
'border-dark': '#343A46', // gray-80
'secondary-button': '#EBECF0', // gray-10
'secondary-button-dark': '#404756', // gray-70
+ brand: '#087EA4', // blue-40
+ 'brand-dark': '#58C4DC', // blue-40
// Gray
'gray-95': '#16181D',
diff --git a/package.json b/package.json
index 5ff6adbab..ad9b9baa4 100644
--- a/package.json
+++ b/package.json
@@ -15,28 +15,29 @@
"prettier:diff": "yarn nit:source",
"lint-heading-ids": "node scripts/headingIdLinter.js",
"fix-headings": "node scripts/headingIdLinter.js --fix",
- "ci-check": "npm-run-all prettier:diff --parallel lint tsc lint-heading-ids",
+ "ci-check": "npm-run-all prettier:diff --parallel lint tsc lint-heading-ids rss",
"tsc": "tsc --noEmit",
"start": "next start",
"postinstall": "patch-package && (is-ci || husky install .husky)",
- "check-all": "npm-run-all prettier lint:fix tsc"
+ "check-all": "npm-run-all prettier lint:fix tsc rss",
+ "rss": "node scripts/generateRss.js"
},
"dependencies": {
- "@codesandbox/sandpack-react": "2.6.0",
- "@docsearch/css": "3.0.0-alpha.41",
- "@docsearch/react": "3.0.0-alpha.41",
+ "@codesandbox/sandpack-react": "2.13.5",
+ "@docsearch/css": "^3.6.1",
+ "@docsearch/react": "^3.6.1",
"@headlessui/react": "^1.7.0",
+ "@radix-ui/react-context-menu": "^2.1.5",
"body-scroll-lock": "^3.1.3",
"classnames": "^2.2.6",
"date-fns": "^2.16.1",
"debounce": "^1.2.1",
- "ga-lite": "^2.1.4",
"github-slugger": "^1.3.0",
"next": "^13.4.1",
"next-remote-watch": "^1.0.0",
"parse-numeric-range": "^1.2.0",
"react": "^0.0.0-experimental-16d053d59-20230506",
- "react-collapsed": "npm:@gaearon/react-collapsed@3.1.0-forked.1",
+ "react-collapsed": "4.0.4",
"react-dom": "^0.0.0-experimental-16d053d59-20230506",
"remark-frontmatter": "^4.0.1",
"remark-gfm": "^3.0.1"
@@ -92,13 +93,13 @@
"retext": "^7.0.1",
"retext-smartypants": "^4.0.0",
"rss": "^1.2.2",
- "tailwindcss": "^3.3.2",
+ "tailwindcss": "^3.4.1",
"typescript": "^4.0.2",
"unist-util-visit": "^2.0.3",
"webpack-bundle-analyzer": "^4.5.0"
},
"engines": {
- "node": "^16.8.0 || ^18.0.0 || ^19.0.0 || ^20.0.0"
+ "node": ">=16.8.0"
},
"nextBundleAnalysis": {
"budget": null,
diff --git a/plugins/remark-smartypants.js b/plugins/remark-smartypants.js
index 7dd1b0c4a..4694ff674 100644
--- a/plugins/remark-smartypants.js
+++ b/plugins/remark-smartypants.js
@@ -1,3 +1,8 @@
+/*!
+ * Based on 'silvenon/remark-smartypants'
+ * https://github.com/silvenon/remark-smartypants/pull/80
+ */
+
const visit = require('unist-util-visit');
const retext = require('retext');
const smartypants = require('retext-smartypants');
@@ -9,12 +14,48 @@ function check(parent) {
}
module.exports = function (options) {
- const processor = retext().use(smartypants, options);
+ const processor = retext().use(smartypants, {
+ ...options,
+ // Do not replace ellipses, dashes, backticks because they change string
+ // length, and we couldn't guarantee right splice of text in second visit of
+ // tree
+ ellipses: false,
+ dashes: false,
+ backticks: false,
+ });
+
+ const processor2 = retext().use(smartypants, {
+ ...options,
+ // Do not replace quotes because they are already replaced in the first
+ // processor
+ quotes: false,
+ });
function transformer(tree) {
- visit(tree, 'text', (node, index, parent) => {
- if (check(parent)) node.value = String(processor.processSync(node.value));
+ let allText = '';
+ let startIndex = 0;
+ const textOrInlineCodeNodes = [];
+
+ visit(tree, ['text', 'inlineCode'], (node, _, parent) => {
+ if (check(parent)) {
+ if (node.type === 'text') allText += node.value;
+ // for the case when inlineCode contains just one part of quote: `foo'bar`
+ else allText += 'A'.repeat(node.value.length);
+ textOrInlineCodeNodes.push(node);
+ }
});
+
+ // Concat all text into one string, to properly replace quotes around non-"text" nodes
+ allText = String(processor.processSync(allText));
+
+ for (const node of textOrInlineCodeNodes) {
+ const endIndex = startIndex + node.value.length;
+ if (node.type === 'text') {
+ const processedText = allText.slice(startIndex, endIndex);
+ node.value = String(processor2.processSync(processedText));
+ }
+ startIndex = endIndex;
+ }
}
return transformer;
diff --git a/public/.well-known/atproto-did b/public/.well-known/atproto-did
new file mode 100644
index 000000000..ad8b0a36b
--- /dev/null
+++ b/public/.well-known/atproto-did
@@ -0,0 +1 @@
+did:plc:uorpbnp2q32vuvyeruwauyhe
\ No newline at end of file
diff --git a/public/android-chrome-192x192.png b/public/android-chrome-192x192.png
new file mode 100644
index 000000000..5de701e13
Binary files /dev/null and b/public/android-chrome-192x192.png differ
diff --git a/public/android-chrome-384x384.png b/public/android-chrome-384x384.png
new file mode 100644
index 000000000..f42a6776e
Binary files /dev/null and b/public/android-chrome-384x384.png differ
diff --git a/public/android-chrome-512x512.png b/public/android-chrome-512x512.png
new file mode 100644
index 000000000..2fdbf6902
Binary files /dev/null and b/public/android-chrome-512x512.png differ
diff --git a/public/apple-touch-icon.png b/public/apple-touch-icon.png
new file mode 100644
index 000000000..baf1332a3
Binary files /dev/null and b/public/apple-touch-icon.png differ
diff --git a/public/browserconfig.xml b/public/browserconfig.xml
new file mode 100644
index 000000000..f9c2e67fe
--- /dev/null
+++ b/public/browserconfig.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+ #2b5797
+
+
+
diff --git a/public/favicon-16x16.png b/public/favicon-16x16.png
new file mode 100644
index 000000000..d24cb4f76
Binary files /dev/null and b/public/favicon-16x16.png differ
diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png
new file mode 100644
index 000000000..953ae4cc3
Binary files /dev/null and b/public/favicon-32x32.png differ
diff --git a/public/favicon.ico b/public/favicon.ico
index 38fd8641c..519b939a0 100644
Binary files a/public/favicon.ico and b/public/favicon.ico differ
diff --git a/public/favicon_old.ico b/public/favicon_old.ico
new file mode 100644
index 000000000..20b59d440
Binary files /dev/null and b/public/favicon_old.ico differ
diff --git a/public/images/brand/logo_dark.svg b/public/images/brand/logo_dark.svg
new file mode 100644
index 000000000..265777fa3
--- /dev/null
+++ b/public/images/brand/logo_dark.svg
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/public/images/brand/logo_light.svg b/public/images/brand/logo_light.svg
new file mode 100644
index 000000000..bbe5a8994
--- /dev/null
+++ b/public/images/brand/logo_light.svg
@@ -0,0 +1,10 @@
+
+
\ No newline at end of file
diff --git a/public/images/brand/wordmark_dark.svg b/public/images/brand/wordmark_dark.svg
new file mode 100644
index 000000000..ec028ae21
--- /dev/null
+++ b/public/images/brand/wordmark_dark.svg
@@ -0,0 +1,15 @@
+
+
\ No newline at end of file
diff --git a/public/images/brand/wordmark_light.svg b/public/images/brand/wordmark_light.svg
new file mode 100644
index 000000000..2de8f3cc7
--- /dev/null
+++ b/public/images/brand/wordmark_light.svg
@@ -0,0 +1,11 @@
+
+
\ No newline at end of file
diff --git a/public/images/docs/diagrams/conditional_render_tree.dark.png b/public/images/docs/diagrams/conditional_render_tree.dark.png
new file mode 100644
index 000000000..5189a44c8
Binary files /dev/null and b/public/images/docs/diagrams/conditional_render_tree.dark.png differ
diff --git a/public/images/docs/diagrams/conditional_render_tree.png b/public/images/docs/diagrams/conditional_render_tree.png
new file mode 100644
index 000000000..c76e8cb63
Binary files /dev/null and b/public/images/docs/diagrams/conditional_render_tree.png differ
diff --git a/public/images/docs/diagrams/generic_dependency_tree.dark.png b/public/images/docs/diagrams/generic_dependency_tree.dark.png
new file mode 100644
index 000000000..64694f585
Binary files /dev/null and b/public/images/docs/diagrams/generic_dependency_tree.dark.png differ
diff --git a/public/images/docs/diagrams/generic_dependency_tree.png b/public/images/docs/diagrams/generic_dependency_tree.png
new file mode 100644
index 000000000..8ab6f1a34
Binary files /dev/null and b/public/images/docs/diagrams/generic_dependency_tree.png differ
diff --git a/public/images/docs/diagrams/generic_render_tree.dark.png b/public/images/docs/diagrams/generic_render_tree.dark.png
new file mode 100644
index 000000000..859fdaa96
Binary files /dev/null and b/public/images/docs/diagrams/generic_render_tree.dark.png differ
diff --git a/public/images/docs/diagrams/generic_render_tree.png b/public/images/docs/diagrams/generic_render_tree.png
new file mode 100644
index 000000000..952cf5faa
Binary files /dev/null and b/public/images/docs/diagrams/generic_render_tree.png differ
diff --git a/public/images/docs/diagrams/module_dependency_tree.dark.png b/public/images/docs/diagrams/module_dependency_tree.dark.png
new file mode 100644
index 000000000..e8a85f7c0
Binary files /dev/null and b/public/images/docs/diagrams/module_dependency_tree.dark.png differ
diff --git a/public/images/docs/diagrams/module_dependency_tree.png b/public/images/docs/diagrams/module_dependency_tree.png
new file mode 100644
index 000000000..0dcaaa7aa
Binary files /dev/null and b/public/images/docs/diagrams/module_dependency_tree.png differ
diff --git a/public/images/docs/diagrams/prerender.dark.png b/public/images/docs/diagrams/prerender.dark.png
new file mode 100644
index 000000000..1e7d67e13
Binary files /dev/null and b/public/images/docs/diagrams/prerender.dark.png differ
diff --git a/public/images/docs/diagrams/prerender.png b/public/images/docs/diagrams/prerender.png
new file mode 100644
index 000000000..ababa5493
Binary files /dev/null and b/public/images/docs/diagrams/prerender.png differ
diff --git a/public/images/docs/diagrams/prewarm.dark.png b/public/images/docs/diagrams/prewarm.dark.png
new file mode 100644
index 000000000..461406039
Binary files /dev/null and b/public/images/docs/diagrams/prewarm.dark.png differ
diff --git a/public/images/docs/diagrams/prewarm.png b/public/images/docs/diagrams/prewarm.png
new file mode 100644
index 000000000..f6ec1c49d
Binary files /dev/null and b/public/images/docs/diagrams/prewarm.png differ
diff --git a/public/images/docs/diagrams/render_tree.dark.png b/public/images/docs/diagrams/render_tree.dark.png
new file mode 100644
index 000000000..117d7ff3e
Binary files /dev/null and b/public/images/docs/diagrams/render_tree.dark.png differ
diff --git a/public/images/docs/diagrams/render_tree.png b/public/images/docs/diagrams/render_tree.png
new file mode 100644
index 000000000..1ea750bb0
Binary files /dev/null and b/public/images/docs/diagrams/render_tree.png differ
diff --git a/public/images/docs/diagrams/use_client_module_dependency.dark.png b/public/images/docs/diagrams/use_client_module_dependency.dark.png
new file mode 100644
index 000000000..c50e7308b
Binary files /dev/null and b/public/images/docs/diagrams/use_client_module_dependency.dark.png differ
diff --git a/public/images/docs/diagrams/use_client_module_dependency.png b/public/images/docs/diagrams/use_client_module_dependency.png
new file mode 100644
index 000000000..d535246f7
Binary files /dev/null and b/public/images/docs/diagrams/use_client_module_dependency.png differ
diff --git a/public/images/docs/diagrams/use_client_render_tree.dark.png b/public/images/docs/diagrams/use_client_render_tree.dark.png
new file mode 100644
index 000000000..8d3e6a484
Binary files /dev/null and b/public/images/docs/diagrams/use_client_render_tree.dark.png differ
diff --git a/public/images/docs/diagrams/use_client_render_tree.png b/public/images/docs/diagrams/use_client_render_tree.png
new file mode 100644
index 000000000..ad3840681
Binary files /dev/null and b/public/images/docs/diagrams/use_client_render_tree.png differ
diff --git a/public/images/team/dave-mccabe.jpg b/public/images/team/dave-mccabe.jpg
deleted file mode 100644
index 505f75617..000000000
Binary files a/public/images/team/dave-mccabe.jpg and /dev/null differ
diff --git a/public/images/team/jack-pope.jpg b/public/images/team/jack-pope.jpg
new file mode 100644
index 000000000..601e5840e
Binary files /dev/null and b/public/images/team/jack-pope.jpg differ
diff --git a/public/images/team/lauren.jpg b/public/images/team/lauren.jpg
index 1485cf8ff..26d46bd2f 100644
Binary files a/public/images/team/lauren.jpg and b/public/images/team/lauren.jpg differ
diff --git a/public/images/team/lesiutin.jpg b/public/images/team/lesiutin.jpg
new file mode 100644
index 000000000..edfc942e0
Binary files /dev/null and b/public/images/team/lesiutin.jpg differ
diff --git a/public/images/team/lunaruan.jpg b/public/images/team/lunaruan.jpg
deleted file mode 100644
index f6de76d4e..000000000
Binary files a/public/images/team/lunaruan.jpg and /dev/null differ
diff --git a/public/images/team/mengdi-chen.jpg b/public/images/team/mengdi-chen.jpg
deleted file mode 100644
index 7a47ea4f7..000000000
Binary files a/public/images/team/mengdi-chen.jpg and /dev/null differ
diff --git a/public/images/team/noahlemen.jpg b/public/images/team/noahlemen.jpg
new file mode 100644
index 000000000..e3f788d89
Binary files /dev/null and b/public/images/team/noahlemen.jpg differ
diff --git a/public/images/team/sean-keegan.jpg b/public/images/team/sean-keegan.jpg
deleted file mode 100644
index 38873c9d0..000000000
Binary files a/public/images/team/sean-keegan.jpg and /dev/null differ
diff --git a/public/images/uwu.png b/public/images/uwu.png
new file mode 100644
index 000000000..a09d245ea
Binary files /dev/null and b/public/images/uwu.png differ
diff --git a/public/mstile-150x150.png b/public/mstile-150x150.png
new file mode 100644
index 000000000..d36e7ee9e
Binary files /dev/null and b/public/mstile-150x150.png differ
diff --git a/public/safari-pinned-tab.svg b/public/safari-pinned-tab.svg
new file mode 100644
index 000000000..7e4874b2f
--- /dev/null
+++ b/public/safari-pinned-tab.svg
@@ -0,0 +1,60 @@
+
+
+
diff --git a/public/site.webmanifest b/public/site.webmanifest
new file mode 100644
index 000000000..337446d52
--- /dev/null
+++ b/public/site.webmanifest
@@ -0,0 +1,19 @@
+{
+ "name": "React",
+ "short_name": "React",
+ "icons": [
+ {
+ "src": "/android-chrome-192x192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ },
+ {
+ "src": "/android-chrome-384x384.png",
+ "sizes": "384x384",
+ "type": "image/png"
+ }
+ ],
+ "theme_color": "#23272f",
+ "background_color": "#23272f",
+ "display": "standalone"
+}
diff --git a/scripts/generateRss.js b/scripts/generateRss.js
new file mode 100644
index 000000000..e0f3d5561
--- /dev/null
+++ b/scripts/generateRss.js
@@ -0,0 +1,6 @@
+/*
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ */
+const {generateRssFeed} = require('../src/utils/rss');
+
+generateRssFeed();
diff --git a/src/components/ButtonLink.tsx b/src/components/ButtonLink.tsx
index 15ab83f2b..23c971756 100644
--- a/src/components/ButtonLink.tsx
+++ b/src/components/ButtonLink.tsx
@@ -26,7 +26,8 @@ function ButtonLink({
className,
'active:scale-[.98] transition-transform inline-flex font-bold items-center outline-none focus:outline-none focus-visible:outline focus-visible:outline-link focus:outline-offset-2 focus-visible:dark:focus:outline-link-dark leading-snug',
{
- 'bg-link text-white hover:bg-opacity-80': type === 'primary',
+ 'bg-link text-white dark:bg-brand-dark dark:text-secondary hover:bg-opacity-80':
+ type === 'primary',
'text-primary dark:text-primary-dark shadow-secondary-button-stroke dark:shadow-secondary-button-stroke-dark hover:bg-gray-40/5 active:bg-gray-40/10 hover:dark:bg-gray-60/5 active:dark:bg-gray-60/10':
type === 'secondary',
'text-lg py-3 rounded-full px-4 sm:px-6': size === 'lg',
diff --git a/src/components/DocsFooter.tsx b/src/components/DocsFooter.tsx
index 2fdbb0460..5f2330e7e 100644
--- a/src/components/DocsFooter.tsx
+++ b/src/components/DocsFooter.tsx
@@ -27,7 +27,7 @@ export const DocsPageFooter = memo(
<>
{prevRoute?.path || nextRoute?.path ? (
<>
-
+
{prevRoute?.path ? (
-
-
+
+
{type}
- {title}
-
+
+ {title}
+
+
);
}
diff --git a/src/components/ErrorDecoderContext.tsx b/src/components/ErrorDecoderContext.tsx
new file mode 100644
index 000000000..080969efe
--- /dev/null
+++ b/src/components/ErrorDecoderContext.tsx
@@ -0,0 +1,23 @@
+// Error Decoder requires reading pregenerated error message from getStaticProps,
+// but MDX component doesn't support props. So we use React Context to populate
+// the value without prop-drilling.
+// TODO: Replace with React.cache + React.use when migrating to Next.js App Router
+
+import {createContext, useContext} from 'react';
+
+const notInErrorDecoderContext = Symbol('not in error decoder context');
+
+export const ErrorDecoderContext = createContext<
+ | {errorMessage: string | null; errorCode: string | null}
+ | typeof notInErrorDecoderContext
+>(notInErrorDecoderContext);
+
+export const useErrorDecoderParams = () => {
+ const params = useContext(ErrorDecoderContext);
+
+ if (params === notInErrorDecoderContext) {
+ throw new Error('useErrorDecoder must be used in error decoder pages only');
+ }
+
+ return params;
+};
diff --git a/src/components/Icon/IconBsky.tsx b/src/components/Icon/IconBsky.tsx
new file mode 100644
index 000000000..6645152dd
--- /dev/null
+++ b/src/components/Icon/IconBsky.tsx
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ */
+
+import {memo} from 'react';
+
+export const IconBsky = memo(function IconBsky(
+ props
+) {
+ return (
+
+ );
+});
diff --git a/src/components/Icon/IconCanary.tsx b/src/components/Icon/IconCanary.tsx
index a7782b141..7f584fed7 100644
--- a/src/components/Icon/IconCanary.tsx
+++ b/src/components/Icon/IconCanary.tsx
@@ -4,29 +4,35 @@
import {memo} from 'react';
-export const IconCanary = memo(
- function IconCanary({className, title}) {
- return (
-
- );
+export const IconCanary = memo<
+ JSX.IntrinsicElements['svg'] & {title?: string; size?: 's' | 'md'}
+>(function IconCanary(
+ {className, title, size} = {
+ className: undefined,
+ title: undefined,
+ size: 'md',
}
-);
+) {
+ return (
+
+ );
+});
diff --git a/src/components/Icon/IconGitHub.tsx b/src/components/Icon/IconGitHub.tsx
index de2a982bd..49d7fb460 100644
--- a/src/components/Icon/IconGitHub.tsx
+++ b/src/components/Icon/IconGitHub.tsx
@@ -9,8 +9,8 @@ export const IconGitHub = memo(
return (