- Slugify tag/category static params so pre-rendered pages match links; disable dynamic params and return a real 404 via notFound() - Drop bogus generateStaticParams from the tags/categories index pages - Add a styled not-found page - Sort 'Recently updated' by last modification before slicing - Atom feed: correct rel=self URL, use updated dates, valid content type - Swap no-js -> js class in an inline head script before first paint - Markdown links: only route internal paths through next/link and tolerate missing hrefs
42 lines
1.1 KiB
TypeScript
42 lines
1.1 KiB
TypeScript
import { Space_Grotesk } from 'next/font/google'
|
|
import { Sidebar } from '@/components/layout/Sidebar'
|
|
import { MobileNavbar } from '@/components/layout/MobileNavbar'
|
|
import { metadata } from '@/app/metadata'
|
|
// eslint-disable-next-line import/no-unassigned-import
|
|
import '@/app/globals.css'
|
|
|
|
const spaceGrotesk = Space_Grotesk({
|
|
subsets: ['latin'],
|
|
variable: '--font-sans',
|
|
display: 'swap',
|
|
weight: ['400', '500', '600', '700'],
|
|
})
|
|
export default function RootLayout({
|
|
children,
|
|
}: Readonly<{
|
|
children: React.ReactNode
|
|
}>) {
|
|
return (
|
|
<html
|
|
lang="en"
|
|
className={`${spaceGrotesk.variable} h-full antialiased no-js`}
|
|
suppressHydrationWarning
|
|
>
|
|
<head>
|
|
{/* Runs before first paint so `js-only` elements don't flash in after hydration */}
|
|
<script
|
|
dangerouslySetInnerHTML={{
|
|
__html: `document.documentElement.classList.replace('no-js','js')`,
|
|
}}
|
|
/>
|
|
</head>
|
|
<body className="min-h-full flex">
|
|
<Sidebar />
|
|
<MobileNavbar />
|
|
{children}
|
|
</body>
|
|
</html>
|
|
)
|
|
}
|
|
|
|
export { metadata }
|