mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-09 16:13:31 +01:00
refactor: remove guide route prefix (#11146)
* refactor: remove guide route prefix * chore: implement backwards compat redirect * Change guide redirect destination and permanence Updated the redirect destination and permanence for the guide route. --------- Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
This commit is contained in:
@@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"pages": [
|
"pages": [
|
||||||
"[MessageCircleQuestion][FAQ](/guide/legacy/popular-topics/faq)",
|
"[MessageCircleQuestion][FAQ](/legacy/popular-topics/faq)",
|
||||||
"[ArrowDownToLine][Updating to v14](/guide/legacy/additional-info/changes-in-v14)",
|
"[ArrowDownToLine][Updating to v14](/legacy/additional-info/changes-in-v14)",
|
||||||
"[LibraryBig][Documentation](https://discord.js.org/docs)",
|
"[LibraryBig][Documentation](https://discord.js.org/docs)",
|
||||||
"[Info][Introduction](/guide/legacy)",
|
"[Info][Introduction](/legacy)",
|
||||||
"---Setup---",
|
"---Setup---",
|
||||||
"preparations",
|
"preparations",
|
||||||
"---Your App---",
|
"---Your App---",
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ export async function generateStaticParams() {
|
|||||||
return source.generateParams();
|
return source.generateParams();
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function generateMetadata(props: { params: Promise<{ slug?: string[] }> }) {
|
export async function generateMetadata(props: { params: Promise<{ slug?: string[] }> }): Promise<Metadata> {
|
||||||
const params = await props.params;
|
const params = await props.params;
|
||||||
const page = source.getPage(params.slug);
|
const page = source.getPage(params.slug);
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ export async function generateMetadata(props: { params: Promise<{ slug?: string[
|
|||||||
notFound();
|
notFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
const image = ['/docs-og', ...(params.slug ?? []), 'image.png'].join('/');
|
const image = ['/og', ...(params.slug ?? []), 'image.png'].join('/');
|
||||||
return {
|
return {
|
||||||
title: page.data.title,
|
title: page.data.title,
|
||||||
description: page.data.description,
|
description: page.data.description,
|
||||||
@@ -27,7 +27,7 @@ export async function generateMetadata(props: { params: Promise<{ slug?: string[
|
|||||||
card: 'summary_large_image',
|
card: 'summary_large_image',
|
||||||
images: image,
|
images: image,
|
||||||
},
|
},
|
||||||
} satisfies Metadata;
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function Page(props: { readonly params: Promise<{ slug?: string[] }> }) {
|
export default async function Page(props: { readonly params: Promise<{ slug?: string[] }> }) {
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
|
|
||||||
import type { CSSProperties, ReactNode } from 'react';
|
|
||||||
import { baseOptions } from '@/app/layout.config';
|
|
||||||
import { source } from '@/lib/source';
|
|
||||||
|
|
||||||
export default function Layout({ children }: { readonly children: ReactNode }) {
|
|
||||||
return (
|
|
||||||
<DocsLayout
|
|
||||||
sidebar={{
|
|
||||||
tabs: {
|
|
||||||
transform(option, node) {
|
|
||||||
const meta = source.getNodeMeta(node);
|
|
||||||
if (!meta || !node.icon) return option;
|
|
||||||
|
|
||||||
// category selection color based on path src/styles/base.css
|
|
||||||
const color = `var(--${meta.path.split('/')[0]}-color, var(--color-fd-foreground))`;
|
|
||||||
|
|
||||||
return {
|
|
||||||
...option,
|
|
||||||
icon: (
|
|
||||||
<div
|
|
||||||
className="size-full rounded-lg text-(--tab-color) max-md:border max-md:bg-(--tab-color)/10 max-md:p-1.5 [&_svg]:size-full"
|
|
||||||
style={
|
|
||||||
{
|
|
||||||
'--tab-color': color,
|
|
||||||
} as CSSProperties
|
|
||||||
}
|
|
||||||
>
|
|
||||||
{node.icon}
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
tree={source.pageTree}
|
|
||||||
{...baseOptions}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</DocsLayout>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
import { Analytics } from '@vercel/analytics/react';
|
import { Analytics } from '@vercel/analytics/react';
|
||||||
|
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
|
||||||
import { RootProvider } from 'fumadocs-ui/provider';
|
import { RootProvider } from 'fumadocs-ui/provider';
|
||||||
import { GeistMono } from 'geist/font/mono';
|
import { GeistMono } from 'geist/font/mono';
|
||||||
import { GeistSans } from 'geist/font/sans';
|
import { GeistSans } from 'geist/font/sans';
|
||||||
import type { Metadata, Viewport } from 'next';
|
import type { Metadata, Viewport } from 'next';
|
||||||
import type { PropsWithChildren } from 'react';
|
import type { CSSProperties, PropsWithChildren } from 'react';
|
||||||
import { Body } from '@/app/layout.client';
|
import { Body } from '@/app/layout.client';
|
||||||
|
import { source } from '@/lib/source';
|
||||||
import { ENV } from '@/util/env';
|
import { ENV } from '@/util/env';
|
||||||
|
import { baseOptions } from './layout.config';
|
||||||
|
|
||||||
import '@/styles/base.css';
|
import '@/styles/base.css';
|
||||||
|
|
||||||
@@ -18,7 +21,7 @@ export const viewport: Viewport = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
metadataBase: new URL(ENV.IS_LOCAL_DEV ? `http://localhost:${ENV.PORT}` : 'https://next.discordjs.guide'),
|
metadataBase: new URL(ENV.IS_LOCAL_DEV ? `http://localhost:${ENV.PORT}` : 'https://discordjs.guide'),
|
||||||
title: {
|
title: {
|
||||||
template: '%s | discord.js',
|
template: '%s | discord.js',
|
||||||
default: 'discord.js',
|
default: 'discord.js',
|
||||||
@@ -74,7 +77,41 @@ export default async function RootLayout({ children }: PropsWithChildren) {
|
|||||||
return (
|
return (
|
||||||
<html className={`${GeistSans.variable} ${GeistMono.variable} antialiased`} lang="en" suppressHydrationWarning>
|
<html className={`${GeistSans.variable} ${GeistMono.variable} antialiased`} lang="en" suppressHydrationWarning>
|
||||||
<Body>
|
<Body>
|
||||||
<RootProvider>{children}</RootProvider>
|
<RootProvider>
|
||||||
|
<DocsLayout
|
||||||
|
sidebar={{
|
||||||
|
tabs: {
|
||||||
|
transform(option, node) {
|
||||||
|
const meta = source.getNodeMeta(node);
|
||||||
|
if (!meta || !node.icon) return option;
|
||||||
|
|
||||||
|
// category selection color based on path src/styles/base.css
|
||||||
|
const color = `var(--${meta.path.split('/')[0]}-color, var(--color-fd-foreground))`;
|
||||||
|
|
||||||
|
return {
|
||||||
|
...option,
|
||||||
|
icon: (
|
||||||
|
<div
|
||||||
|
className="size-full rounded-lg text-(--tab-color) max-md:border max-md:bg-(--tab-color)/10 max-md:p-1.5 [&_svg]:size-full"
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
'--tab-color': color,
|
||||||
|
} as CSSProperties
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{node.icon}
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
tree={source.pageTree}
|
||||||
|
{...baseOptions}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</DocsLayout>
|
||||||
|
</RootProvider>
|
||||||
<Analytics />
|
<Analytics />
|
||||||
</Body>
|
</Body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ export function generateStaticParams() {
|
|||||||
export async function GET(_req: Request, { params }: { params: Promise<{ slug: string[] }> }) {
|
export async function GET(_req: Request, { params }: { params: Promise<{ slug: string[] }> }) {
|
||||||
const { slug } = await params;
|
const { slug } = await params;
|
||||||
const page = source.getPage(slug.slice(0, -1));
|
const page = source.getPage(slug.slice(0, -1));
|
||||||
// const fontData = await fetch(new URL('../../../assets/Geist-Regular.ttf', import.meta.url), {
|
// const fontData = await fetch(new URL('../../assets/Geist-Regular.ttf', import.meta.url), {
|
||||||
// next: { revalidate: 604_800 },
|
// next: { revalidate: 604_800 },
|
||||||
// }).then(async (res) => res.arrayBuffer());
|
// }).then(async (res) => res.arrayBuffer());
|
||||||
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
import { redirect } from 'next/navigation';
|
|
||||||
|
|
||||||
export default async function Page() {
|
|
||||||
redirect('/guide/legacy');
|
|
||||||
}
|
|
||||||
@@ -15,6 +15,6 @@ export const source = loader({
|
|||||||
|
|
||||||
return undefined;
|
return undefined;
|
||||||
},
|
},
|
||||||
baseUrl: '/guide/',
|
baseUrl: '/',
|
||||||
source: docs.toFumadocsSource(),
|
source: docs.toFumadocsSource(),
|
||||||
});
|
});
|
||||||
|
|||||||
16
apps/guide/src/middleware.ts
Normal file
16
apps/guide/src/middleware.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import { NextResponse, type NextRequest } from 'next/server';
|
||||||
|
|
||||||
|
export function middleware(request: NextRequest) {
|
||||||
|
// TODO: Remove this eventually
|
||||||
|
if (request.nextUrl.pathname.startsWith('/guide/')) {
|
||||||
|
const newUrl = request.nextUrl.clone();
|
||||||
|
newUrl.pathname = newUrl.pathname.replace('/guide/', '/');
|
||||||
|
return NextResponse.redirect(new URL(newUrl.pathname, request.url));
|
||||||
|
}
|
||||||
|
|
||||||
|
return NextResponse.redirect(new URL('/legacy', request.url));
|
||||||
|
}
|
||||||
|
|
||||||
|
export const config = {
|
||||||
|
matcher: ['/', '/guide/:path*'],
|
||||||
|
};
|
||||||
@@ -39,8 +39,8 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
source: '/guide/:path*',
|
source: '/guide/:path*',
|
||||||
destination: 'https://next.discordjs.guide/guide/:path*',
|
destination: 'https://discordjs.guide/:path*',
|
||||||
permanent: true,
|
permanent: false,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user