diff --git a/docs/src/app/(home)/layout.tsx b/docs/src/app/(home)/layout.tsx
index d23d116cb..d88cfe761 100644
--- a/docs/src/app/(home)/layout.tsx
+++ b/docs/src/app/(home)/layout.tsx
@@ -1,9 +1,11 @@
+import { getGitHubStars } from '@/lib/github-stars';
import { SiteNav } from './site-nav';
-export default function Layout({ children }: LayoutProps<'/'>) {
+export default async function Layout({ children }: LayoutProps<'/'>) {
+ const stars = await getGitHubStars();
return (
<>
-
+
{children}
>
);
diff --git a/docs/src/app/(home)/site-nav.tsx b/docs/src/app/(home)/site-nav.tsx
index 8c8230aa2..57cc809c7 100644
--- a/docs/src/app/(home)/site-nav.tsx
+++ b/docs/src/app/(home)/site-nav.tsx
@@ -1,6 +1,6 @@
'use client';
-import { Menu, X } from 'lucide-react';
+import { Menu, Star, X } from 'lucide-react';
import Link from 'next/link';
import type { FC, SVGProps } from 'react';
import { useEffect, useRef, useState } from 'react';
@@ -17,16 +17,12 @@ type NavLink = {
external: boolean;
icon?: FC>;
iconOnly?: boolean;
+ showStars?: boolean;
};
-const navLinks: NavLink[] = [
- { href: '/docs', label: 'Docs', external: false },
- {
- href: 'https://github.com/inkeep/open-knowledge',
- label: 'GitHub',
- external: true,
- icon: GitHubIcon,
- },
+const docsLink: NavLink = { href: '/docs', label: 'Docs', external: false };
+
+const socialLinks: NavLink[] = [
{
href: 'https://x.com/OpenKnowledgeAI',
label: 'X',
@@ -43,9 +39,124 @@ const navLinks: NavLink[] = [
},
];
+const githubLink: NavLink = {
+ href: 'https://github.com/inkeep/open-knowledge',
+ label: 'GitHub',
+ external: true,
+ icon: GitHubIcon,
+ showStars: true,
+};
+
+const mobileLinks: NavLink[] = [docsLink, ...socialLinks, githubLink];
+
const FOCUSABLE_SELECTOR = 'a[href], button:not([disabled]), [tabindex]:not([tabindex="-1"])';
-export function SiteNav() {
+const starFormatter = new Intl.NumberFormat('en-US', {
+ notation: 'compact',
+ maximumFractionDigits: 1,
+});
+
+const fullStarFormatter = new Intl.NumberFormat('en-US');
+
+function NavLinkContent({ link }: { link: NavLink }) {
+ const Icon = link.icon;
+ return (
+ <>
+ {Icon ? : null}
+ {link.iconOnly ? null : link.label}
+ >
+ );
+}
+
+function NavItem({ link, className }: { link: NavLink; className: string }) {
+ const ariaLabel = link.iconOnly ? link.label : undefined;
+ return link.external ? (
+
+
+
+ ) : (
+
+
+
+ );
+}
+
+function StarCount({ stars }: { stars: number }) {
+ return (
+ <>
+
+ {starFormatter.format(stars)}
+ >
+ );
+}
+
+function GitHubStarButton({
+ link,
+ stars,
+ variant,
+}: {
+ link: NavLink;
+ stars: number | null;
+ variant: 'pill' | 'row';
+}) {
+ const Icon = link.icon;
+ const title = stars != null ? `${fullStarFormatter.format(stars)} GitHub stars` : undefined;
+
+ if (variant === 'row') {
+ return (
+
+
+ {Icon ? : null}
+ {link.label}
+
+ {stars != null ? (
+
+
+
+ ) : null}
+
+ );
+ }
+
+ return (
+
+
+ {Icon ? : null}
+ {link.label}
+
+ {stars != null ? (
+
+
+
+ ) : null}
+
+ );
+}
+
+export function SiteNav({ stars }: { stars: number | null }) {
const [open, setOpen] = useState(false);
const triggerRef = useRef(null);
const menuRef = useRef(null);
@@ -92,41 +203,34 @@ export function SiteNav() {
return (
-
-
-
-
-