mirror of
https://github.com/jakejarvis/jarv.is.git
synced 2025-07-03 13:06:37 -04:00
json-ld improvements
This commit is contained in:
@ -1,6 +1,9 @@
|
||||
import { JsonLd } from "react-schemaorg";
|
||||
import PageTitle from "../../components/PageTitle";
|
||||
import Video from "../../components/Video";
|
||||
import { addMetadata } from "../../lib/helpers/metadata";
|
||||
import { BASE_URL } from "../../lib/config/constants";
|
||||
import type { VideoObject } from "schema-dts";
|
||||
|
||||
import thumbnail from "./thumbnail.png";
|
||||
|
||||
@ -15,6 +18,20 @@ export const metadata = addMetadata({
|
||||
const Page = () => {
|
||||
return (
|
||||
<>
|
||||
<JsonLd<VideoObject>
|
||||
item={{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "VideoObject",
|
||||
name: metadata.title as string,
|
||||
description: metadata.description as string,
|
||||
thumbnailUrl: `${BASE_URL}${thumbnail.src}`,
|
||||
contentUrl:
|
||||
"https://bcm6wnmyyzj1p5ls.public.blob.vercel-storage.com/videos/birthday/birthday-8iayCEy1jfEHpNGZkdBPvxPFOuGz0g.mp4",
|
||||
uploadDate: "1996-02-06T00:00:00Z",
|
||||
duration: "PT6M10S",
|
||||
}}
|
||||
/>
|
||||
|
||||
<PageTitle canonical="/birthday">1996.mov</PageTitle>
|
||||
|
||||
<Video
|
||||
|
@ -1,7 +1,10 @@
|
||||
import { JsonLd } from "react-schemaorg";
|
||||
import PageTitle from "../../components/PageTitle";
|
||||
import Link from "../../components/Link";
|
||||
import Video from "../../components/Video";
|
||||
import { addMetadata } from "../../lib/helpers/metadata";
|
||||
import { BASE_URL } from "../../lib/config/constants";
|
||||
import type { VideoObject } from "schema-dts";
|
||||
|
||||
import thumbnail from "./thumbnail.png";
|
||||
|
||||
@ -16,6 +19,20 @@ export const metadata = addMetadata({
|
||||
const Page = () => {
|
||||
return (
|
||||
<>
|
||||
<JsonLd<VideoObject>
|
||||
item={{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "VideoObject",
|
||||
name: metadata.title as string,
|
||||
description: metadata.description as string,
|
||||
thumbnailUrl: `${BASE_URL}${thumbnail.src}`,
|
||||
contentUrl:
|
||||
"https://bcm6wnmyyzj1p5ls.public.blob.vercel-storage.com/videos/hillary/convention-720p-YLGreYE59PzmPo4epB21HQG6jXgYL5.mp4",
|
||||
uploadDate: "2016-07-25T00:00:00Z",
|
||||
duration: "PT1M51S",
|
||||
}}
|
||||
/>
|
||||
|
||||
<PageTitle canonical="/hillary">HRC.mov</PageTitle>
|
||||
|
||||
<Video
|
||||
|
@ -13,8 +13,10 @@
|
||||
}
|
||||
|
||||
.container {
|
||||
margin: 0 auto;
|
||||
display: block;
|
||||
width: 100%;
|
||||
max-width: var(--max-width);
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import clsx from "clsx";
|
||||
import { JsonLd } from "react-schemaorg";
|
||||
import Analytics from "./analytics";
|
||||
import { ThemeProvider } from "../contexts/ThemeContext";
|
||||
import Header from "../components/Header";
|
||||
@ -8,7 +9,7 @@ import * as config from "../lib/config";
|
||||
import { BASE_URL, MAX_WIDTH } from "../lib/config/constants";
|
||||
import defaultMetadata from "../lib/config/metadata";
|
||||
import type { Metadata } from "next";
|
||||
import type { Person, WithContext } from "schema-dts";
|
||||
import type { Person, WebSite } from "schema-dts";
|
||||
|
||||
import { GeistMono, GeistSans } from "../lib/styles/fonts";
|
||||
import "modern-normalize/modern-normalize.css"; // https://github.com/sindresorhus/modern-normalize/blob/main/modern-normalize.css
|
||||
@ -21,35 +22,52 @@ import ogImage from "./opengraph-image.jpg";
|
||||
|
||||
export const metadata: Metadata = defaultMetadata;
|
||||
|
||||
// https://nextjs.org/docs/app/building-your-application/optimizing/metadata#json-ld
|
||||
const jsonLd: WithContext<Person> = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Person",
|
||||
name: config.authorName,
|
||||
url: BASE_URL,
|
||||
image: `${BASE_URL}${ogImage.src}`,
|
||||
sameAs: [
|
||||
BASE_URL,
|
||||
`https://github.com/${config.authorSocial?.github}`,
|
||||
`https://keybase.io/${config.authorSocial?.keybase}`,
|
||||
`https://twitter.com/${config.authorSocial?.twitter}`,
|
||||
`https://medium.com/@${config.authorSocial?.medium}`,
|
||||
`https://www.linkedin.com/in/${config.authorSocial?.linkedin}/`,
|
||||
`https://www.facebook.com/${config.authorSocial?.facebook}`,
|
||||
`https://www.instagram.com/${config.authorSocial?.instagram}/`,
|
||||
`https://${config.authorSocial?.mastodon}`,
|
||||
`https://bsky.app/profile/${config.authorSocial?.bluesky}`,
|
||||
],
|
||||
};
|
||||
|
||||
const RootLayout = ({ children }: Readonly<{ children: React.ReactNode }>) => {
|
||||
return (
|
||||
<html lang={config.siteLocale} suppressHydrationWarning>
|
||||
<head>
|
||||
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }} />
|
||||
<JsonLd<Person>
|
||||
item={{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Person",
|
||||
"@id": `${BASE_URL}/#person`,
|
||||
name: config.authorName,
|
||||
url: BASE_URL,
|
||||
image: `${BASE_URL}${ogImage.src}`,
|
||||
sameAs: [
|
||||
BASE_URL,
|
||||
`https://github.com/${config.authorSocial?.github}`,
|
||||
`https://keybase.io/${config.authorSocial?.keybase}`,
|
||||
`https://twitter.com/${config.authorSocial?.twitter}`,
|
||||
`https://medium.com/@${config.authorSocial?.medium}`,
|
||||
`https://www.linkedin.com/in/${config.authorSocial?.linkedin}/`,
|
||||
`https://www.facebook.com/${config.authorSocial?.facebook}`,
|
||||
`https://www.instagram.com/${config.authorSocial?.instagram}/`,
|
||||
`https://${config.authorSocial?.mastodon}`,
|
||||
`https://bsky.app/profile/${config.authorSocial?.bluesky}`,
|
||||
],
|
||||
}}
|
||||
/>
|
||||
|
||||
<JsonLd<WebSite>
|
||||
item={{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "WebSite",
|
||||
"@id": `${BASE_URL}/#website`,
|
||||
name: config.siteName,
|
||||
url: BASE_URL,
|
||||
author: config.authorName,
|
||||
description: config.longDescription,
|
||||
inLanguage: config.siteLocale,
|
||||
license: config.licenseUrl,
|
||||
}}
|
||||
/>
|
||||
</head>
|
||||
|
||||
<body className={clsx(GeistMono.variable, GeistSans.variable)}>
|
||||
<body
|
||||
className={clsx(GeistMono.variable, GeistSans.variable)}
|
||||
style={{ ["--max-width" as string]: `${MAX_WIDTH}px` }}
|
||||
>
|
||||
<ThemeProvider>
|
||||
<SkipToContentLink />
|
||||
|
||||
@ -58,9 +76,7 @@ const RootLayout = ({ children }: Readonly<{ children: React.ReactNode }>) => {
|
||||
|
||||
<main className={styles.default}>
|
||||
<SkipToContentTarget />
|
||||
<div className={styles.container} style={{ maxWidth: MAX_WIDTH }}>
|
||||
{children}
|
||||
</div>
|
||||
<div className={styles.container}>{children}</div>
|
||||
</main>
|
||||
|
||||
<Footer />
|
||||
|
@ -1,7 +1,10 @@
|
||||
import { JsonLd } from "react-schemaorg";
|
||||
import PageTitle from "../../components/PageTitle";
|
||||
import Link from "../../components/Link";
|
||||
import Video from "../../components/Video";
|
||||
import { addMetadata } from "../../lib/helpers/metadata";
|
||||
import { BASE_URL } from "../../lib/config/constants";
|
||||
import type { VideoObject } from "schema-dts";
|
||||
|
||||
import thumbnail from "./thumbnail.png";
|
||||
|
||||
@ -16,6 +19,20 @@ export const metadata = addMetadata({
|
||||
const Page = () => {
|
||||
return (
|
||||
<>
|
||||
<JsonLd<VideoObject>
|
||||
item={{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "VideoObject",
|
||||
name: metadata.title as string,
|
||||
description: metadata.description as string,
|
||||
thumbnailUrl: `${BASE_URL}${thumbnail.src}`,
|
||||
contentUrl:
|
||||
"https://bcm6wnmyyzj1p5ls.public.blob.vercel-storage.com/videos/leo/leo-x4E4eG4YPo22KSTJuZwAk6fpNF1NgG.mp4",
|
||||
uploadDate: "2007-05-10T00:00:00Z",
|
||||
duration: "PT1M48S",
|
||||
}}
|
||||
/>
|
||||
|
||||
<PageTitle canonical="/leo">TheLab.mov</PageTitle>
|
||||
|
||||
<Video
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Suspense } from "react";
|
||||
import { ErrorBoundary } from "react-error-boundary";
|
||||
import { JsonLd } from "react-schemaorg";
|
||||
import { CalendarIcon, TagIcon, SquarePenIcon, EyeIcon } from "lucide-react";
|
||||
import Link from "../../../components/Link";
|
||||
import Time from "../../../components/Time";
|
||||
@ -11,7 +12,7 @@ import { addMetadata } from "../../../lib/helpers/metadata";
|
||||
import * as config from "../../../lib/config";
|
||||
import { BASE_URL } from "../../../lib/config/constants";
|
||||
import type { Metadata, Route } from "next";
|
||||
import type { Article, WithContext } from "schema-dts";
|
||||
import type { Article } from "schema-dts";
|
||||
|
||||
import styles from "./page.module.css";
|
||||
|
||||
@ -58,26 +59,29 @@ const Page = async ({ params }: { params: Promise<{ slug: string }> }) => {
|
||||
const { slug } = await params;
|
||||
const frontmatter = await getFrontMatter(slug);
|
||||
|
||||
const jsonLd: WithContext<Article> = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Article",
|
||||
name: frontmatter.title,
|
||||
description: frontmatter.description || config.longDescription,
|
||||
url: frontmatter.permalink,
|
||||
datePublished: frontmatter.date,
|
||||
dateModified: frontmatter.date,
|
||||
author: {
|
||||
"@type": "Person",
|
||||
name: config.authorName,
|
||||
url: BASE_URL,
|
||||
},
|
||||
};
|
||||
|
||||
const { default: MDXContent } = await import(`../../../notes/${slug}/index.mdx`);
|
||||
|
||||
return (
|
||||
<>
|
||||
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }} />
|
||||
<JsonLd<Article>
|
||||
item={{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Article",
|
||||
headline: frontmatter.title,
|
||||
description: frontmatter.description,
|
||||
url: frontmatter.permalink,
|
||||
image: [`${BASE_URL}/notes/${slug}/opengraph-image`],
|
||||
keywords: frontmatter.tags,
|
||||
datePublished: frontmatter.date,
|
||||
dateModified: frontmatter.date,
|
||||
inLanguage: config.siteLocale,
|
||||
license: config.licenseUrl,
|
||||
author: {
|
||||
// defined in app/layout.tsx
|
||||
"@id": `${BASE_URL}/#person`,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className={styles.meta}>
|
||||
<div className={styles.metaItem}>
|
||||
|
Reference in New Issue
Block a user