Migrate docs to Nextra 4 (App Router), Next 16, React 19
Upgrade to the latest major versions across the stack. Nextra 4 drops the Pages Router, so this is a full App Router migration: - theme.config.tsx -> config moved into app/layout.jsx (Navbar/Footer props) - add app/[[...mdxPath]]/page.jsx catch-all route and mdx-components.js - pages/*.mdx -> content/ (cli.mdx -> content/cli/index.mdx, asIndexPage) - add _meta.js sidebar ordering; remove pages/_app.jsx - favicon.ico moved into app/; pagefind search (postbuild + gitignore) Pin zod to 4.1.12 via pnpm.overrides: nextra-theme-docs@4.6.1 strips `children` before validating a schema that still requires it, which throws on zod 4.4.x's stricter z.custom() handling and 500s every page. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Seto Elkahfi committed
Jun 21, 2026 at 14:27 UTC
24b4eb1bcb819c13aa75f3d9d6327806fe75bdee
10 files changed
+140
app/[[...mdxPath]]/page.jsx
new
+27
@@ -0,0 +1,27 @@
1
+import { generateStaticParamsFor, importPage } from 'nextra/pages'
2
+import { useMDXComponents as getMDXComponents } from '../../mdx-components'
3
+
4
+export const generateStaticParams = generateStaticParamsFor('mdxPath')
5
+
6
+export async function generateMetadata(props) {
7
+ const params = await props.params
8
+ const { metadata } = await importPage(params.mdxPath)
9
+ return metadata
10
+}
11
+
12
+const Wrapper = getMDXComponents().wrapper
13
+
14
+export default async function Page(props) {
15
+ const params = await props.params
16
+ const {
17
+ default: MDXContent,
18
+ toc,
19
+ metadata,
20
+ sourceCode
21
+ } = await importPage(params.mdxPath)
22
+ return (
23
+ <Wrapper toc={toc} metadata={metadata} sourceCode={sourceCode}>
24
+ <MDXContent {...props} params={params} />
25
+ </Wrapper>
26
+ )
27
+}
app/favicon.ico
Binary files /dev/null and b/app/favicon.ico differ
app/layout.jsx
new
+57
@@ -0,0 +1,57 @@
1
+import { Footer, Layout, Navbar } from 'nextra-theme-docs'
2
+import { Head } from 'nextra/components'
3
+import { getPageMap } from 'nextra/page-map'
4
+import 'nextra-theme-docs/style.css'
5
+
6
+export const metadata = {
7
+ metadataBase: new URL('https://docs.smbcloud.xyz'),
8
+ title: {
9
+ default: 'smbCloud Documentation',
10
+ template: '%s – smbCloud Documentation'
11
+ },
12
+ description: 'smbCloud Documentation',
13
+ applicationName: 'smbCloud Documentation',
14
+ openGraph: {
15
+ title: 'smbCloud Documentation',
16
+ description: 'smbCloud Documentation',
17
+ url: 'https://docs.smbcloud.xyz',
18
+ siteName: 'smbCloud Documentation'
19
+ }
20
+}
21
+
22
+const navbar = (
23
+ <Navbar
24
+ logo={<span>smbCloud Documentation</span>}
25
+ projectLink="https://github.com/smbcloudXYZ"
26
+ />
27
+)
28
+
29
+const footer = (
30
+ <Footer>
31
+ MIT {new Date().getFullYear()} ©{' '}
32
+ <a href="https://docs.smbcloud.xyz" target="_blank" rel="noreferrer">
33
+ smbCloud Documentation
34
+ </a>
35
+ </Footer>
36
+)
37
+
38
+export default async function RootLayout({ children }) {
39
+ const pageMap = await getPageMap()
40
+ return (
41
+ <html lang="en" dir="ltr" suppressHydrationWarning>
42
+ <Head />
43
+ <body>
44
+ <Layout
45
+ navbar={navbar}
46
+ footer={footer}
47
+ pageMap={pageMap}
48
+ docsRepositoryBase="https://github.com/smbcloudXYZ/smbcloud-docs/tree/main"
49
+ editLink="Edit this page on GitHub"
50
+ sidebar={{ defaultMenuCollapseLevel: 1 }}
51
+ >
52
+ {children}
53
+ </Layout>
54
+ </body>
55
+ </html>
56
+ )
57
+}
content/_meta.js
new
+5
@@ -0,0 +1,5 @@
1
+export default {
2
+ index: 'Introduction',
3
+ cli: 'CLI',
4
+ about: 'About'
5
+}
content/about.mdx
new
+3
@@ -0,0 +1,3 @@
1
+# About
2
+
3
+This is the documentation page for smbCloud, the unified cloud platform for modern app deployment.
\ No newline at end of file
content/cli/_meta.js
new
+3
@@ -0,0 +1,3 @@
1
+export default {
2
+ setup: 'Setup'
3
+}
content/cli/index.mdx
new
+7
@@ -0,0 +1,7 @@
1
+---
2
+asIndexPage: true
3
+---
4
+
5
+# CLI
6
+
7
+We use CLI program to interact with smbCloud resources.
\ No newline at end of file
content/cli/setup.mdx
new
+23
@@ -0,0 +1,23 @@
1
+# Setup
2
+
3
+Our CLI interface is build with Rust and published on [Crates.io](https://crates.io/crates/smbcloud-cli).
4
+
5
+1. Setup your [Rust](https://www.rust-lang.org/tools/install).
6
+2. Install it globally with cargo: `cargo install smbcloud-cli`.
7
+3. Run `smb` command in your teminal to check your installation. You should get something like this:
8
+
9
+```
10
+╰─➤ smb
11
+Command line tool for creating and managing smbCloud resources.
12
+
13
+Usage: smb [OPTIONS] <COMMAND>
14
+
15
+Commands:
16
+ login Login to your account. To create an account, visit https://smbcloud.xyz
17
+ help Print this message or the help of the given subcommand(s)
18
+
19
+Options:
20
+ -l, --log-level <LOG_LEVEL> Log level: trace, debug, info, warn, error, off
21
+ -h, --help Print help
22
+ -V, --version Print version
23
+```
\ No newline at end of file
content/index.mdx
new
+7
@@ -0,0 +1,7 @@
1
+# smbCloud Documentation
2
+
3
+Find technical documentation for smbCloud services, SDKs and toolkits, use cases, scenarios, and tasks. Browse user guides, developer guides, tutorials, and API references.
4
+
5
+## What is smbCloud?
6
+
7
+A **simple**, **powerful** and **flexible** cloud platform for the next generation web.
mdx-components.js
new
+8
@@ -0,0 +1,8 @@
1
+import { useMDXComponents as getDocsMDXComponents } from 'nextra-theme-docs'
2
+
3
+const docsComponents = getDocsMDXComponents()
4
+
5
+export const useMDXComponents = components => ({
6
+ ...docsComponents,
7
+ ...components
8
+})