diff --git a/documentation/.gitignore b/documentation/.gitignore
new file mode 100644
index 0000000..9e429e4
--- /dev/null
+++ b/documentation/.gitignore
@@ -0,0 +1,26 @@
+# deps
+/node_modules
+
+# generated content
+.source
+
+# test & build
+/coverage
+/.next/
+/out/
+/build
+*.tsbuildinfo
+
+# misc
+.DS_Store
+*.pem
+/.pnp
+.pnp.js
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# others
+.env*.local
+.vercel
+next-env.d.ts
\ No newline at end of file
diff --git a/documentation/README.md b/documentation/README.md
new file mode 100644
index 0000000..17a3003
--- /dev/null
+++ b/documentation/README.md
@@ -0,0 +1,45 @@
+# documentation
+
+This is a Next.js application generated with
+[Create Fumadocs](https://github.com/fuma-nama/fumadocs).
+
+Run development server:
+
+```bash
+npm run dev
+# or
+pnpm dev
+# or
+yarn dev
+```
+
+Open http://localhost:3000 with your browser to see the result.
+
+## Explore
+
+In the project, you can see:
+
+- `lib/source.ts`: Code for content source adapter, [`loader()`](https://fumadocs.dev/docs/headless/source-api) provides the interface to access your content.
+- `lib/layout.shared.tsx`: Shared options for layouts, optional but preferred to keep.
+
+| Route | Description |
+| ------------------------- | ------------------------------------------------------ |
+| `app/(home)` | The route group for your landing page and other pages. |
+| `app/docs` | The documentation layout and pages. |
+| `app/api/search/route.ts` | The Route Handler for search. |
+
+### Fumadocs MDX
+
+A `source.config.ts` config file has been included, you can customise different options like frontmatter schema.
+
+Read the [Introduction](https://fumadocs.dev/docs/mdx) for further details.
+
+## Learn More
+
+To learn more about Next.js and Fumadocs, take a look at the following
+resources:
+
+- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js
+ features and API.
+- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
+- [Fumadocs](https://fumadocs.dev) - learn about Fumadocs
diff --git a/documentation/biome.json b/documentation/biome.json
new file mode 100644
index 0000000..593467c
--- /dev/null
+++ b/documentation/biome.json
@@ -0,0 +1,41 @@
+{
+ "$schema": "https://biomejs.dev/schemas/2.3.11/schema.json",
+ "vcs": {
+ "enabled": true,
+ "clientKind": "git",
+ "useIgnoreFile": true
+ },
+ "files": {
+ "ignoreUnknown": true,
+ "includes": [
+ "**",
+ "!node_modules",
+ "!.next",
+ "!dist",
+ "!build",
+ "!.source"
+ ]
+ },
+ "formatter": {
+ "enabled": true,
+ "indentStyle": "tab",
+ "indentWidth": 1
+ },
+ "linter": {
+ "enabled": true,
+ "rules": {
+ "recommended": true
+ },
+ "domains": {
+ "next": "recommended",
+ "react": "recommended"
+ }
+ },
+ "assist": {
+ "actions": {
+ "source": {
+ "organizeImports": "on"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/documentation/content/docs/index.mdx b/documentation/content/docs/index.mdx
new file mode 100644
index 0000000..1ede18e
--- /dev/null
+++ b/documentation/content/docs/index.mdx
@@ -0,0 +1,13 @@
+---
+title: Hello World
+description: Your first document
+---
+
+Welcome to the docs! You can start writing documents in `/content/docs`.
+
+## What is Next?
+
+
+
+
+
diff --git a/documentation/content/docs/test.mdx b/documentation/content/docs/test.mdx
new file mode 100644
index 0000000..f475f4a
--- /dev/null
+++ b/documentation/content/docs/test.mdx
@@ -0,0 +1,17 @@
+---
+title: Components
+description: Components
+---
+
+## Code Block
+
+```js
+console.log('Hello World');
+```
+
+## Cards
+
+
+
+
+
diff --git a/documentation/next.config.mjs b/documentation/next.config.mjs
new file mode 100644
index 0000000..457dcf2
--- /dev/null
+++ b/documentation/next.config.mjs
@@ -0,0 +1,10 @@
+import { createMDX } from 'fumadocs-mdx/next';
+
+const withMDX = createMDX();
+
+/** @type {import('next').NextConfig} */
+const config = {
+ reactStrictMode: true,
+};
+
+export default withMDX(config);
diff --git a/documentation/package.json b/documentation/package.json
new file mode 100644
index 0000000..98c412b
--- /dev/null
+++ b/documentation/package.json
@@ -0,0 +1,34 @@
+{
+ "name": "@memegoat/documentation",
+ "version": "0.0.1",
+ "private": true,
+ "scripts": {
+ "build": "next build",
+ "dev": "next dev",
+ "start": "next start",
+ "types:check": "fumadocs-mdx && next typegen && tsc --noEmit",
+ "postinstall": "fumadocs-mdx",
+ "lint": "biome check",
+ "format": "biome format --write"
+ },
+ "dependencies": {
+ "fumadocs-core": "16.4.3",
+ "fumadocs-mdx": "14.2.4",
+ "fumadocs-ui": "16.4.3",
+ "lucide-react": "^0.562.0",
+ "next": "16.1.1",
+ "react": "^19.2.3",
+ "react-dom": "^19.2.3"
+ },
+ "devDependencies": {
+ "@tailwindcss/postcss": "^4.1.18",
+ "@types/mdx": "^2.0.13",
+ "@types/node": "^24.10.2",
+ "@types/react": "^19.2.7",
+ "@types/react-dom": "^19.2.3",
+ "postcss": "^8.5.6",
+ "tailwindcss": "^4.1.18",
+ "typescript": "^5.9.3",
+ "@biomejs/biome": "^2.3.10"
+ }
+}
\ No newline at end of file
diff --git a/documentation/postcss.config.mjs b/documentation/postcss.config.mjs
new file mode 100644
index 0000000..a34a3d5
--- /dev/null
+++ b/documentation/postcss.config.mjs
@@ -0,0 +1,5 @@
+export default {
+ plugins: {
+ '@tailwindcss/postcss': {},
+ },
+};
diff --git a/documentation/source.config.ts b/documentation/source.config.ts
new file mode 100644
index 0000000..63cedfa
--- /dev/null
+++ b/documentation/source.config.ts
@@ -0,0 +1,22 @@
+import { defineConfig, defineDocs, frontmatterSchema, metaSchema } from 'fumadocs-mdx/config';
+
+// You can customise Zod schemas for frontmatter and `meta.json` here
+// see https://fumadocs.dev/docs/mdx/collections
+export const docs = defineDocs({
+ dir: 'content/docs',
+ docs: {
+ schema: frontmatterSchema,
+ postprocess: {
+ includeProcessedMarkdown: true,
+ },
+ },
+ meta: {
+ schema: metaSchema,
+ },
+});
+
+export default defineConfig({
+ mdxOptions: {
+ // MDX options
+ },
+});
diff --git a/documentation/src/app/(home)/layout.tsx b/documentation/src/app/(home)/layout.tsx
new file mode 100644
index 0000000..77379fa
--- /dev/null
+++ b/documentation/src/app/(home)/layout.tsx
@@ -0,0 +1,6 @@
+import { HomeLayout } from 'fumadocs-ui/layouts/home';
+import { baseOptions } from '@/lib/layout.shared';
+
+export default function Layout({ children }: LayoutProps<'/'>) {
+ return {children};
+}
diff --git a/documentation/src/app/(home)/page.tsx b/documentation/src/app/(home)/page.tsx
new file mode 100644
index 0000000..c936084
--- /dev/null
+++ b/documentation/src/app/(home)/page.tsx
@@ -0,0 +1,16 @@
+import Link from 'next/link';
+
+export default function HomePage() {
+ return (
+
+
Hello World
+
+ You can open{' '}
+
+ /docs
+ {' '}
+ and see the documentation.
+
+
+ );
+}
diff --git a/documentation/src/app/api/search/route.ts b/documentation/src/app/api/search/route.ts
new file mode 100644
index 0000000..7ba7e82
--- /dev/null
+++ b/documentation/src/app/api/search/route.ts
@@ -0,0 +1,7 @@
+import { source } from '@/lib/source';
+import { createFromSource } from 'fumadocs-core/search/server';
+
+export const { GET } = createFromSource(source, {
+ // https://docs.orama.com/docs/orama-js/supported-languages
+ language: 'english',
+});
diff --git a/documentation/src/app/docs/[[...slug]]/page.tsx b/documentation/src/app/docs/[[...slug]]/page.tsx
new file mode 100644
index 0000000..3d4190c
--- /dev/null
+++ b/documentation/src/app/docs/[[...slug]]/page.tsx
@@ -0,0 +1,47 @@
+import { getPageImage, source } from '@/lib/source';
+import { DocsBody, DocsDescription, DocsPage, DocsTitle } from 'fumadocs-ui/layouts/docs/page';
+import { notFound } from 'next/navigation';
+import { getMDXComponents } from '@/mdx-components';
+import type { Metadata } from 'next';
+import { createRelativeLink } from 'fumadocs-ui/mdx';
+
+export default async function Page(props: PageProps<'/docs/[[...slug]]'>) {
+ const params = await props.params;
+ const page = source.getPage(params.slug);
+ if (!page) notFound();
+
+ const MDX = page.data.body;
+
+ return (
+
+ {page.data.title}
+ {page.data.description}
+
+
+
+
+ );
+}
+
+export async function generateStaticParams() {
+ return source.generateParams();
+}
+
+export async function generateMetadata(props: PageProps<'/docs/[[...slug]]'>): Promise {
+ const params = await props.params;
+ const page = source.getPage(params.slug);
+ if (!page) notFound();
+
+ return {
+ title: page.data.title,
+ description: page.data.description,
+ openGraph: {
+ images: getPageImage(page).url,
+ },
+ };
+}
diff --git a/documentation/src/app/docs/layout.tsx b/documentation/src/app/docs/layout.tsx
new file mode 100644
index 0000000..a373143
--- /dev/null
+++ b/documentation/src/app/docs/layout.tsx
@@ -0,0 +1,11 @@
+import { source } from '@/lib/source';
+import { DocsLayout } from 'fumadocs-ui/layouts/docs';
+import { baseOptions } from '@/lib/layout.shared';
+
+export default function Layout({ children }: LayoutProps<'/docs'>) {
+ return (
+
+ {children}
+
+ );
+}
diff --git a/documentation/src/app/global.css b/documentation/src/app/global.css
new file mode 100644
index 0000000..50b3bc2
--- /dev/null
+++ b/documentation/src/app/global.css
@@ -0,0 +1,3 @@
+@import 'tailwindcss';
+@import 'fumadocs-ui/css/neutral.css';
+@import 'fumadocs-ui/css/preset.css';
diff --git a/documentation/src/app/layout.tsx b/documentation/src/app/layout.tsx
new file mode 100644
index 0000000..22fdca3
--- /dev/null
+++ b/documentation/src/app/layout.tsx
@@ -0,0 +1,17 @@
+import { RootProvider } from 'fumadocs-ui/provider/next';
+import './global.css';
+import { Inter } from 'next/font/google';
+
+const inter = Inter({
+ subsets: ['latin'],
+});
+
+export default function Layout({ children }: LayoutProps<'/'>) {
+ return (
+
+
+ {children}
+
+
+ );
+}
diff --git a/documentation/src/app/llms-full.txt/route.ts b/documentation/src/app/llms-full.txt/route.ts
new file mode 100644
index 0000000..d494d2c
--- /dev/null
+++ b/documentation/src/app/llms-full.txt/route.ts
@@ -0,0 +1,10 @@
+import { getLLMText, source } from '@/lib/source';
+
+export const revalidate = false;
+
+export async function GET() {
+ const scan = source.getPages().map(getLLMText);
+ const scanned = await Promise.all(scan);
+
+ return new Response(scanned.join('\n\n'));
+}
diff --git a/documentation/src/app/og/docs/[...slug]/route.tsx b/documentation/src/app/og/docs/[...slug]/route.tsx
new file mode 100644
index 0000000..2d741be
--- /dev/null
+++ b/documentation/src/app/og/docs/[...slug]/route.tsx
@@ -0,0 +1,27 @@
+import { getPageImage, source } from '@/lib/source';
+import { notFound } from 'next/navigation';
+import { ImageResponse } from 'next/og';
+import { generate as DefaultImage } from 'fumadocs-ui/og';
+
+export const revalidate = false;
+
+export async function GET(_req: Request, { params }: RouteContext<'/og/docs/[...slug]'>) {
+ const { slug } = await params;
+ const page = source.getPage(slug.slice(0, -1));
+ if (!page) notFound();
+
+ return new ImageResponse(
+ ,
+ {
+ width: 1200,
+ height: 630,
+ },
+ );
+}
+
+export function generateStaticParams() {
+ return source.getPages().map((page) => ({
+ lang: page.locale,
+ slug: getPageImage(page).segments,
+ }));
+}
diff --git a/documentation/src/lib/layout.shared.tsx b/documentation/src/lib/layout.shared.tsx
new file mode 100644
index 0000000..7e961b6
--- /dev/null
+++ b/documentation/src/lib/layout.shared.tsx
@@ -0,0 +1,9 @@
+import type { BaseLayoutProps } from 'fumadocs-ui/layouts/shared';
+
+export function baseOptions(): BaseLayoutProps {
+ return {
+ nav: {
+ title: 'My App',
+ },
+ };
+}
diff --git a/documentation/src/lib/source.ts b/documentation/src/lib/source.ts
new file mode 100644
index 0000000..2b2d52f
--- /dev/null
+++ b/documentation/src/lib/source.ts
@@ -0,0 +1,27 @@
+import { docs } from 'fumadocs-mdx:collections/server';
+import { type InferPageType, loader } from 'fumadocs-core/source';
+import { lucideIconsPlugin } from 'fumadocs-core/source/lucide-icons';
+
+// See https://fumadocs.dev/docs/headless/source-api for more info
+export const source = loader({
+ baseUrl: '/docs',
+ source: docs.toFumadocsSource(),
+ plugins: [lucideIconsPlugin()],
+});
+
+export function getPageImage(page: InferPageType) {
+ const segments = [...page.slugs, 'image.png'];
+
+ return {
+ segments,
+ url: `/og/docs/${segments.join('/')}`,
+ };
+}
+
+export async function getLLMText(page: InferPageType) {
+ const processed = await page.data.getText('processed');
+
+ return `# ${page.data.title}
+
+${processed}`;
+}
diff --git a/documentation/src/mdx-components.tsx b/documentation/src/mdx-components.tsx
new file mode 100644
index 0000000..20beb4c
--- /dev/null
+++ b/documentation/src/mdx-components.tsx
@@ -0,0 +1,9 @@
+import defaultMdxComponents from 'fumadocs-ui/mdx';
+import type { MDXComponents } from 'mdx/types';
+
+export function getMDXComponents(components?: MDXComponents): MDXComponents {
+ return {
+ ...defaultMdxComponents,
+ ...components,
+ };
+}
diff --git a/documentation/tsconfig.json b/documentation/tsconfig.json
new file mode 100644
index 0000000..77775fb
--- /dev/null
+++ b/documentation/tsconfig.json
@@ -0,0 +1,46 @@
+{
+ "compilerOptions": {
+ "baseUrl": ".",
+ "target": "ESNext",
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "react-jsx",
+ "incremental": true,
+ "paths": {
+ "@/*": [
+ "./src/*"
+ ],
+ "fumadocs-mdx:collections/*": [
+ ".source/*"
+ ]
+ },
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ]
+ },
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx",
+ ".next/types/**/*.ts",
+ ".next/dev/types/**/*.ts"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
\ No newline at end of file