feat: docs
CI / 🔍 Lint & Type Check (push) Successful in 2m11s
CI / 🐳 Build & Push Image (push) Successful in 1m16s

This commit is contained in:
2026-07-17 16:15:54 +02:00
parent 0c2f42b4a3
commit 1542a991b9
38 changed files with 6366 additions and 19 deletions
+6
View File
@@ -0,0 +1,6 @@
import { source } from "@/lib/source";
import { createFromSource } from "fumadocs-core/search/server";
export const { GET } = createFromSource(source, {
language: "french",
});
+58
View File
@@ -0,0 +1,58 @@
import { source } from "@/lib/source";
import { getMDXComponents } from "@/mdx-components";
import {
DocsBody,
DocsDescription,
DocsPage,
DocsTitle,
} from "fumadocs-ui/layouts/docs/page";
import { createRelativeLink } from "fumadocs-ui/mdx";
import type { Metadata } from "next";
import { notFound } from "next/navigation";
export default async function DocumentationPage(
props: PageProps<"/docs/[[...slug]]">,
) {
const { slug } = await props.params;
const page = source.getPage(slug);
if (!page) {
notFound();
}
const MDXContent = page.data.body;
return (
<DocsPage toc={page.data.toc} full={page.data.full}>
<DocsTitle>{page.data.title}</DocsTitle>
<DocsDescription>{page.data.description}</DocsDescription>
<DocsBody>
<MDXContent
components={getMDXComponents({
a: createRelativeLink(source, page),
})}
/>
</DocsBody>
</DocsPage>
);
}
export function generateStaticParams() {
return source.generateParams();
}
export async function generateMetadata(
props: PageProps<"/docs/[[...slug]]">,
): Promise<Metadata> {
const { slug } = await props.params;
const page = source.getPage(slug);
if (!page) {
notFound();
}
return {
title: page.data.title,
description: page.data.description,
};
}
+29
View File
@@ -0,0 +1,29 @@
import { baseOptions } from "@/lib/layout.shared";
import { source } from "@/lib/source";
import { DocsLayout } from "fumadocs-ui/layouts/docs";
import type { Metadata } from "next";
export const metadata: Metadata = {
title: {
default: "Cours Docker | Le serveur de Leon",
template: "%s | Le serveur de Leon",
},
description: "Support de cours Docker, des fondamentaux au déploiement.",
};
export default function DocsRootLayout({ children }: LayoutProps<"/docs">) {
return (
<DocsLayout
{...baseOptions()}
tree={source.getPageTree()}
tabs={false}
sidebar={{
collapsible: true,
defaultOpenLevel: 1,
}}
containerProps={{ className: "server-docs" }}
>
{children}
</DocsLayout>
);
}
+63
View File
@@ -1,4 +1,6 @@
@import "tailwindcss";
@import "fumadocs-ui/css/neutral.css";
@import "fumadocs-ui/css/preset.css";
:root {
--background: #090a0f;
@@ -18,6 +20,26 @@
--shadow-hard: 6px 6px 0 rgb(0 0 0 / 55%);
}
.dark {
--color-fd-background: #090a0f;
--color-fd-foreground: #f8fbff;
--color-fd-muted: #15182a;
--color-fd-muted-foreground: #9eabc1;
--color-fd-popover: #111426;
--color-fd-popover-foreground: #f8fbff;
--color-fd-card: #141832;
--color-fd-card-foreground: #f8fbff;
--color-fd-border: rgb(168 245 255 / 16%);
--color-fd-primary: #a8f5ff;
--color-fd-primary-foreground: #06111a;
--color-fd-secondary: #1b2039;
--color-fd-secondary-foreground: #e8f8ff;
--color-fd-accent: rgb(0 231 255 / 12%);
--color-fd-accent-foreground: #c9f9ff;
--color-fd-ring: #00e7ff;
--color-fd-overlay: rgb(0 0 0 / 62%);
}
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
@@ -59,6 +81,47 @@ svg {
color: #06111a;
}
.server-docs {
min-height: 100vh;
background:
radial-gradient(circle at 82% 10%, rgb(139 77 255 / 11%), transparent 28rem),
radial-gradient(circle at 12% 85%, rgb(0 231 255 / 8%), transparent 30rem),
var(--color-fd-background);
}
.server-docs #nd-sidebar {
background: rgb(9 10 15 / 94%);
backdrop-filter: blur(18px);
}
.server-docs [data-toc-popover] {
backdrop-filter: blur(18px);
}
.docs-brand {
display: inline-flex;
align-items: center;
gap: 10px;
color: #d8fbff;
font-family: var(--font-fredoka), var(--font-geist-sans), sans-serif;
font-weight: 700;
letter-spacing: -0.02em;
}
.docs-brand-mark {
display: grid;
width: 30px;
height: 30px;
place-items: center;
border: 1px solid rgb(168 245 255 / 70%);
border-radius: 7px;
background: rgb(0 231 255 / 8%);
box-shadow: 0 0 18px rgb(0 231 255 / 22%);
color: #a8f5ff;
font-size: 1.05rem;
line-height: 1;
}
*:focus-visible {
outline: 3px solid var(--gold);
outline-offset: 4px;
+35 -2
View File
@@ -1,5 +1,6 @@
import type { Metadata } from "next";
import { Fredoka, Geist, Geist_Mono, Press_Start_2P, VT323 } from "next/font/google";
import { RootProvider } from "fumadocs-ui/provider/next";
import "./globals.css";
const geistSans = Geist({
@@ -29,6 +30,30 @@ const vt323 = VT323({
weight: "400",
});
const frenchTranslations = {
"Back to Home(404 page)": "Retour à l'accueil",
"Close Search(search dialog)(aria-label)": "Fermer la recherche",
"Close Sidebar(sidebar)(aria-label)": "Fermer la navigation",
"Collapse Sidebar(sidebar)(aria-label)": "Réduire la navigation",
"Copied Text(code block)(aria-label)": "Texte copié",
"Copy Anchor Link(heading anchor)(aria-label)": "Copier le lien",
"Copy Text(code block)(aria-label)": "Copier le texte",
"Next Page(pagination)": "Page suivante",
"No Headings(table of contents)": "Aucun titre",
"No results found(search dialog)": "Aucun résultat trouvé",
"On this page(table of contents)": "Sur cette page",
"Open Search(search trigger)(aria-label)": "Ouvrir la recherche",
"Open Sidebar(sidebar)(aria-label)": "Ouvrir la navigation",
"Page Not Found(404 page)": "Page introuvable",
"Previous Page(pagination)": "Page précédente",
"Search(search dialog)": "Rechercher dans la documentation",
"Search(search trigger)": "Rechercher",
"Table of Contents(inline table of contents)": "Sommaire",
"The page you are looking for might have been removed, had its name changed, or is temporarily unavailable.(404 page)":
"La page demandée n'existe pas ou a été déplacée.",
"Toggle Menu(mobile menu)(aria-label)": "Ouvrir le menu",
};
export const metadata: Metadata = {
title: "Le serveur de Leon",
description: "Streaming, Minecraft et services privés de Leon.",
@@ -56,9 +81,17 @@ export default function RootLayout({
<html
lang="fr"
data-scroll-behavior="smooth"
className={`${geistSans.variable} ${geistMono.variable} ${fredoka.variable} ${pressStart.variable} ${vt323.variable} h-full antialiased`}
suppressHydrationWarning
className={`dark ${geistSans.variable} ${geistMono.variable} ${fredoka.variable} ${pressStart.variable} ${vt323.variable} h-full antialiased`}
>
<body className="min-h-full flex flex-col">{children}</body>
<body className="min-h-full flex flex-col">
<RootProvider
theme={{ enabled: false }}
i18n={{ locale: "fr", translations: frenchTranslations }}
>
{children}
</RootProvider>
</body>
</html>
);
}