Skip to content

Commit

Permalink
Merge pull request #250 from storybookjs/fix-document-titles
Browse files Browse the repository at this point in the history
Fix document titles
  • Loading branch information
kylegach authored Dec 4, 2024
2 parents 15d7aca + 0eca099 commit 4252f21
Show file tree
Hide file tree
Showing 9 changed files with 182 additions and 77 deletions.
41 changes: 32 additions & 9 deletions apps/addon-catalog/app/(home)/tag/[...name]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,49 @@
import { type Metadata } from 'next';
import { notFound } from 'next/navigation';
import { Preview } from '../../../../components/preview';
import { fetchTagDetailsData } from '../../../../lib/fetch-tag-details-data';
import type { Tag } from '../../../../types';

// 60*60*24 = 24 hrs
export const revalidate = 86400;

interface Params {
name: string[];
}

type GenerateMetaData = (props: {
params: Promise<Params>;
}) => Promise<Metadata>;

interface TagDetailsProps {
params: {
name: string[];
};
params: Params;
}

async function getTagFromName(
tagName: string[],
): Promise<Tag | { error: string }> {
const name = tagName.join('/');
return (await fetchTagDetailsData(name)) || {};
}

export const generateMetadata: GenerateMetaData = async ({ params }) => {
const tagName = (await params).name.join('/');
const data = (await fetchTagDetailsData(tagName)) || {};

if ('error' in data) return {};
const { displayName } = data;

return {
title: displayName ? `${displayName} tag | Storybook integrations` : undefined,
};
};

export default async function TagDetails({
params: { name },
}: TagDetailsProps) {
const tagName = name.join('/');

if (!tagName) return notFound();

const data = (await fetchTagDetailsData(tagName)) || {};
const data = await getTagFromName(name);

if ('error' in data) return notFound();
if (!data || 'error' in data) return notFound();

return (
<>
Expand Down
42 changes: 33 additions & 9 deletions apps/addon-catalog/app/[...addonName]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,51 @@
import { type Metadata } from 'next';
import { notFound } from 'next/navigation';
import { SubHeader } from '@repo/ui';
import { cn } from '@repo/utils';
import { fetchAddonDetailsData } from '../../lib/fetch-addon-details-data';
import { AddonHero } from '../../components/addon/addon-hero';
import { AddonSidebar } from '../../components/addon/addon-sidebar';
import { Highlight } from '../../components/highlight';
import type { AddonWithTagLinks } from '../../types';

// 60*60*24 = 24 hrs
export const revalidate = 86400;

interface Params {
addonName: string[];
}

type GenerateMetaData = (props: {
params: Promise<Params>;
}) => Promise<Metadata>;

interface AddonDetailsProps {
params: {
addonName: string[];
};
params: Params;
}

export default async function AddonDetails({ params }: AddonDetailsProps) {
async function getAddonFromName(
addonName: string[],
): Promise<AddonWithTagLinks | undefined> {
// TODO: Better decoding?
const name = params.addonName.join('/').replace('%40', '@');
const addon = await fetchAddonDetailsData(name);
const name = addonName.join('/').replace('%40', '@');
return await fetchAddonDetailsData(name);
}

export const generateMetadata: GenerateMetaData = async ({ params }) => {
const name = (await params).addonName;
const addon = await getAddonFromName(name);

return {
title: addon?.displayName
? `${addon.displayName} | Storybook integrations`
: undefined,
};
};

export default async function AddonDetails({ params }: AddonDetailsProps) {
const addon = await getAddonFromName(params.addonName);

if (!addon) {
return <div>Not found.</div>;
}
if (!addon) notFound();

return (
<main className="mb-20">
Expand Down
2 changes: 1 addition & 1 deletion apps/addon-catalog/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const fontSans = nunitoSans({

export const metadata: Metadata = {
metadataBase: new URL('https://storybook.js.org/integrations'),
title: 'Integrations | Storybook: Frontend workshop for UI development',
title: 'Storybook integrations',
description:
'Integrations enable advanced functionality and unlock new workflows. Contributed by core maintainers and the amazing developer community.',
openGraph: {
Expand Down
7 changes: 7 additions & 0 deletions apps/frontpage/app/community/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { Metadata } from 'next';
import { Header, Footer, Container, NewsletterForm } from '@repo/ui';
import {
fetchDiscordMembers,
Expand All @@ -18,6 +19,12 @@ import { Sponsor } from '../../components/community/sponsor';
import { Testimonials } from '../../components/community/testimonials';
import { CommunityProvider } from './provider';

export function generateMetadata(): Metadata {
return {
title: 'Community | Storybook',
};
}

export default async function Page() {
const { number: githubCount, formattedResult: githubCountFormatted } =
await fetchGithubCount();
Expand Down
65 changes: 38 additions & 27 deletions apps/frontpage/app/docs/[...slug]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,43 @@
import { type Metadata } from 'next';
import { notFound, redirect } from 'next/navigation';
import { globalSearchMetaKeys, globalSearchImportance } from '@repo/ui';
import { latestVersion } from '@repo/utils';
import { type Metadata } from 'next';
import { type DocsVersion, latestVersion } from '@repo/utils';
import { getVersion } from '../../../lib/get-version';
import { getPageData } from '../../../lib/get-page';
import { getPageData, type PageDataProps } from '../../../lib/get-page';
import { getAllTrees } from '../../../lib/get-all-trees';
import { getFlatTree } from '../../../lib/get-flat-tree';
import { Content } from '../../../components/docs/content';

interface Params {
slug: string[];
}

type GenerateMetaData = (props: {
params: Promise<Params>;
}) => Promise<Metadata>;

interface PageProps {
params: {
slug?: string[];
};
params: Params;
}

export async function generateMetadata({
params: { slug },
}: PageProps): Promise<Metadata> {
async function getPageFromSlug(
slug: string[],
): Promise<{ activeVersion: DocsVersion; page: PageDataProps | undefined }> {
const activeVersion = getVersion(slug);
const isLatest = activeVersion.id === latestVersion.id;

const slugToFetch = slug ? [...slug] : [];
if (!isLatest) slugToFetch.shift();
slugToFetch.unshift(activeVersion.id);

const page = await getPageData(slugToFetch, activeVersion);
return { activeVersion, page };
}

export const generateMetadata: GenerateMetaData = async ({ params }) => {
const slug = (await params).slug;
const { activeVersion, page } = await getPageFromSlug(slug);

const listofTrees = getAllTrees();
const flatTree = getFlatTree({
tree: listofTrees,
Expand All @@ -29,11 +49,8 @@ export async function generateMetadata({
(node) => node.slug === `/docs/${newSlug.join('/')}`,
);

const slugToFetch = slug ? [...slug] : [];
const page = await getPageData(slugToFetch, activeVersion);

return {
title: `${page?.title ?? 'Docs'} | Storybook`,
title: page?.title ? `${page.title} | Storybook docs` : undefined,
alternates: {
canonical: findPage?.canonical,
},
Expand All @@ -42,7 +59,7 @@ export async function generateMetadata({
[globalSearchMetaKeys.importance]: globalSearchImportance.docs,
},
};
}
};

export const generateStaticParams = () => {
const listofTrees = getAllTrees();
Expand All @@ -62,21 +79,15 @@ export const generateStaticParams = () => {
};

export default async function Page({ params: { slug } }: PageProps) {
const activeVersion = getVersion(slug);
const isLatest = activeVersion.id === latestVersion.id;
const slugToFetch = slug ? [...slug] : [];
if (!isLatest) slugToFetch.shift();
slugToFetch.unshift(activeVersion.id);
const newSlug = slug ?? [];

const page = await getPageData(slugToFetch, activeVersion);

const isIndex = slug && slug[slug.length - 1] === 'index';
const pathWithoutIndex = `/docs/${newSlug.slice(0, -1).join('/')}`;

// If the page is an index page, redirect to the parent page
if (isIndex) redirect(pathWithoutIndex);
const isIndex = slug && slug[slug.length - 1] === 'index';
if (isIndex) {
const newSlug = slug ?? [];
const pathWithoutIndex = `/docs/${newSlug.slice(0, -1).join('/')}`;
redirect(pathWithoutIndex);
}

const { page } = await getPageFromSlug(slug);
if (!page) notFound();

return <Content page={page} />;
Expand Down
9 changes: 1 addition & 8 deletions apps/frontpage/app/docs/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Header, Footer, Container } from '@repo/ui';
import Image from 'next/image';
import { fetchGithubCount } from '@repo/utils';
import { type ReactNode, Suspense } from 'react';
import { type Metadata } from 'next';
import { Sidebar } from '../../components/docs/sidebar/sidebar';
import { NavDocs } from '../../components/docs/sidebar/docs-nav';
import { Submenu } from '../../components/docs/submenu';
Expand All @@ -12,12 +11,6 @@ import { getAllTrees } from '../../lib/get-all-trees';
import { DocsProvider } from './provider';
import { RendererCookie } from './renderer-cookie';

export function generateMetadata(): Metadata {
return {
title: 'Docs | Storybook',
};
}

export default async function Layout({ children }: { children: ReactNode }) {
const { number: githubCount } = await fetchGithubCount();
const listofTrees = getAllTrees();
Expand All @@ -39,7 +32,7 @@ export default async function Layout({ children }: { children: ReactNode }) {
<Image
alt="Storybook Docs"
// TODO: 40px is height of eyebrow. Find way to not hard-code this.
className="absolute top-[40px] left-0 w-full -z-10"
className="absolute left-0 top-[40px] -z-10 w-full"
height={339}
priority
src="/bubbles.png"
Expand Down
5 changes: 4 additions & 1 deletion apps/frontpage/app/docs/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import { type Metadata } from 'next';
import { getPageData } from '../../lib/get-page';
import { Content } from '../../components/docs/content';

export function generateMetadata(): Metadata {
export async function generateMetadata(): Promise<Metadata> {
const page = await getPageData([latestVersion.id], latestVersion);

return {
title: page?.title ? `${page.title} | Storybook docs` : undefined,
alternates: {
canonical: '/docs',
},
Expand Down
Loading

0 comments on commit 4252f21

Please sign in to comment.