Skip to content

Commit 5da0ada

Browse files
committed
Refactor: share part of root layout across App/Pages Routers
1 parent 8f5a120 commit 5da0ada

File tree

4 files changed

+178
-140
lines changed

4 files changed

+178
-140
lines changed

src/app/layout.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import {SharedRootBody, SharedRootHead} from '../components/_/root-layout';
2+
import {siteConfig} from '../siteConfig';
3+
4+
export default function RootLayout({children}: React.PropsWithChildren) {
5+
return (
6+
<html lang={siteConfig.languageCode} dir={siteConfig.isRTL ? 'rtl' : 'ltr'}>
7+
<head>
8+
<SharedRootHead />
9+
</head>
10+
<SharedRootBody>{children}</SharedRootBody>
11+
</html>
12+
);
13+
}

src/components/_/README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# `components/_` folder {/*components_-folder*/}
2+
3+
This folder surves as a temporary location during transition from Next.js Pages Router to Next.js App Router. During this phase, many layout components may be shared bwetween both Next.js Pages Router and Next.js App Router.
4+
5+
Due to the requirements of the Next.js Pages Router, any components under this foldeer must either be shared components or client components. React Server Components are not allowed in this folder.
6+
7+
Once the migration to Next.js App Router is complete, this folder will be removed, and all components will be relocated to their appropriate locations.

src/components/_/root-layout.tsx

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
import type React from 'react';
2+
3+
export function SharedRootHead() {
4+
return (
5+
<>
6+
<link
7+
rel="apple-touch-icon"
8+
sizes="180x180"
9+
href="/apple-touch-icon.png"
10+
/>
11+
<link
12+
rel="icon"
13+
type="image/png"
14+
sizes="32x32"
15+
href="/favicon-32x32.png"
16+
/>
17+
<link
18+
rel="icon"
19+
type="image/png"
20+
sizes="16x16"
21+
href="/favicon-16x16.png"
22+
/>
23+
<link rel="manifest" href="/site.webmanifest" />
24+
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#404756" />
25+
<meta name="msapplication-TileColor" content="#2b5797" />
26+
<meta name="theme-color" content="#23272f" />
27+
<script
28+
async
29+
src={`https://www.googletagmanager.com/gtag/js?id=${process.env.NEXT_PUBLIC_GA_TRACKING_ID}`}
30+
/>
31+
<script
32+
dangerouslySetInnerHTML={{
33+
__html: `window.dataLayer = window.dataLayer || [];function gtag(){dataLayer.push(arguments);}gtag('js', new Date());gtag('config', '${process.env.NEXT_PUBLIC_GA_TRACKING_ID}');`,
34+
}}
35+
/>
36+
</>
37+
);
38+
}
39+
40+
export function SharedRootBody({children}: React.PropsWithChildren) {
41+
return (
42+
<body className="font-text font-medium antialiased text-lg bg-wash dark:bg-wash-dark text-secondary dark:text-secondary-dark leading-base">
43+
<script
44+
dangerouslySetInnerHTML={{
45+
__html: `
46+
(function () {
47+
try {
48+
let logShown = false;
49+
function setUwu(isUwu) {
50+
try {
51+
if (isUwu) {
52+
localStorage.setItem('uwu', true);
53+
document.documentElement.classList.add('uwu');
54+
if (!logShown) {
55+
console.log('uwu mode! turn off with ?uwu=0');
56+
console.log('logo credit to @sawaratsuki1004 via https://github.com/SAWARATSUKI/ServiceLogos');
57+
logShown = true;
58+
}
59+
} else {
60+
localStorage.removeItem('uwu');
61+
document.documentElement.classList.remove('uwu');
62+
console.log('uwu mode off. turn on with ?uwu');
63+
}
64+
} catch (err) { }
65+
}
66+
window.__setUwu = setUwu;
67+
function checkQueryParam() {
68+
const params = new URLSearchParams(window.location.search);
69+
const value = params.get('uwu');
70+
switch(value) {
71+
case '':
72+
case 'true':
73+
case '1':
74+
return true;
75+
case 'false':
76+
case '0':
77+
return false;
78+
default:
79+
return null;
80+
}
81+
}
82+
function checkLocalStorage() {
83+
try {
84+
return localStorage.getItem('uwu') === 'true';
85+
} catch (err) {
86+
return false;
87+
}
88+
}
89+
const uwuQueryParam = checkQueryParam();
90+
if (uwuQueryParam != null) {
91+
setUwu(uwuQueryParam);
92+
} else if (checkLocalStorage()) {
93+
document.documentElement.classList.add('uwu');
94+
}
95+
} catch (err) { }
96+
})();
97+
`,
98+
}}
99+
/>
100+
<script
101+
dangerouslySetInnerHTML={{
102+
__html: `
103+
(function () {
104+
function setTheme(newTheme) {
105+
window.__theme = newTheme;
106+
if (newTheme === 'dark') {
107+
document.documentElement.classList.add('dark');
108+
} else if (newTheme === 'light') {
109+
document.documentElement.classList.remove('dark');
110+
}
111+
}
112+
113+
var preferredTheme;
114+
try {
115+
preferredTheme = localStorage.getItem('theme');
116+
} catch (err) { }
117+
118+
window.__setPreferredTheme = function(newTheme) {
119+
preferredTheme = newTheme;
120+
setTheme(newTheme);
121+
try {
122+
localStorage.setItem('theme', newTheme);
123+
} catch (err) { }
124+
};
125+
126+
var initialTheme = preferredTheme;
127+
var darkQuery = window.matchMedia('(prefers-color-scheme: dark)');
128+
129+
if (!initialTheme) {
130+
initialTheme = darkQuery.matches ? 'dark' : 'light';
131+
}
132+
setTheme(initialTheme);
133+
134+
darkQuery.addEventListener('change', function (e) {
135+
if (!preferredTheme) {
136+
setTheme(e.matches ? 'dark' : 'light');
137+
}
138+
});
139+
140+
// Detect whether the browser is Mac to display platform specific content
141+
// An example of such content can be the keyboard shortcut displayed in the search bar
142+
document.documentElement.classList.add(
143+
window.navigator.platform.includes('Mac')
144+
? "platform-mac"
145+
: "platform-win"
146+
);
147+
})();
148+
`,
149+
}}
150+
/>
151+
{children}
152+
</body>
153+
);
154+
}

src/pages/_document.tsx

Lines changed: 4 additions & 140 deletions
Original file line numberDiff line numberDiff line change
@@ -11,153 +11,17 @@
1111

1212
import {Html, Head, Main, NextScript} from 'next/document';
1313
import {siteConfig} from '../siteConfig';
14+
import {SharedRootBody, SharedRootHead} from '../components/_/root-layout';
1415

1516
const MyDocument = () => {
1617
return (
1718
<Html lang={siteConfig.languageCode} dir={siteConfig.isRTL ? 'rtl' : 'ltr'}>
1819
<Head />
19-
<link
20-
rel="apple-touch-icon"
21-
sizes="180x180"
22-
href="/apple-touch-icon.png"
23-
/>
24-
<link
25-
rel="icon"
26-
type="image/png"
27-
sizes="32x32"
28-
href="/favicon-32x32.png"
29-
/>
30-
<link
31-
rel="icon"
32-
type="image/png"
33-
sizes="16x16"
34-
href="/favicon-16x16.png"
35-
/>
36-
<link rel="manifest" href="/site.webmanifest" />
37-
<link rel="mask-icon" href="/safari-pinned-tab.svg" color="#404756" />
38-
<meta name="msapplication-TileColor" content="#2b5797" />
39-
<meta name="theme-color" content="#23272f" />
40-
<script
41-
async
42-
src={`https://www.googletagmanager.com/gtag/js?id=${process.env.NEXT_PUBLIC_GA_TRACKING_ID}`}
43-
/>
44-
<script
45-
dangerouslySetInnerHTML={{
46-
__html: `window.dataLayer = window.dataLayer || [];function gtag(){dataLayer.push(arguments);}gtag('js', new Date());gtag('config', '${process.env.NEXT_PUBLIC_GA_TRACKING_ID}');`,
47-
}}
48-
/>
49-
<body className="font-text font-medium antialiased text-lg bg-wash dark:bg-wash-dark text-secondary dark:text-secondary-dark leading-base">
50-
<script
51-
dangerouslySetInnerHTML={{
52-
__html: `
53-
(function () {
54-
try {
55-
let logShown = false;
56-
function setUwu(isUwu) {
57-
try {
58-
if (isUwu) {
59-
localStorage.setItem('uwu', true);
60-
document.documentElement.classList.add('uwu');
61-
if (!logShown) {
62-
console.log('uwu mode! turn off with ?uwu=0');
63-
console.log('logo credit to @sawaratsuki1004 via https://github.com/SAWARATSUKI/ServiceLogos');
64-
logShown = true;
65-
}
66-
} else {
67-
localStorage.removeItem('uwu');
68-
document.documentElement.classList.remove('uwu');
69-
console.log('uwu mode off. turn on with ?uwu');
70-
}
71-
} catch (err) { }
72-
}
73-
window.__setUwu = setUwu;
74-
function checkQueryParam() {
75-
const params = new URLSearchParams(window.location.search);
76-
const value = params.get('uwu');
77-
switch(value) {
78-
case '':
79-
case 'true':
80-
case '1':
81-
return true;
82-
case 'false':
83-
case '0':
84-
return false;
85-
default:
86-
return null;
87-
}
88-
}
89-
function checkLocalStorage() {
90-
try {
91-
return localStorage.getItem('uwu') === 'true';
92-
} catch (err) {
93-
return false;
94-
}
95-
}
96-
const uwuQueryParam = checkQueryParam();
97-
if (uwuQueryParam != null) {
98-
setUwu(uwuQueryParam);
99-
} else if (checkLocalStorage()) {
100-
document.documentElement.classList.add('uwu');
101-
}
102-
} catch (err) { }
103-
})();
104-
`,
105-
}}
106-
/>
107-
<script
108-
dangerouslySetInnerHTML={{
109-
__html: `
110-
(function () {
111-
function setTheme(newTheme) {
112-
window.__theme = newTheme;
113-
if (newTheme === 'dark') {
114-
document.documentElement.classList.add('dark');
115-
} else if (newTheme === 'light') {
116-
document.documentElement.classList.remove('dark');
117-
}
118-
}
119-
120-
var preferredTheme;
121-
try {
122-
preferredTheme = localStorage.getItem('theme');
123-
} catch (err) { }
124-
125-
window.__setPreferredTheme = function(newTheme) {
126-
preferredTheme = newTheme;
127-
setTheme(newTheme);
128-
try {
129-
localStorage.setItem('theme', newTheme);
130-
} catch (err) { }
131-
};
132-
133-
var initialTheme = preferredTheme;
134-
var darkQuery = window.matchMedia('(prefers-color-scheme: dark)');
135-
136-
if (!initialTheme) {
137-
initialTheme = darkQuery.matches ? 'dark' : 'light';
138-
}
139-
setTheme(initialTheme);
140-
141-
darkQuery.addEventListener('change', function (e) {
142-
if (!preferredTheme) {
143-
setTheme(e.matches ? 'dark' : 'light');
144-
}
145-
});
146-
147-
// Detect whether the browser is Mac to display platform specific content
148-
// An example of such content can be the keyboard shortcut displayed in the search bar
149-
document.documentElement.classList.add(
150-
window.navigator.platform.includes('Mac')
151-
? "platform-mac"
152-
: "platform-win"
153-
);
154-
})();
155-
`,
156-
}}
157-
/>
20+
<SharedRootHead />
21+
<SharedRootBody>
15822
<Main />
15923
<NextScript />
160-
</body>
24+
</SharedRootBody>
16125
</Html>
16226
);
16327
};

0 commit comments

Comments
 (0)