Switch to new Metadata API
This commit is contained in:
parent
afd18d19a9
commit
6d184906b1
21 changed files with 258 additions and 209 deletions
|
@ -1,5 +0,0 @@
|
|||
import PageSeo from "@components/page-seo"
|
||||
|
||||
export default function AuthHead() {
|
||||
return <PageSeo title="Sign In" />
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
import { getMetadata } from "src/app/lib/metadata"
|
||||
import config from "@lib/config"
|
||||
import Auth from "../components"
|
||||
|
||||
|
@ -10,3 +11,7 @@ function isGithubEnabled() {
|
|||
export default function SignInPage() {
|
||||
return <Auth page="signin" isGithubEnabled={isGithubEnabled()} />
|
||||
}
|
||||
|
||||
export const metadata = getMetadata({
|
||||
title: "Sign in",
|
||||
})
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
import PageSeo from "@components/page-seo"
|
||||
|
||||
export default function AuthHead() {
|
||||
return <PageSeo title="Sign Up" />
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
import Auth from "../components"
|
||||
import { getRequiresPasscode } from "src/pages/api/auth/requires-passcode"
|
||||
import config from "@lib/config"
|
||||
import { getMetadata } from "src/app/lib/metadata"
|
||||
|
||||
async function getPasscode() {
|
||||
return await getRequiresPasscode()
|
||||
|
@ -22,3 +23,7 @@ export default async function SignUpPage() {
|
|||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export const metadata = getMetadata({
|
||||
title: "Sign up",
|
||||
})
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
"use client"
|
||||
|
||||
import Note from "@components/note"
|
||||
import { getMetadata } from "src/app/lib/metadata"
|
||||
|
||||
export default function ExpiredPage() {
|
||||
return (
|
||||
|
@ -9,3 +8,8 @@ export default function ExpiredPage() {
|
|||
</Note>
|
||||
)
|
||||
}
|
||||
|
||||
export const metadata = getMetadata({
|
||||
title: "Post expired",
|
||||
hidden: true
|
||||
})
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
import PageSeo from "@components/page-seo"
|
||||
|
||||
export default function NewPostHead() {
|
||||
return <PageSeo title="New" />
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
import { getMetadata } from "src/app/lib/metadata"
|
||||
import NewPost from "src/app/(drift)/(posts)/new/components/new"
|
||||
import "./react-datepicker.css"
|
||||
|
||||
|
@ -6,3 +7,8 @@ export default function New() {
|
|||
}
|
||||
|
||||
export const dynamic = "force-static"
|
||||
|
||||
export const metadata = getMetadata({
|
||||
title: "New post",
|
||||
hidden: true
|
||||
})
|
|
@ -1,29 +0,0 @@
|
|||
import PageSeo from "@components/page-seo"
|
||||
import { getPostById } from "@lib/server/prisma"
|
||||
|
||||
export default async function Head({
|
||||
params
|
||||
}: {
|
||||
params: {
|
||||
id: string
|
||||
}
|
||||
}) {
|
||||
const post = await getPostById(params.id, {
|
||||
select: {
|
||||
title: true,
|
||||
description: true
|
||||
}
|
||||
})
|
||||
|
||||
if (!post) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<PageSeo
|
||||
title={post.title}
|
||||
description={post.description || undefined}
|
||||
isPrivate={false}
|
||||
/>
|
||||
)
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
import VisibilityControl from "@components/badges/visibility-control"
|
||||
import { getMetadata } from "src/app/lib/metadata"
|
||||
import {
|
||||
PostWithFilesAndAuthor,
|
||||
serverPostToClientPost,
|
||||
|
@ -28,3 +29,28 @@ export default async function PostPage({
|
|||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export const generateMetadata = async ({
|
||||
params
|
||||
}: {
|
||||
params: {
|
||||
id: string
|
||||
}
|
||||
}) => {
|
||||
const post = (await getPost(params.id)) as ServerPostWithFilesAndAuthor
|
||||
|
||||
return getMetadata({
|
||||
title: post.title,
|
||||
description: post.description || undefined,
|
||||
hidden: post.visibility === "public",
|
||||
overrides: {
|
||||
openGraph: {
|
||||
title: post.title,
|
||||
description: post.description || undefined,
|
||||
type: "website",
|
||||
siteName: "Drift",
|
||||
// TODO: og images
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { getMetadata } from "src/app/lib/metadata"
|
||||
import { getCurrentUser } from "@lib/server/session"
|
||||
import { redirect } from "next/navigation"
|
||||
|
||||
|
@ -15,3 +16,9 @@ export default async function AdminLayout({
|
|||
|
||||
return children
|
||||
}
|
||||
|
||||
export const metadata = getMetadata({
|
||||
title: "Admin",
|
||||
hidden: true
|
||||
})
|
||||
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
import PageSeo from "@components/page-seo"
|
||||
|
||||
export default function RootHead() {
|
||||
return <PageSeo />
|
||||
}
|
|
@ -4,6 +4,8 @@ import Layout from "@components/layout"
|
|||
import { Toasts } from "@components/toasts"
|
||||
import Header from "@components/header"
|
||||
import { Inter } from "next/font/google"
|
||||
import type { Metadata } from 'next'
|
||||
import { getMetadata } from "src/app/lib/metadata"
|
||||
|
||||
const inter = Inter({ subsets: ["latin"], variable: "--inter-font" })
|
||||
|
||||
|
@ -28,3 +30,5 @@ export default async function RootLayout({
|
|||
</html>
|
||||
)
|
||||
}
|
||||
|
||||
export const metadata = getMetadata()
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
import PageSeo from "@components/page-seo"
|
||||
|
||||
export default function Head() {
|
||||
return <PageSeo title="Your profile" isPrivate />
|
||||
}
|
|
@ -5,6 +5,7 @@ import { getCurrentUser } from "@lib/server/session"
|
|||
import { authOptions } from "@lib/server/auth"
|
||||
import { Suspense } from "react"
|
||||
import ErrorBoundary from "@components/error/fallback"
|
||||
import { getMetadata } from "src/app/lib/metadata"
|
||||
|
||||
export default async function Mine() {
|
||||
const userId = (await getCurrentUser())?.id
|
||||
|
@ -29,3 +30,8 @@ export default async function Mine() {
|
|||
}
|
||||
|
||||
export const revalidate = 0
|
||||
|
||||
export const metadata = getMetadata({
|
||||
title: "Your profile",
|
||||
hidden: true
|
||||
})
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
import PageSeo from "@components/page-seo"
|
||||
|
||||
export default function Head() {
|
||||
return <PageSeo title="Settings" isPrivate />
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
import { getMetadata } from "src/app/lib/metadata"
|
||||
import SettingsGroup from "../../components/settings-group"
|
||||
import APIKeys from "./components/sections/api-keys"
|
||||
import Profile from "./components/sections/profile"
|
||||
|
@ -14,3 +15,8 @@ export default async function SettingsPage() {
|
|||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export const metadata = getMetadata({
|
||||
title: "Settings",
|
||||
hidden: true
|
||||
})
|
||||
|
|
|
@ -1,89 +0,0 @@
|
|||
import config from "@lib/config"
|
||||
import React from "react"
|
||||
|
||||
type PageSeoProps = {
|
||||
title?: string
|
||||
description?: string
|
||||
isLoading?: boolean
|
||||
isPrivate?: boolean
|
||||
}
|
||||
|
||||
const PageSeo = ({
|
||||
title: pageTitle,
|
||||
description = "A self-hostable clone of GitHub Gist",
|
||||
isPrivate = false
|
||||
}: PageSeoProps) => {
|
||||
const title = `Drift${pageTitle ? ` - ${pageTitle}` : ""}`
|
||||
return (
|
||||
<>
|
||||
<title>{title}</title>
|
||||
<meta charSet="utf-8" />
|
||||
{!isPrivate && <meta name="description" content={description} />}
|
||||
{isPrivate && <meta name="robots" content="noindex" />}
|
||||
|
||||
{/* TODO: verify the correct meta tags */}
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width, initial-scale=1, shrink-to-fit=no"
|
||||
/>
|
||||
<ThemeAndIcons />
|
||||
<URLs />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default PageSeo
|
||||
|
||||
const ThemeAndIcons = () => (
|
||||
<>
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
sizes="180x180"
|
||||
href="/assets/apple-touch-icon.png"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
sizes="32x32"
|
||||
href="/assets/favicon-32x32.png"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
sizes="16x16"
|
||||
href="/assets/favicon-16x16.png"
|
||||
/>
|
||||
<link rel="manifest" href="/site.webmanifest" />
|
||||
<link
|
||||
rel="mask-icon"
|
||||
href="/assets/safari-pinned-tab.svg"
|
||||
color="#5bbad5"
|
||||
/>
|
||||
<meta name="apple-mobile-web-app-title" content="Drift" />
|
||||
<meta name="application-name" content="Drift" />
|
||||
<meta name="msapplication-TileColor" content="#da532c" />
|
||||
<meta
|
||||
name="theme-color"
|
||||
content="#ffffff"
|
||||
media="(prefers-color-scheme: light)"
|
||||
/>
|
||||
<meta
|
||||
name="theme-color"
|
||||
content="#000"
|
||||
media="(prefers-color-scheme: dark)"
|
||||
/>
|
||||
</>
|
||||
)
|
||||
|
||||
const URLs = () => (
|
||||
<>
|
||||
<meta property="twitter:card" content="summary_large_image" />
|
||||
<meta property="twitter:url" content={config.url} />
|
||||
{/* TODO: OG image */}
|
||||
<meta property="twitter:image" content={`${config.url}/assets/og.png`} />
|
||||
<meta property="twitter:site" content="@" />
|
||||
<meta property="twitter:creator" content="@drift" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content={config.url} />
|
||||
</>
|
||||
)
|
|
@ -99,6 +99,7 @@ const ListItem = ({
|
|||
<Button
|
||||
iconRight={<ArrowUpCircle />}
|
||||
onClick={viewParentClick}
|
||||
// TODO: not perfect on mobile
|
||||
height={38}
|
||||
/>
|
||||
</Tooltip>
|
||||
|
|
127
src/app/lib/metadata.tsx
Normal file
127
src/app/lib/metadata.tsx
Normal file
|
@ -0,0 +1,127 @@
|
|||
import config from "@lib/config"
|
||||
import { Metadata } from "next"
|
||||
import React from "react"
|
||||
|
||||
type PageSeoProps = {
|
||||
title?: string
|
||||
description?: string
|
||||
isLoading?: boolean
|
||||
isPrivate?: boolean
|
||||
}
|
||||
|
||||
const PageSeo = ({
|
||||
title: pageTitle,
|
||||
description = "A self-hostable clone of GitHub Gist",
|
||||
isPrivate = false
|
||||
}: PageSeoProps) => {
|
||||
const title = `Drift${pageTitle ? ` - ${pageTitle}` : ""}`
|
||||
return (
|
||||
<>
|
||||
<title>{title}</title>
|
||||
<meta charSet="utf-8" />
|
||||
{!isPrivate && <meta name="description" content={description} />}
|
||||
{isPrivate && <meta name="robots" content="noindex" />}
|
||||
|
||||
<ThemeAndIcons />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default PageSeo
|
||||
|
||||
const ThemeAndIcons = () => (
|
||||
<>
|
||||
<link />
|
||||
<meta name="apple-mobile-web-app-title" content="Drift" />
|
||||
<meta name="application-name" content="Drift" />
|
||||
<meta
|
||||
name="theme-color"
|
||||
content="#ffffff"
|
||||
media="(prefers-color-scheme: light)"
|
||||
/>
|
||||
<meta
|
||||
name="theme-color"
|
||||
content="#000"
|
||||
media="(prefers-color-scheme: dark)"
|
||||
/>
|
||||
</>
|
||||
)
|
||||
|
||||
export function getMetadata({
|
||||
title,
|
||||
description = "A self-hostable clone of GitHub Gist",
|
||||
hidden = false,
|
||||
overrides
|
||||
}: {
|
||||
overrides?: Metadata
|
||||
title?: string
|
||||
description?: string
|
||||
hidden?: boolean
|
||||
} = {}): Metadata {
|
||||
function undefinedIfHidden<T>(value: T): T | undefined {
|
||||
return hidden ? undefined : value
|
||||
}
|
||||
|
||||
title = `Drift${title ? ` - ${title}` : ""}`
|
||||
|
||||
return {
|
||||
title,
|
||||
description: undefinedIfHidden(description),
|
||||
themeColor: "#000",
|
||||
manifest: "/site.webmanifest",
|
||||
viewport: "width=device-width, initial-scale=1, shrink-to-fit=no",
|
||||
robots: hidden ? "noindex" : undefined,
|
||||
twitter: undefinedIfHidden({
|
||||
card: "summary_large_image",
|
||||
title,
|
||||
description,
|
||||
...overrides?.twitter
|
||||
}),
|
||||
applicationName: "Drift",
|
||||
icons: [
|
||||
{
|
||||
rel: "icon",
|
||||
sizes: "32x32",
|
||||
type: "image/png",
|
||||
url: "/assets/favicon-32x32.png"
|
||||
},
|
||||
{
|
||||
rel: "apple-touch-icon",
|
||||
sizes: "180x180",
|
||||
url: "/assets/apple-touch-icon.png"
|
||||
},
|
||||
{
|
||||
rel: "icon",
|
||||
sizes: "16x16",
|
||||
url: "/assets/favicon-16x16.png"
|
||||
},
|
||||
{
|
||||
rel: "mask-icon",
|
||||
url: "/assets/safari-pinned-tab.svg"
|
||||
// TODO: re-enable this when we have a better color
|
||||
// color: "#5bbad5"
|
||||
}
|
||||
],
|
||||
openGraph: undefinedIfHidden({
|
||||
type: "website",
|
||||
url: config.url,
|
||||
siteName: "Drift",
|
||||
title,
|
||||
description,
|
||||
...overrides?.openGraph
|
||||
}),
|
||||
keywords: undefinedIfHidden([
|
||||
"gist",
|
||||
"github",
|
||||
"drift",
|
||||
"next.js",
|
||||
"self-hosted",
|
||||
"paste",
|
||||
"pastebin",
|
||||
"clone",
|
||||
"code",
|
||||
"snippet"
|
||||
]),
|
||||
...overrides
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue