Skip to content

Commit 207988a

Browse files
Add Nest hosting configuration
## Summary - Add `nest.json` with project config (name: react_docs, framework: nextjs, oncall: react_core) - Move redirects and headers from `vercel.json` into `next.config.js` so they work on both Vercel and Nest hosting - Strip redundant redirects/headers from `vercel.json`, keeping only Vercel-specific settings (github.silent, trailingSlash) - Add `/api/health` health check endpoint for deployment monitoring
1 parent 40ea071 commit 207988a

File tree

5 files changed

+320
-280
lines changed

5 files changed

+320
-280
lines changed

nest.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"name": "react_docs",
3+
"framework": "nextjs",
4+
"oncall": "react_core"
5+
}

next.config.js

Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,303 @@ const nextConfig = {
4343
],
4444
};
4545
},
46+
async redirects() {
47+
return [
48+
{
49+
source: '/reference',
50+
destination: '/reference/react',
51+
permanent: true,
52+
},
53+
{
54+
source: '/reference/react-dom/hooks/useFormState',
55+
destination: '/reference/react/useActionState',
56+
permanent: true,
57+
},
58+
{
59+
source: '/learn/meet-the-team',
60+
destination: '/community/team',
61+
permanent: true,
62+
},
63+
{
64+
source: '/link/warning-keys',
65+
destination:
66+
'/learn/rendering-lists#keeping-list-items-in-order-with-key',
67+
permanent: false,
68+
},
69+
{
70+
source: '/docs/lists-and-keys',
71+
destination:
72+
'/learn/rendering-lists#keeping-list-items-in-order-with-key',
73+
permanent: false,
74+
},
75+
{
76+
source: '/link/invalid-hook-call',
77+
destination: '/warnings/invalid-hook-call-warning',
78+
permanent: false,
79+
},
80+
{
81+
source: '/link/hooks-data-fetching',
82+
destination: '/reference/react/useEffect#fetching-data-with-effects',
83+
permanent: false,
84+
},
85+
{
86+
source: '/link/special-props',
87+
destination: '/warnings/special-props',
88+
permanent: false,
89+
},
90+
{
91+
source: '/link/dangerously-set-inner-html',
92+
destination:
93+
'/reference/react-dom/components/common#dangerously-setting-the-inner-html',
94+
permanent: false,
95+
},
96+
{
97+
source: '/link/controlled-components',
98+
destination:
99+
'/reference/react-dom/components/input#controlling-an-input-with-a-state-variable',
100+
permanent: false,
101+
},
102+
{
103+
source: '/link/react-devtools',
104+
destination: '/learn/react-developer-tools',
105+
permanent: false,
106+
},
107+
{
108+
source: '/link/invalid-aria-props',
109+
destination: '/warnings/invalid-aria-prop',
110+
permanent: false,
111+
},
112+
{
113+
source: '/link/hydration-mismatch',
114+
destination:
115+
'/reference/react-dom/client/hydrateRoot#hydrating-server-rendered-html',
116+
permanent: false,
117+
},
118+
{
119+
source: '/link/switch-to-createroot',
120+
destination:
121+
'/blog/2022/03/08/react-18-upgrade-guide#updates-to-client-rendering-apis',
122+
permanent: false,
123+
},
124+
{
125+
source: '/link/error-boundaries',
126+
destination:
127+
'/reference/react/Component#catching-rendering-errors-with-an-error-boundary',
128+
permanent: false,
129+
},
130+
{
131+
source: '/link/strict-mode-find-node',
132+
destination:
133+
'https://18.react.dev/reference/react-dom/findDOMNode#alternatives',
134+
permanent: false,
135+
},
136+
{
137+
source: '/link/rules-of-hooks',
138+
destination: '/warnings/invalid-hook-call-warning',
139+
permanent: false,
140+
},
141+
{
142+
source: '/link/event-pooling',
143+
destination:
144+
'https://legacy.reactjs.org/docs/legacy-event-pooling.html',
145+
permanent: false,
146+
},
147+
{
148+
source: '/link/legacy-context',
149+
destination:
150+
'https://react.dev/blog/2024/04/25/react-19-upgrade-guide#removed-removing-legacy-context',
151+
permanent: false,
152+
},
153+
{
154+
source: '/link/crossorigin-error',
155+
destination: 'https://legacy.reactjs.org/docs/cross-origin-errors.html',
156+
permanent: false,
157+
},
158+
{
159+
source: '/link/react-polyfills',
160+
destination:
161+
'https://legacy.reactjs.org/docs/javascript-environment-requirements.html',
162+
permanent: false,
163+
},
164+
{
165+
source: '/link/wrap-tests-with-act',
166+
destination: 'https://legacy.reactjs.org/docs/test-utils.html#act',
167+
permanent: false,
168+
},
169+
{
170+
source: '/link/refs-must-have-owner',
171+
destination:
172+
'https://legacy.reactjs.org/warnings/refs-must-have-owner.html',
173+
permanent: false,
174+
},
175+
{
176+
source: '/link/derived-state',
177+
destination:
178+
'https://legacy.reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html',
179+
permanent: false,
180+
},
181+
{
182+
source: '/link/strict-mode-string-ref',
183+
destination:
184+
'https://legacy.reactjs.org/docs/refs-and-the-dom.html#legacy-api-string-refs',
185+
permanent: false,
186+
},
187+
{
188+
source: '/link/perf-use-production-build',
189+
destination:
190+
'https://legacy.reactjs.org/docs/optimizing-performance.html#use-the-production-build',
191+
permanent: false,
192+
},
193+
{
194+
source: '/link/unsafe-component-lifecycles',
195+
destination:
196+
'https://legacy.reactjs.org/blog/2018/03/27/update-on-async-rendering.html',
197+
permanent: false,
198+
},
199+
{
200+
source: '/link/test-utils-mock-component',
201+
destination:
202+
'https://gist.github.com/bvaughn/fbf41b3f895bf2d297935faa5525eee9',
203+
permanent: false,
204+
},
205+
{
206+
source: '/link/attribute-behavior',
207+
destination:
208+
'https://legacy.reactjs.org/blog/2017/09/08/dom-attributes-in-react-16.html#changes-in-detail',
209+
permanent: false,
210+
},
211+
{
212+
source: '/link/react-devtools-faq',
213+
destination:
214+
'https://github.com/facebook/react/tree/main/packages/react-devtools#faq',
215+
permanent: false,
216+
},
217+
{
218+
source: '/link/setstate-in-render',
219+
destination:
220+
'https://github.com/facebook/react/issues/18178#issuecomment-595846312',
221+
permanent: false,
222+
},
223+
{
224+
source: '/link/new-jsx-transform',
225+
destination:
226+
'https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html',
227+
permanent: false,
228+
},
229+
{
230+
source: '/link/cra',
231+
destination: '/blog/2025/02/14/sunsetting-create-react-app',
232+
permanent: false,
233+
},
234+
{
235+
source: '/warnings/version-mismatch',
236+
destination:
237+
'/warnings/invalid-hook-call-warning#mismatching-versions-of-react-and-react-dom',
238+
permanent: false,
239+
},
240+
{
241+
source: '/reference/react/directives',
242+
destination: '/reference/rsc/directives',
243+
permanent: true,
244+
},
245+
{
246+
source: '/reference/react/use-client',
247+
destination: '/reference/rsc/use-client',
248+
permanent: true,
249+
},
250+
{
251+
source: '/reference/react/use-server',
252+
destination: '/reference/rsc/use-server',
253+
permanent: true,
254+
},
255+
{
256+
source: '/reference/rsc/server-actions',
257+
destination: '/reference/rsc/server-functions',
258+
permanent: true,
259+
},
260+
{
261+
source: '/reference/react-dom/findDOMNode',
262+
destination: 'https://18.react.dev/reference/react-dom/findDOMNode',
263+
permanent: true,
264+
},
265+
{
266+
source: '/reference/react/createFactory',
267+
destination: 'https://18.react.dev/reference/react/createFactory',
268+
permanent: true,
269+
},
270+
{
271+
source: '/reference/react-dom/render',
272+
destination: 'https://18.react.dev/reference/react-dom/render',
273+
permanent: true,
274+
},
275+
{
276+
source: '/reference/react-dom/hydrate',
277+
destination: 'https://18.react.dev/reference/react-dom/hydrate',
278+
permanent: true,
279+
},
280+
{
281+
source: '/reference/react-dom/unmountComponentAtNode',
282+
destination:
283+
'https://18.react.dev/reference/react-dom/unmountComponentAtNode',
284+
permanent: true,
285+
},
286+
{
287+
source: '/reference/react-dom/server/renderToStaticNodeStream',
288+
destination:
289+
'https://18.react.dev/reference/react-dom/server/renderToStaticNodeStream',
290+
permanent: true,
291+
},
292+
{
293+
source: '/reference/react-dom/server/renderToNodeStream',
294+
destination:
295+
'https://18.react.dev/reference/react-dom/server/renderToNodeStream',
296+
permanent: true,
297+
},
298+
{
299+
source: '/learn/start-a-new-react-project',
300+
destination: '/learn/creating-a-react-app',
301+
permanent: true,
302+
},
303+
{
304+
source: '/learn/building-a-react-framework',
305+
destination: '/learn/build-a-react-app-from-scratch',
306+
permanent: true,
307+
},
308+
{
309+
source: '/blog/2024/04/25/react-19',
310+
destination: '/blog/2024/12/05/react-19',
311+
permanent: true,
312+
},
313+
{
314+
source: '/feed.xml',
315+
destination: '/rss.xml',
316+
permanent: true,
317+
},
318+
{
319+
source: '/reference/react/experimental_useEffectEvent',
320+
destination: '/reference/react/useEffectEvent',
321+
permanent: true,
322+
},
323+
{
324+
source: '/blog/2025/04/21/react-compiler-rc',
325+
destination: '/blog/2025/10/07/react-compiler-1',
326+
permanent: true,
327+
},
328+
];
329+
},
330+
async headers() {
331+
return [
332+
{
333+
source: '/fonts/(.*).woff2',
334+
headers: [
335+
{
336+
key: 'Cache-Control',
337+
value: 'public, max-age=31536000, immutable',
338+
},
339+
],
340+
},
341+
];
342+
},
46343
env: {},
47344
webpack: (config, {dev, isServer, ...options}) => {
48345
if (process.env.ANALYZE) {

scripts/deadLinkChecker.js

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -326,23 +326,20 @@ async function fetchErrorCodes() {
326326

327327
async function buildRedirectsMap() {
328328
try {
329-
const vercelConfigPath = path.join(__dirname, '../vercel.json');
330-
const vercelConfig = JSON.parse(
331-
await fs.promises.readFile(vercelConfigPath, 'utf8')
332-
);
333-
334-
if (vercelConfig.redirects) {
335-
for (const redirect of vercelConfig.redirects) {
329+
const nextConfig = require('../next.config.js');
330+
if (typeof nextConfig.redirects === 'function') {
331+
const redirects = await nextConfig.redirects();
332+
for (const redirect of redirects) {
336333
redirectMap.set(redirect.source, redirect.destination);
337334
}
338-
console.log(
339-
chalk.gray(`Loaded ${redirectMap.size} redirects from vercel.json`)
340-
);
341335
}
336+
console.log(
337+
chalk.gray(`Loaded ${redirectMap.size} redirects from next.config.js`)
338+
);
342339
} catch (error) {
343340
console.log(
344341
chalk.yellow(
345-
`Warning: Could not load redirects from vercel.json: ${error.message}\n`
342+
`Warning: Could not load redirects from next.config.js: ${error.message}\n`
346343
)
347344
);
348345
}

src/pages/api/health.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import type {NextApiRequest, NextApiResponse} from 'next';
2+
3+
export default function handler(req: NextApiRequest, res: NextApiResponse) {
4+
if (req.method !== 'GET') {
5+
res.setHeader('Allow', 'GET');
6+
return res.status(405).send('Method not allowed');
7+
}
8+
res.status(200).json({status: 'healthy'});
9+
}

0 commit comments

Comments
 (0)