Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/ai/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export const metadata = getMetadata({
title: "DocumentDB for AI - Vector Search, RAG, and Embeddings",
description:
"Build AI applications with DocumentDB: a Mongo API-compatible document model, native vector search, PostgreSQL reliability, and self-hosted deployment.",
path: "/ai/",
extraKeywords: [
"AI database",
"vector search",
Expand Down
2 changes: 1 addition & 1 deletion app/components/Grid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export default function Grid({ items }: {
<h4 className="text-blue-300 font-mono font-medium group-hover:text-blue-200">
{page.name}
</h4>
<p className="text-xs text-gray-400 font-italic">
<p className="text-xs text-gray-400 italic">
{page.description}
</p>
</div>
Expand Down
27 changes: 15 additions & 12 deletions app/components/Markdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -244,18 +244,21 @@ function getMarkdownComponents() {
);
},

// Links
a: ({ children, href, ...props }: any) => (
<a
href={href}
className="text-blue-400 hover:text-blue-300 transition-colors"
target="_blank"
rel="noopener noreferrer"
{...props}
>
{children}
</a>
),
// Links: only external links open in a new tab; internal links (/docs/...,
// /samples, #anchors) navigate in place
a: ({ children, href, ...props }: any) => {
const isExternal = /^https?:\/\//i.test(href ?? '');
return (
<a
href={href}
className="text-blue-400 hover:text-blue-300 transition-colors"
{...(isExternal ? { target: '_blank', rel: 'noopener noreferrer' } : {})}
{...props}
>
{children}
</a>
);
},

// Strong text
strong: ({ children, ...props }: any) => (
Expand Down
3 changes: 2 additions & 1 deletion app/components/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { useState } from "react";
import Image from "next/image";
import Link from "next/link";
import { documentdbDiscordUrl } from "../services/externalLinks";
import { withBasePath } from "../services/sitePath";

type NavItem = {
Expand All @@ -24,7 +25,7 @@ const navItems: NavItem[] = [
},
{
label: "Discord",
href: "https://discord.gg/vH7bYu524D",
href: documentdbDiscordUrl,
kind: "anchor",
newTab: true,
icon: "discord",
Expand Down
96 changes: 60 additions & 36 deletions app/docs/[section]/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Link from "next/link";
import { notFound, redirect } from 'next/navigation';
import { capitalCase } from 'change-case';
import { getAllArticlePaths, getArticleByPath } from "../../../services/articleService";
import { getMetadata } from "../../../services/metadataService";
import ComingSoon from "../../../components/ComingSoon";
import CommandSnippet from "../../../components/CommandSnippet";
import Markdown from "../../../components/Markdown";
Expand Down Expand Up @@ -48,10 +49,12 @@ export async function generateMetadata({ params }: PageProps) {
const selectedNavItem = navigation.find((item) => item.link.includes(file));
const pageTitle = frontmatter.title || selectedNavItem?.title || section;

return {
return getMetadata({
title: `${pageTitle} - DocumentDB Documentation`,
description: frontmatter.description || undefined,
};
description: frontmatter.description || '',
path: slug.length > 0 ? `/docs/${section}/${slug.join('/')}/` : `/docs/${section}/`,
type: 'article',
});
}

export default async function ArticlePage({ params }: PageProps) {
Expand Down Expand Up @@ -80,6 +83,34 @@ export default async function ArticlePage({ params }: PageProps) {
// Use title from frontmatter if available, otherwise fall back to navigation title or section name
const pageTitle = frontmatter.title || selectedNavItem?.title || section;
const showInstallPrimer = section === "getting-started" && file === "index";
const sectionTitle = capitalCase(section)
.replace(/documentdb/i, 'DocumentDB')
.replace(/api/i, 'API');

// Rendered once, shown in the desktop sidebar and the mobile disclosure
const navigationLinks = navigation.map((item) => {
// Better matching logic for active state
// For index files, match both /section and /section/index
// For other files, match the specific file name
const itemPath = item.link.replace('/docs/', '');
const currentPath = file === 'index' ? section : `${section}/${file}`;
const isActive = itemPath === currentPath ||
(file === 'index' && itemPath === `${section}/index`) ||
(item.link.includes(file) && file !== 'index');

return (
<Link
key={item.link}
href={item.link}
className={`block w-full text-left px-4 py-3 rounded-lg text-sm transition-all duration-200 ${isActive
? "bg-blue-500/20 text-blue-300 border border-blue-500/30"
: "text-gray-300 hover:text-white hover:bg-neutral-700/50"
}`}
>
{item.title}
</Link>
);
});

return (
<div className="min-h-screen bg-neutral-900 relative overflow-hidden">
Expand All @@ -94,8 +125,8 @@ export default async function ArticlePage({ params }: PageProps) {
</div>

<div className="relative flex min-h-screen">
{/* Left Sidebar */}
<div className="w-80 bg-neutral-800/50 backdrop-blur-sm border-r border-neutral-700/50 flex flex-col">
{/* Left Sidebar (desktop only; mobile gets the disclosure below) */}
<div className="hidden w-80 bg-neutral-800/50 backdrop-blur-sm border-r border-neutral-700/50 md:flex flex-col">
{/* Header */}
<div className="p-6 border-b border-neutral-700/50">
<Link
Expand All @@ -117,48 +148,41 @@ export default async function ArticlePage({ params }: PageProps) {
</svg>
Back to Documentation
</Link>
<h1 className="text-2xl font-bold text-white">
{
capitalCase(section)
.replace(/documentdb/i, 'DocumentDB')
.replace(/api/i, 'API')
}
</h1>
{/* Not a heading: the article's h1 comes from the markdown content */}
<p className="text-2xl font-bold text-white">
{sectionTitle}
</p>
</div>

{/* Menu Items */}
<div className="flex-1 p-4 overflow-y-auto">
<nav className="space-y-1">
{navigation.map((item) => {
// Better matching logic for active state
// For index files, match both /section and /section/index
// For other files, match the specific file name
const itemPath = item.link.replace('/docs/', '');
const currentPath = file === 'index' ? section : `${section}/${file}`;
const isActive = itemPath === currentPath ||
(file === 'index' && itemPath === `${section}/index`) ||
(item.link.includes(file) && file !== 'index');

return (
<Link
key={item.link}
href={item.link}
className={`block w-full text-left px-4 py-3 rounded-lg text-sm transition-all duration-200 ${isActive
? "bg-blue-500/20 text-blue-300 border border-blue-500/30"
: "text-gray-300 hover:text-white hover:bg-neutral-700/50"
}`}
>
{item.title}
</Link>
);
})}
{navigationLinks}
</nav>
</div>
</div>

{/* Main Content */}
<div className="flex-1 p-8 overflow-y-auto">
<div className="flex-1 p-4 sm:p-8 overflow-y-auto">
<div className="max-w-4xl">
{/* Mobile section navigation */}
<details className="mb-6 rounded-lg border border-neutral-700/50 bg-neutral-800/50 md:hidden">
<summary className="cursor-pointer px-4 py-3 text-sm font-semibold text-gray-200">
{sectionTitle} navigation
</summary>
<div className="border-t border-neutral-700/50 p-3">
<Link
href="/docs"
className="block px-4 py-2 text-sm text-blue-400 hover:text-blue-300 transition-colors"
>
← Back to Documentation
</Link>
<nav className="space-y-1">
{navigationLinks}
</nav>
</div>
</details>

{/* Coming Soon Component for coming-soon layout */}
{frontmatter.layout === 'coming-soon' && <ComingSoon />}

Expand Down
10 changes: 10 additions & 0 deletions app/docs/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
import Link from "next/link";
import { getArticleContent } from "../services/articleService";
import { getMetadata } from "../services/metadataService";

export function generateMetadata() {
const articleContent = getArticleContent();
return getMetadata({
title: `${articleContent.landing.title} - DocumentDB`,
description: articleContent.landing.description,
path: '/docs/',
});
}

export default function Docs() {
const articleContent = getArticleContent();
Expand Down
2 changes: 2 additions & 0 deletions app/docs/reference/[type]/[category]/[name]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ export async function generateMetadata({ params }: { params: Promise<{ type: str
return getMetadata({
title: `${data.frontmatter.title || name} - DocumentDB MQL Reference`,
description: data.frontmatter.description || '',
path: `/docs/reference/${type}/${category}/${name}/`,
type: 'article',
extraKeywords: ['reference', type, category, name]
});
}
Expand Down
7 changes: 4 additions & 3 deletions app/docs/reference/[type]/[category]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ export async function generateMetadata({ params }: { params: Promise<{ type: str
const title = `${capitalCase(category)} ${capitalCase(pluralize(type))}`;
const description = getCategoryDescription(type, category);
return getMetadata({
title: `${title} - DocumentDB MQL Reference`,
title: `${title} - DocumentDB MQL Reference`,
description: await sanitizeMarkdown(description),
path: `/docs/reference/${type}/${category}/`,
extraKeywords: ['reference', type, category]
});
}
Expand All @@ -38,9 +39,9 @@ export default async function CommandReferencePage({ params }: { params: Promise
<article>
<Breadcrumb type={type} category={category} />
<div className="mb-8">
<h2 className="text-4xl font-bold text-white mb-4 capitalize">
<h1 className="text-4xl font-bold text-white mb-4 capitalize">
MongoDB Query Language (MQL) {capitalCase(category)} {capitalCase(pluralize(type))}
</h2>
</h1>
<div className="w-24 h-1 bg-gradient-to-r from-blue-500 via-purple-500 to-green-500 rounded-full mb-6"></div>
{description && (
<div className="text-gray-400 text-lg mb-6">
Expand Down
7 changes: 4 additions & 3 deletions app/docs/reference/[type]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ export async function generateMetadata({ params }: { params: Promise<{ type: str
const title = capitalCase(pluralize(type));
const description = getTypeDescription(type);
return getMetadata({
title: `${title} - DocumentDB MQL Reference`,
title: `${title} - DocumentDB MQL Reference`,
description: await sanitizeMarkdown(description),
path: `/docs/reference/${type}/`,
extraKeywords: ['reference', type]
});
}
Expand All @@ -37,9 +38,9 @@ export default async function CommandReferencePage({ params }: { params: Promise
<article>
<Breadcrumb type={type} />
<div className="mb-8">
<h2 className="text-4xl font-bold text-white mb-4 capitalize">
<h1 className="text-4xl font-bold text-white mb-4 capitalize">
MongoDB Query Language (MQL) {capitalCase(pluralize(type))}
</h2>
</h1>
<div className="w-24 h-1 bg-gradient-to-r from-blue-500 via-purple-500 to-green-500 rounded-full mb-6"></div>
{description && (
<div className="text-gray-400 text-lg mb-6">
Expand Down
14 changes: 12 additions & 2 deletions app/docs/reference/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ export default function ReferenceLayout({
></div>
</div>
<div className="relative flex h-screen">
<div className="w-80 bg-neutral-800/50 backdrop-blur-sm border-r border-neutral-700/50 flex flex-col h-full">
{/* Sidebar (desktop only; mobile gets the disclosure below) */}
<div className="hidden w-80 bg-neutral-800/50 backdrop-blur-sm border-r border-neutral-700/50 md:flex flex-col h-full">
<div className="p-6 border-b border-neutral-700/50 flex-shrink-0">
<Link href="/docs" className="text-blue-400 hover:text-blue-300 text-sm mb-4 flex items-center transition-colors">
<svg
Expand All @@ -51,8 +52,17 @@ export default function ReferenceLayout({
</div>
<Index groupedReferences={groupedReferences} />
</div>
<article className="flex-1 p-8 overflow-y-auto h-full">
<article className="flex-1 p-4 sm:p-8 overflow-y-auto h-full">
<div className="max-w-4xl">
{/* Mobile reference navigation */}
<details className="mb-6 rounded-lg border border-neutral-700/50 bg-neutral-800/50 md:hidden">
<summary className="cursor-pointer px-4 py-3 text-sm font-semibold text-gray-200">
MQL reference navigation
</summary>
<div className="max-h-[60vh] overflow-y-auto border-t border-neutral-700/50">
<Index groupedReferences={groupedReferences} />
</div>
</details>
{children}
</div>
</article>
Expand Down
5 changes: 3 additions & 2 deletions app/docs/reference/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export async function generateMetadata() {
return getMetadata({
title: 'DocumentDB MQL Reference',
description: await sanitizeMarkdown(description),
path: '/docs/reference/',
extraKeywords: ['reference']
});
}
Expand All @@ -23,9 +24,9 @@ export default function Home() {
<article>
<Breadcrumb />
<div className="mb-8">
<h2 className="text-4xl font-bold text-white mb-4">
<h1 className="text-4xl font-bold text-white mb-4">
MongoDB Query Language (MQL)
</h2>
</h1>
<div className="w-24 h-1 bg-gradient-to-r from-blue-500 via-purple-500 to-green-500 rounded-full mb-6"></div>
{description && (
<div className="text-gray-400 text-lg mb-6">
Expand Down
1 change: 1 addition & 0 deletions app/kubernetes-operator/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ export const metadata = getMetadata({
title: "DocumentDB Kubernetes Operator",
description:
"Run DocumentDB on Kubernetes with a PostgreSQL foundation, replication, HA, backups, TLS, and hybrid or multi-cloud topologies.",
path: "/kubernetes-operator/",
extraKeywords: [
"Kubernetes",
"operator",
Expand Down
Loading