mirror of
https://github.com/Dokploy/website
synced 2025-06-26 18:16:01 +00:00
refactor: rename folder v2 and delete old docs
This commit is contained in:
@@ -1,104 +0,0 @@
|
||||
import { getLanguages, getPage } from "@/app/source.config";
|
||||
import { url, baseUrl } from "@/utils/metadata";
|
||||
import { DocsBody, DocsPage } from "fumadocs-ui/page";
|
||||
import type { Metadata } from "next";
|
||||
import { notFound, permanentRedirect } from "next/navigation";
|
||||
|
||||
export default async function Page({
|
||||
params,
|
||||
}: {
|
||||
params: { lang: string; slug?: string[] };
|
||||
}) {
|
||||
const page = getPage(params.slug, params.lang);
|
||||
|
||||
if (page == null) {
|
||||
permanentRedirect("/docs/core/get-started/introduction");
|
||||
}
|
||||
|
||||
const MDX = page.data.exports.default;
|
||||
|
||||
return (
|
||||
<DocsPage toc={page.data.exports.toc}>
|
||||
<DocsBody>
|
||||
<h1>{page.data.title}</h1>
|
||||
<MDX />
|
||||
</DocsBody>
|
||||
</DocsPage>
|
||||
);
|
||||
}
|
||||
|
||||
export async function generateStaticParams() {
|
||||
return getLanguages().flatMap(({ language, pages }) =>
|
||||
pages.map((page) => ({
|
||||
lang: language,
|
||||
slug: page.slugs,
|
||||
})),
|
||||
);
|
||||
}
|
||||
|
||||
export function generateMetadata({
|
||||
params,
|
||||
}: {
|
||||
params: { lang: string; slug?: string[] };
|
||||
}) {
|
||||
const page = getPage(params.slug, params.lang);
|
||||
if (page == null) {
|
||||
permanentRedirect("/docs/core/get-started/introduction");
|
||||
}
|
||||
return {
|
||||
title: page.data.title,
|
||||
|
||||
description: page.data.description,
|
||||
robots: "index,follow",
|
||||
alternates: {
|
||||
canonical: new URL(`${baseUrl}${page.url}`).toString(),
|
||||
languages: {
|
||||
zh: `${baseUrl}/cn${page.url.replace("/cn", "")}`,
|
||||
en: `${baseUrl}/en${page.url.replace("/en", "")}`,
|
||||
},
|
||||
},
|
||||
openGraph: {
|
||||
title: page.data.title,
|
||||
description: page.data.description,
|
||||
url: new URL(`${baseUrl}`).toString(),
|
||||
images: [
|
||||
{
|
||||
url: new URL(
|
||||
`${baseUrl}/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flogo.7cfd81d9.png&w=828&q=75`,
|
||||
).toString(),
|
||||
width: 1200,
|
||||
height: 630,
|
||||
alt: page.data.title,
|
||||
},
|
||||
],
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
creator: "@getdokploy",
|
||||
title: page.data.title,
|
||||
description: page.data.description,
|
||||
images: [
|
||||
{
|
||||
url: new URL(
|
||||
`${baseUrl}/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Flogo.7cfd81d9.png&w=828&q=75`,
|
||||
).toString(),
|
||||
width: 1200,
|
||||
height: 630,
|
||||
alt: page.data.title,
|
||||
},
|
||||
],
|
||||
},
|
||||
applicationName: "Dokploy Docs",
|
||||
keywords: [
|
||||
"dokploy",
|
||||
"vps",
|
||||
"open source",
|
||||
"cloud",
|
||||
"self hosting",
|
||||
"free",
|
||||
],
|
||||
icons: {
|
||||
icon: "/icon.svg",
|
||||
},
|
||||
} satisfies Metadata;
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
import { RootToggle } from "fumadocs-ui/components/layout/root-toggle";
|
||||
import { I18nProvider } from "fumadocs-ui/i18n";
|
||||
import { DocsLayout } from "fumadocs-ui/layout";
|
||||
import { RootProvider } from "fumadocs-ui/provider";
|
||||
import { Inter } from "next/font/google";
|
||||
import type { ReactNode } from "react";
|
||||
import { baseOptions } from "../layout.config";
|
||||
import { pageTree } from "../source.config";
|
||||
import "../global.css";
|
||||
import GoogleAnalytics from "@/components/analytics/google";
|
||||
import {
|
||||
LibraryIcon,
|
||||
type LucideIcon,
|
||||
PlugZapIcon,
|
||||
TerminalIcon,
|
||||
} from "lucide-react";
|
||||
import Script from "next/script";
|
||||
const inter = Inter({
|
||||
subsets: ["latin"],
|
||||
});
|
||||
|
||||
interface Mode {
|
||||
param: string;
|
||||
name: string;
|
||||
package: string;
|
||||
description: string;
|
||||
icon: LucideIcon;
|
||||
}
|
||||
|
||||
const modes: Mode[] = [
|
||||
{
|
||||
param: "core/get-started/introduction",
|
||||
name: "Core",
|
||||
package: "Dokploy",
|
||||
description: "The core",
|
||||
icon: LibraryIcon,
|
||||
},
|
||||
{
|
||||
param: "cli",
|
||||
name: "CLI",
|
||||
package: "fumadocs-ui",
|
||||
description: "Interactive CLI",
|
||||
icon: TerminalIcon,
|
||||
},
|
||||
{
|
||||
param: "api",
|
||||
name: "API",
|
||||
package: "fumadocs-mdx",
|
||||
description: "API Documentation",
|
||||
icon: PlugZapIcon,
|
||||
},
|
||||
];
|
||||
|
||||
export default function Layout({
|
||||
params,
|
||||
children,
|
||||
}: {
|
||||
params: { lang: string };
|
||||
children: ReactNode;
|
||||
}) {
|
||||
return (
|
||||
<html
|
||||
lang={params.lang}
|
||||
className={inter.className}
|
||||
suppressHydrationWarning
|
||||
>
|
||||
<Script
|
||||
src="https://umami.dokploy.com/script.js"
|
||||
data-website-id="6ad2aa56-6d38-4f39-97a8-1a8fcdda8d51"
|
||||
/>
|
||||
<GoogleAnalytics />
|
||||
<body>
|
||||
<I18nProvider
|
||||
locale={params.lang}
|
||||
translations={{
|
||||
en: {
|
||||
name: "English",
|
||||
},
|
||||
cn: {
|
||||
name: "中文",
|
||||
toc: "目录",
|
||||
search: "搜索文档",
|
||||
lastUpdate: "最后更新于",
|
||||
searchNoResult: "没有结果",
|
||||
previousPage: "上一页",
|
||||
nextPage: "下一页",
|
||||
chooseLanguage: "选择语言",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<RootProvider>
|
||||
<DocsLayout
|
||||
i18n
|
||||
tree={pageTree[params.lang]}
|
||||
nav={{
|
||||
title: params.lang === "cn" ? "目录" : "Dokploy",
|
||||
url: `/${params.lang}`,
|
||||
transparentMode: "none",
|
||||
}}
|
||||
sidebar={{
|
||||
// defaultOpenLevel: 0,
|
||||
|
||||
banner: (
|
||||
<RootToggle
|
||||
options={modes.map((mode) => {
|
||||
return {
|
||||
url: `/${params.lang}/docs/${mode.param}`,
|
||||
icon: (
|
||||
<mode.icon
|
||||
className="size-9 shrink-0 rounded-md bg-gradient-to-t from-background/80 p-1.5"
|
||||
style={{
|
||||
backgroundColor: `hsl(var(--${mode.param}-color)/.3)`,
|
||||
color: `hsl(var(--${mode.param}-color))`,
|
||||
}}
|
||||
/>
|
||||
),
|
||||
title: mode.name,
|
||||
description: mode.description,
|
||||
};
|
||||
})}
|
||||
/>
|
||||
),
|
||||
}}
|
||||
{...baseOptions}
|
||||
>
|
||||
{children}
|
||||
</DocsLayout>
|
||||
</RootProvider>
|
||||
</I18nProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
@@ -1,18 +1,4 @@
|
||||
import { getPages } from "@/app/source.config";
|
||||
import { createI18nSearchAPI } from "fumadocs-core/search/server";
|
||||
import { source } from "@/lib/source";
|
||||
import { createFromSource } from "fumadocs-core/search/server";
|
||||
|
||||
import { languages } from "@/i18n";
|
||||
|
||||
export const { GET } = createI18nSearchAPI("advanced", {
|
||||
indexes: languages.map((lang) => {
|
||||
return {
|
||||
language: lang,
|
||||
indexes: getPages(lang).map((page) => ({
|
||||
id: page.url,
|
||||
url: page.url,
|
||||
title: page.data.title,
|
||||
structuredData: page.data.exports.structuredData,
|
||||
})),
|
||||
};
|
||||
}),
|
||||
});
|
||||
export const { GET } = createFromSource(source);
|
||||
|
||||
117
apps/docs/app/docs/[[...slug]]/page.tsx
Normal file
117
apps/docs/app/docs/[[...slug]]/page.tsx
Normal file
@@ -0,0 +1,117 @@
|
||||
import { source } from "@/lib/source";
|
||||
import { openapi } from "@/lib/source";
|
||||
import { baseUrl } from "@/utils/metadata";
|
||||
import { ImageZoom } from "fumadocs-ui/components/image-zoom";
|
||||
import defaultMdxComponents from "fumadocs-ui/mdx";
|
||||
import {
|
||||
DocsBody,
|
||||
DocsDescription,
|
||||
DocsPage,
|
||||
DocsTitle,
|
||||
} from "fumadocs-ui/page";
|
||||
import { notFound, permanentRedirect } from "next/navigation";
|
||||
|
||||
export default async function Page(props: {
|
||||
params: Promise<{ slug?: string[] }>;
|
||||
}) {
|
||||
const params = await props.params;
|
||||
const page = source.getPage(params.slug);
|
||||
if (!page) {
|
||||
permanentRedirect("/docs/core");
|
||||
}
|
||||
|
||||
const MDX = page.data.body;
|
||||
|
||||
return (
|
||||
<DocsPage toc={page.data.toc} full={page.data.full}>
|
||||
<DocsTitle>{page.data.title}</DocsTitle>
|
||||
<DocsDescription>{page.data.description}</DocsDescription>
|
||||
<DocsBody>
|
||||
<MDX
|
||||
components={{
|
||||
...defaultMdxComponents,
|
||||
ImageZoom: (props) => <ImageZoom {...(props as any)} />,
|
||||
p: ({ children }) => (
|
||||
<p className="text-[#3E4342] dark:text-muted-foreground">
|
||||
{children}
|
||||
</p>
|
||||
),
|
||||
li: ({ children, id }) => (
|
||||
<li
|
||||
{...{ id }}
|
||||
className="text-[#3E4342] dark:text-muted-foreground"
|
||||
>
|
||||
{children}
|
||||
</li>
|
||||
),
|
||||
APIPage: openapi.APIPage,
|
||||
}}
|
||||
/>
|
||||
</DocsBody>
|
||||
</DocsPage>
|
||||
);
|
||||
}
|
||||
|
||||
export async function generateStaticParams() {
|
||||
return source.generateParams();
|
||||
}
|
||||
|
||||
export async function generateMetadata(props: {
|
||||
params: Promise<{ slug?: string[] }>;
|
||||
}) {
|
||||
const params = await props.params;
|
||||
const page = source.getPage(params.slug);
|
||||
if (!page) notFound();
|
||||
|
||||
return {
|
||||
title: page.data.title,
|
||||
|
||||
description: page.data.description,
|
||||
robots: "index,follow",
|
||||
alternates: {
|
||||
canonical: new URL(`${baseUrl}${page.url}`).toString(),
|
||||
languages: {
|
||||
en: `${baseUrl}/${page.url}`,
|
||||
},
|
||||
},
|
||||
openGraph: {
|
||||
title: page.data.title,
|
||||
description: page.data.description,
|
||||
url: new URL(`${baseUrl}`).toString(),
|
||||
images: [
|
||||
{
|
||||
url: new URL(`${baseUrl}/logo.png`).toString(),
|
||||
width: 1200,
|
||||
height: 630,
|
||||
alt: page.data.title,
|
||||
},
|
||||
],
|
||||
},
|
||||
twitter: {
|
||||
card: "summary_large_image",
|
||||
creator: "@getdokploy",
|
||||
title: page.data.title,
|
||||
description: page.data.description,
|
||||
images: [
|
||||
{
|
||||
url: new URL(`${baseUrl}/logo.png`).toString(),
|
||||
width: 1200,
|
||||
height: 630,
|
||||
alt: page.data.title,
|
||||
},
|
||||
],
|
||||
},
|
||||
applicationName: "Dokploy Docs",
|
||||
keywords: [
|
||||
"dokploy",
|
||||
"vps",
|
||||
"open source",
|
||||
"cloud",
|
||||
"self hosting",
|
||||
"free",
|
||||
],
|
||||
icons: {
|
||||
icon: "/icon.svg",
|
||||
},
|
||||
};
|
||||
}
|
||||
22
apps/docs/app/docs/layout.tsx
Normal file
22
apps/docs/app/docs/layout.tsx
Normal file
@@ -0,0 +1,22 @@
|
||||
import { baseOptions } from "@/app/layout.config";
|
||||
import { source } from "@/lib/source";
|
||||
import { baseUrl, createMetadata } from "@/utils/metadata";
|
||||
import { DocsLayout } from "fumadocs-ui/layouts/docs";
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
export const metadata = createMetadata({
|
||||
title: {
|
||||
template: "%s | Dokploy",
|
||||
default: "Dokploy",
|
||||
},
|
||||
description: "The Open Source Alternative to Vercel, Heroku, and Netlify",
|
||||
metadataBase: new URL(baseUrl),
|
||||
});
|
||||
|
||||
export default function Layout({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<DocsLayout tree={source.pageTree} {...baseOptions}>
|
||||
{children}
|
||||
</DocsLayout>
|
||||
);
|
||||
}
|
||||
@@ -2,26 +2,17 @@
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
.api {
|
||||
--primary: var(--api-color);
|
||||
}
|
||||
|
||||
.core {
|
||||
--primary: var(--core-color);
|
||||
}
|
||||
|
||||
.cli {
|
||||
--primary: var(--cli-color);
|
||||
}
|
||||
|
||||
|
||||
|
||||
:root {
|
||||
--core-color: 250 80% 54%;
|
||||
--cli-color: 0 0% 9%;
|
||||
--api-color: 220deg 91% 54%;
|
||||
--fd-background: 0 0% 0%;
|
||||
--background: 0 0% 100%;
|
||||
--card: 0 0% 97.6%;
|
||||
}
|
||||
|
||||
.dark{
|
||||
--fd-background: 0 0% 100%;
|
||||
--background: 0 0% 0%;
|
||||
--card: 0 0% 6.0%;
|
||||
}
|
||||
|
||||
.dark {
|
||||
--headless-color: 250 100% 80%;
|
||||
--cli-color: 0 0% 100%;
|
||||
--api-color: 217deg 92% 76%;
|
||||
}
|
||||
@@ -1,5 +1,13 @@
|
||||
import type { BaseLayoutProps } from "fumadocs-ui/layout";
|
||||
import type { BaseLayoutProps } from "fumadocs-ui/layouts/shared";
|
||||
import { Github, GlobeIcon, HeartIcon } from "lucide-react";
|
||||
import Link from "next/link";
|
||||
/**
|
||||
* Shared layout configurations
|
||||
*
|
||||
* you can configure layouts individually from:
|
||||
* Home Layout: app/(home)/layout.tsx
|
||||
* Docs Layout: app/docs/layout.tsx
|
||||
*/
|
||||
|
||||
export const Logo = () => {
|
||||
return (
|
||||
@@ -27,14 +35,13 @@ export const Logo = () => {
|
||||
};
|
||||
|
||||
export const baseOptions: BaseLayoutProps = {
|
||||
githubUrl: "https://github.com/dokploy/dokploy",
|
||||
nav: {
|
||||
url: "/get-started/introduction",
|
||||
title: (
|
||||
<>
|
||||
// title: "Dokploy",
|
||||
children: (
|
||||
<Link href="/docs/core" className="flex items-center gap-2">
|
||||
<Logo />
|
||||
<span className="text-foreground">Dokploy</span>
|
||||
</>
|
||||
<span className="text-foreground font-semibold">Dokploy</span>
|
||||
</Link>
|
||||
),
|
||||
},
|
||||
links: [
|
||||
|
||||
21
apps/docs/app/layout.tsx
Normal file
21
apps/docs/app/layout.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import "./global.css";
|
||||
import { RootProvider } from "fumadocs-ui/provider";
|
||||
import { Inter } from "next/font/google";
|
||||
import type { ReactNode } from "react";
|
||||
|
||||
const inter = Inter({
|
||||
subsets: ["latin"],
|
||||
});
|
||||
|
||||
export default async function Layout({
|
||||
children,
|
||||
...rest
|
||||
}: { children: ReactNode }) {
|
||||
return (
|
||||
<html lang="en" className={inter.className} suppressHydrationWarning>
|
||||
<body className="flex flex-col min-h-screen">
|
||||
<RootProvider>{children}</RootProvider>
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
@@ -1,18 +1,19 @@
|
||||
import { source } from "@/lib/source";
|
||||
import { url } from "@/utils/metadata";
|
||||
import type { MetadataRoute } from "next";
|
||||
import { getPages } from "./source.config";
|
||||
|
||||
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
|
||||
return [
|
||||
...getPages().map<MetadataRoute.Sitemap[number]>((page) => {
|
||||
return {
|
||||
url: url(`/en${page.url}`),
|
||||
lastModified: page.data.exports.lastModified
|
||||
? new Date(page.data.exports.lastModified)
|
||||
: undefined,
|
||||
changeFrequency: "weekly",
|
||||
priority: page.url === "/docs/core/get-started/introduction" ? 1 : 0.8,
|
||||
};
|
||||
}),
|
||||
...(await Promise.all(
|
||||
source.getPages().map(async (page) => {
|
||||
const { lastModified } = page.data;
|
||||
return {
|
||||
url: url(page.url),
|
||||
lastModified: lastModified ? new Date(lastModified) : undefined,
|
||||
changeFrequency: "weekly",
|
||||
priority: 0.5,
|
||||
} as MetadataRoute.Sitemap[number];
|
||||
}),
|
||||
)),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
import { map } from "@/.map";
|
||||
import { languages } from "@/i18n";
|
||||
import { loader } from "fumadocs-core/source";
|
||||
import { createMDXSource } from "fumadocs-mdx";
|
||||
|
||||
export const { getPage, getPages, pageTree, getLanguages } = loader({
|
||||
baseUrl: "/",
|
||||
languages,
|
||||
source: createMDXSource(map),
|
||||
});
|
||||
Reference in New Issue
Block a user