feat(guide): port legacy guide (#10938)

* feat: initial attempt at porting legacy guide

* feat: completion of legacy guide backport

* chore: lockfile shenanigans

* fix: handle svgs

* fix: replace svg with mermaid integration

* chore: format

* chore: remove unnecssary bullet

* chore: cleanup code highlights

* chore: explicit return

* chore: move display components after interactive components in sidebar

* chore: voice

* top link should be installation
* add docs link to sidebar

* feat: subguide-based accent styles

* chore: don't list faq twice

* chore: mention display components in interactive components

* fix: remove unoccs/order rule from guide

* chore: redirect to legacy guide instead of /guide root

* refactor: use `<kbd>`

* refactor: more kbd use

* Update apps/guide/content/docs/legacy/app-creation/handling-events.mdx

Co-authored-by: Naiyar <137700126+imnaiyar@users.noreply.github.com>

* chore: fix typos

Co-authored-by: Qjuh <76154676+Qjuh@users.noreply.github.com>

* chore: fix typos

* chore: fix links regarding secret stores across coding platforms

* chore: fix typo

* chore: link node method directly

Co-authored-by: Qjuh <76154676+Qjuh@users.noreply.github.com>

* chore: typos

Co-authored-by: Vlad Frangu <me@vladfrangu.dev>

* chore: typo

Co-authored-by: Vlad Frangu <me@vladfrangu.dev>

* fix: prevent v14 changes from being listed twice

* chore: prefer relative links

* chore: missed link conversion

* chore: missed link conversion

* chore: fix link

* chore: remove legacy code highlight markers

* chore: rephrase and extend contributing guidelines

* feat(setup): suggest cli flag over dotenv package

* chore: move introduction in sidebar

better navigation experience if the 'next page' in intro refers to getting started vs. updating/faq

* fix: replace outdated link

* fix: update voice dependencies

* chore: update node install instructions

* fix: list in missing access callout

* chore: match bun env file format

* chore: restore ffmpeg disclaimer

* fix: lockfile conflict

* chore: action row typo

Co-authored-by: Vlad Frangu <me@vladfrangu.dev>

* chore: no longer use at-next for pino

---------

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
Co-authored-by: Qjuh <76154676+Qjuh@users.noreply.github.com>
Co-authored-by: Naiyar <137700126+imnaiyar@users.noreply.github.com>
Co-authored-by: Vlad Frangu <me@vladfrangu.dev>
This commit is contained in:
Souji
2025-07-08 15:01:50 +02:00
committed by GitHub
parent ee3ca6f7c6
commit bc6005f446
136 changed files with 11847 additions and 48 deletions

View File

@@ -5,7 +5,36 @@ import { source } from '@/lib/source';
export default function Layout({ children }: { readonly children: ReactNode }) {
return (
<DocsLayout tree={source.pageTree} {...baseOptions}>
<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.file.path.split('/')[0]}-color, var(--color-fd-foreground))`;
return {
...option,
icon: (
<div
className="rounded-lg border p-1.5 shadow-lg md:mb-auto md:rounded-md md:p-1 [&_svg]:size-6 md:[&_svg]:size-5"
style={{
color,
backgroundColor: `color-mix(in oklab, ${color} 10%, transparent)`,
}}
>
{node.icon}
</div>
),
};
},
},
}}
tree={source.pageTree}
{...baseOptions}
>
{children}
</DocsLayout>
);

View File

@@ -0,0 +1,16 @@
'use client';
import { useParams } from 'next/navigation';
import type { ReactNode } from 'react';
export function Body({ children }: { readonly children: ReactNode }): React.ReactElement {
const mode = useMode();
// page highlight color based on path src/styles/base.css
return <body className={`${mode ? `${mode} ` : ''}overscroll-y-none`}>{children}</body>;
}
export function useMode(): string | undefined {
const { slug } = useParams();
return Array.isArray(slug) && slug.length > 0 ? slug[0] : undefined;
}

View File

@@ -4,6 +4,7 @@ import { GeistMono } from 'geist/font/mono';
import { GeistSans } from 'geist/font/sans';
import type { Metadata, Viewport } from 'next';
import type { PropsWithChildren } from 'react';
import { Body } from '@/app/layout.client';
import { ENV } from '@/util/env';
import '@/styles/base.css';
@@ -72,10 +73,10 @@ export const metadata: Metadata = {
export default async function RootLayout({ children }: PropsWithChildren) {
return (
<html className={`${GeistSans.variable} ${GeistMono.variable} antialiased`} lang="en" suppressHydrationWarning>
<body className="overscroll-y-none">
<Body>
<RootProvider>{children}</RootProvider>
<Analytics />
</body>
</Body>
</html>
);
}

View File

@@ -1,5 +1,5 @@
import { redirect } from 'next/navigation';
export default async function Page() {
redirect('/guide');
redirect('/guide/legacy');
}

View File

@@ -0,0 +1,45 @@
'use client';
import { useTheme } from 'next-themes';
import { useEffect, useId, useRef, useState } from 'react';
export function Mermaid({ chart }: { readonly chart: string }) {
const id = useId();
const [svg, setSvg] = useState('');
const containerRef = useRef<HTMLDivElement>(null);
const currentChartRef = useRef<string>(null);
const { resolvedTheme } = useTheme();
useEffect(() => {
if (currentChartRef.current === chart || !containerRef.current) return;
const container = containerRef.current;
currentChartRef.current = chart;
async function renderChart() {
const { default: mermaid } = await import('mermaid');
try {
// configure mermaid
mermaid.initialize({
startOnLoad: false,
securityLevel: 'loose',
fontFamily: 'inherit',
themeCSS: 'margin: 1.5rem auto 0;',
theme: resolvedTheme === 'dark' ? 'dark' : 'default',
});
const { svg, bindFunctions } = await mermaid.render(id, chart.replaceAll('\\n', '\n'));
bindFunctions?.(container);
setSvg(svg);
} catch (error) {
console.error('Error while rendering mermaid', error);
}
}
void renderChart();
}, [chart, id, resolvedTheme]);
// eslint-disable-next-line react/no-danger
return <div dangerouslySetInnerHTML={{ __html: svg }} ref={containerRef} />;
}

View File

@@ -1,7 +1,20 @@
import { loader } from 'fumadocs-core/source';
import { icons } from 'lucide-react';
import { createElement } from 'react';
import { docs } from '../../.source';
export const source = loader({
baseUrl: '/guide',
icon(icon) {
if (!icon) {
return undefined;
}
if (icon in icons) {
return createElement(icons[icon as keyof typeof icons]);
}
return undefined;
},
baseUrl: '/guide/',
source: docs.toFumadocsSource(),
});

View File

@@ -1,6 +1,8 @@
import { Popup, PopupContent, PopupTrigger } from 'fumadocs-twoslash/ui';
import * as TabsComponents from 'fumadocs-ui/components/tabs';
import defaultMdxComponents from 'fumadocs-ui/mdx';
import type { MDXComponents } from 'mdx/types';
import { Mermaid } from '@/components/mdx/mermaid';
export function getMDXComponents(components?: MDXComponents): MDXComponents {
return {
@@ -8,6 +10,8 @@ export function getMDXComponents(components?: MDXComponents): MDXComponents {
Popup,
PopupContent,
PopupTrigger,
Mermaid,
...TabsComponents,
...components,
};
}

View File

@@ -24,3 +24,16 @@
@utility scrollbar-hidden {
scrollbar-width: none;
}
:root {
--legacy-color: hsl(153, 48%, 41%);
--voice-color: hsl(211.3, 66.1%, 65.3%);
}
.legacy {
--color-fd-primary: var(--legacy-color);
}
.voice {
--color-fd-primary: var(--voice-color);
}