diff --git a/content/contracts/index.mdx b/content/contracts/index.mdx
new file mode 100644
index 00000000..ac391133
--- /dev/null
+++ b/content/contracts/index.mdx
@@ -0,0 +1,13 @@
+---
+title: Contracts
+description: OpenZeppelin Contracts documentation
+---
+
+# OpenZeppelin Contracts
+
+Welcome to the OpenZeppelin Contracts documentation. Choose your version:
+
+- [v5.x (Latest)](/contracts/v5.x/) - Latest stable version with new features
+- [v4.x](/contracts/v4.x/) - Previous major version
+- [v3.x](/contracts/v3.x/) - Legacy version
+- [v2.x](/contracts/v2.x/) - Legacy version
\ No newline at end of file
diff --git a/next.config.mjs b/next.config.mjs
index 457dcf29..b422c44b 100644
--- a/next.config.mjs
+++ b/next.config.mjs
@@ -1,10 +1,11 @@
-import { createMDX } from 'fumadocs-mdx/next';
+import { createMDX } from "fumadocs-mdx/next";
const withMDX = createMDX();
/** @type {import('next').NextConfig} */
const config = {
- reactStrictMode: true,
+ reactStrictMode: true,
+ output: "export",
};
export default withMDX(config);
diff --git a/package.json b/package.json
index 9ad78ea9..ecc7ebc8 100644
--- a/package.json
+++ b/package.json
@@ -16,6 +16,7 @@
},
"dependencies": {
"@netlify/plugin-nextjs": "^5.13.0",
+ "@orama/orama": "^3.1.12",
"@radix-ui/react-separator": "^1.1.7",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index d740e92c..cbf7e44e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -11,6 +11,9 @@ importers:
'@netlify/plugin-nextjs':
specifier: ^5.13.0
version: 5.13.0
+ '@orama/orama':
+ specifier: ^3.1.12
+ version: 3.1.12
'@radix-ui/react-separator':
specifier: ^1.1.7
version: 1.1.7(@types/react-dom@19.1.9(@types/react@19.1.12))(@types/react@19.1.12)(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
diff --git a/src/app/api/search/route.ts b/src/app/api/search/route.ts
deleted file mode 100644
index d4ab9962..00000000
--- a/src/app/api/search/route.ts
+++ /dev/null
@@ -1,7 +0,0 @@
-import { createFromSource } from "fumadocs-core/search/server";
-import { source } from "@/lib/source";
-
-export const { GET } = createFromSource(source, {
- // https://docs.orama.com/open-source/supported-languages
- language: "english",
-});
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index e211c8f7..25f9af03 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,5 +1,5 @@
import "@/app/global.css";
-import { RootProvider } from "fumadocs-ui/provider";
+import { Provider } from "./provider";
import { Inter } from "next/font/google";
import type { ReactNode } from "react";
@@ -11,7 +11,7 @@ export default function Layout({ children }: { children: ReactNode }) {
return (
- {children}
+ {children}
);
diff --git a/src/app/provider.tsx b/src/app/provider.tsx
new file mode 100644
index 00000000..36807b5c
--- /dev/null
+++ b/src/app/provider.tsx
@@ -0,0 +1,8 @@
+"use client";
+
+import { RootProvider } from "fumadocs-ui/provider";
+import type { ReactNode } from "react";
+
+export function Provider({ children }: { children: ReactNode }) {
+ return {children};
+}
diff --git a/src/components/search.tsx b/src/components/search.tsx
new file mode 100644
index 00000000..01d70ea6
--- /dev/null
+++ b/src/components/search.tsx
@@ -0,0 +1,51 @@
+"use client";
+import {
+ SearchDialog,
+ SearchDialogClose,
+ SearchDialogContent,
+ SearchDialogHeader,
+ SearchDialogIcon,
+ SearchDialogInput,
+ SearchDialogList,
+ SearchDialogOverlay,
+ type SharedProps,
+} from "fumadocs-ui/components/dialog/search";
+import { useDocsSearch } from "fumadocs-core/search/client";
+import { create } from "@orama/orama";
+import { useI18n } from "fumadocs-ui/contexts/i18n";
+
+function initOrama() {
+ return create({
+ schema: { _: "string" },
+ // https://docs.orama.com/docs/orama-js/supported-languages
+ language: "english",
+ });
+}
+
+export default function DefaultSearchDialog(props: SharedProps) {
+ const { locale } = useI18n(); // (optional) for i18n
+ const { search, setSearch, query } = useDocsSearch({
+ type: "static",
+ initOrama,
+ locale,
+ });
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/middleware.ts b/src/middleware.ts
deleted file mode 100644
index e9ed3945..00000000
--- a/src/middleware.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import { type NextRequest, NextResponse } from "next/server";
-
-// Version mappings for redirects
-const VERSION_REDIRECTS: Record = {
- contracts: "contracts/v5.x",
- "contracts-upgradeable": "contracts-upgradeable/v5.x",
- "cairo-contracts": "cairo-contracts/v2.x",
- "community-contracts": "community-contracts/v1.x",
- "compact-contracts": "compact-contracts/v0.x",
- "confidential-contracts": "confidential-contracts/v0.x",
- "contracts-stylus": "contracts-stylus/v0.x",
- "stellar-contracts": "stellar-contracts/v0.x",
- "substrate-runtimes": "substrate-runtimes/v3.x",
- nile: "nile/v0.x",
- "uniswap-hooks": "uniswap-hooks/v1.x",
- "tools/openzeppelin-monitor": "tools/openzeppelin-monitor/v1.x",
-};
-
-export function middleware(request: NextRequest) {
- const { pathname } = request.nextUrl;
-
- // Check if this path needs a version redirect
- for (const [path, redirect] of Object.entries(VERSION_REDIRECTS)) {
- if (pathname === `/${path}` || pathname === `/${path}/`) {
- const url = request.nextUrl.clone();
- url.pathname = `/${redirect}`;
- return NextResponse.redirect(url);
- }
- }
-
- return NextResponse.next();
-}
-
-export const config = {
- matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
-};