feat: structured data markup
This commit is contained in:
parent
214ffc7a22
commit
89fb6269e9
|
|
@ -4,7 +4,6 @@ import { UniLink } from "~/components/ui/UniLink"
|
|||
import { Note, Profile } from "~/lib/types"
|
||||
import { CSB_SCAN } from "~/lib/env"
|
||||
import { useEffect, useState } from "react"
|
||||
import { useGetUserSites } from "~/queries/site"
|
||||
import { CharacterFloatCard } from "~/components/common/CharacterFloatCard"
|
||||
import { getSiteLink } from "~/lib/helpers"
|
||||
import { Avatar } from "~/components/ui/Avatar"
|
||||
|
|
@ -12,9 +11,9 @@ import { Avatar } from "~/components/ui/Avatar"
|
|||
export const PostMeta: React.FC<{
|
||||
page: Note
|
||||
site?: Profile | null
|
||||
}> = ({ page, site }) => {
|
||||
author?: Profile | null
|
||||
}> = ({ page, site, author }) => {
|
||||
const [isMounted, setIsMounted] = useState(false)
|
||||
const author = useGetUserSites(page.authors[0])
|
||||
|
||||
useEffect(() => {
|
||||
setIsMounted(true)
|
||||
|
|
@ -49,29 +48,28 @@ export const PostMeta: React.FC<{
|
|||
</span>
|
||||
</>
|
||||
) : null}
|
||||
{author.data?.[0].username &&
|
||||
site?.username !== author.data?.[0].username && (
|
||||
<>
|
||||
<span className="inline-flex items-center">
|
||||
<CharacterFloatCard siteId={author.data[0].username}>
|
||||
<UniLink
|
||||
href={getSiteLink({
|
||||
subdomain: author.data?.[0].username,
|
||||
})}
|
||||
className="cursor-pointer hover:text-zinc-600 inline-flex items-center"
|
||||
>
|
||||
<Avatar
|
||||
className="mr-1"
|
||||
images={author.data[0].avatars || []}
|
||||
size={19}
|
||||
name={author.data[0].name}
|
||||
/>
|
||||
<span>{author.data[0].name}</span>
|
||||
</UniLink>
|
||||
</CharacterFloatCard>
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
{author?.username && site?.username !== author?.username && (
|
||||
<>
|
||||
<span className="inline-flex items-center">
|
||||
<CharacterFloatCard siteId={author?.username}>
|
||||
<UniLink
|
||||
href={getSiteLink({
|
||||
subdomain: author?.username,
|
||||
})}
|
||||
className="cursor-pointer hover:text-zinc-600 inline-flex items-center"
|
||||
>
|
||||
<Avatar
|
||||
className="mr-1"
|
||||
images={author?.avatars || []}
|
||||
size={19}
|
||||
name={author?.name}
|
||||
/>
|
||||
<span>{author?.name}</span>
|
||||
</UniLink>
|
||||
</CharacterFloatCard>
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
<UniLink
|
||||
className="xlog-post-blockchain inline-block"
|
||||
href={
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import {
|
|||
prefetchGetSite,
|
||||
prefetchGetSiteSubscriptions,
|
||||
prefetchGetSiteToSubscriptions,
|
||||
prefetchGetUserSites,
|
||||
} from "~/queries/site.server"
|
||||
import { prefetchGetPagesBySite } from "~/queries/page.server"
|
||||
import { PageVisibilityEnum } from "~/lib/types"
|
||||
|
|
@ -48,6 +49,10 @@ export const getServerSideProps = async (
|
|||
if (!page || new Date(page!.date_published) > new Date()) {
|
||||
reject(notFound())
|
||||
}
|
||||
|
||||
if (page?.authors[0]) {
|
||||
await prefetchGetUserSites(page?.authors[0], queryClient)
|
||||
}
|
||||
} catch (error) {
|
||||
reject(error)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,34 +2,71 @@ import { PageContent } from "../common/PageContent"
|
|||
import { PostMeta } from "./PostMeta"
|
||||
import { PostFooter } from "./PostFooter"
|
||||
import { Note, Profile } from "~/lib/types"
|
||||
import Head from "next/head"
|
||||
import { useGetUserSites } from "~/queries/site"
|
||||
import { getSiteLink } from "~/lib/helpers"
|
||||
|
||||
export const SitePage: React.FC<{
|
||||
page?: Note | null
|
||||
site?: Profile | null
|
||||
}> = ({ page, site }) => {
|
||||
const author = useGetUserSites(page?.authors[0])
|
||||
|
||||
function addPageJsonLd() {
|
||||
return {
|
||||
__html: `{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "BlogPosting",
|
||||
"headline": "${page?.title}",
|
||||
"image": [
|
||||
"${page?.cover}"
|
||||
],
|
||||
"datePublished": "${page?.date_published}",
|
||||
"dateModified": "${page?.date_updated}",
|
||||
"author": [{
|
||||
"@type": "Person",
|
||||
"name": "${author?.data?.[0]?.name}",
|
||||
"url": "${getSiteLink({
|
||||
subdomain: author?.data?.[0].username || "",
|
||||
})}"
|
||||
}]
|
||||
}`,
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<script
|
||||
type="application/ld+json"
|
||||
dangerouslySetInnerHTML={addPageJsonLd()}
|
||||
/>
|
||||
</Head>
|
||||
{page?.preview && (
|
||||
<div className="fixed top-0 left-0 w-full text-center text-orange-500 bg-gray-100 py-2 opacity-80 text-sm">
|
||||
Currently in private preview mode, the content is different from the
|
||||
public
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
{page?.tags?.includes("post") ? (
|
||||
<h2 className="xlog-post-title text-4xl font-bold">{page.title}</h2>
|
||||
) : (
|
||||
<h2 className="xlog-post-title text-xl font-bold page-title">
|
||||
{page?.title}
|
||||
</h2>
|
||||
)}
|
||||
{page?.tags?.includes("post") && <PostMeta page={page} site={site} />}
|
||||
</div>
|
||||
<PageContent
|
||||
className="mt-10"
|
||||
content={page?.body?.content}
|
||||
toc={true}
|
||||
></PageContent>
|
||||
<article>
|
||||
<div>
|
||||
{page?.tags?.includes("post") ? (
|
||||
<h2 className="xlog-post-title text-4xl font-bold">{page.title}</h2>
|
||||
) : (
|
||||
<h2 className="xlog-post-title text-xl font-bold page-title">
|
||||
{page?.title}
|
||||
</h2>
|
||||
)}
|
||||
{page?.tags?.includes("post") && (
|
||||
<PostMeta page={page} site={site} author={author.data?.[0]} />
|
||||
)}
|
||||
</div>
|
||||
<PageContent
|
||||
className="mt-10"
|
||||
content={page?.body?.content}
|
||||
toc={true}
|
||||
></PageContent>
|
||||
</article>
|
||||
{page?.metadata && <PostFooter page={page} />}
|
||||
</>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ export const prefetchGetSites = async (
|
|||
queryClient: QueryClient,
|
||||
) => {
|
||||
const key = ["getSites", input]
|
||||
return await queryClient.fetchQuery(key, async () => {
|
||||
await queryClient.fetchQuery(key, async () => {
|
||||
return cacheGet(key, () => siteModel.getSites(input))
|
||||
})
|
||||
}
|
||||
|
|
@ -65,3 +65,13 @@ export const fetchGetNotifications = async (
|
|||
)
|
||||
})
|
||||
}
|
||||
|
||||
export const prefetchGetUserSites = async (
|
||||
address: string,
|
||||
queryClient: QueryClient,
|
||||
) => {
|
||||
const key = ["getUserSites", address]
|
||||
await queryClient.prefetchQuery(key, async () => {
|
||||
return cacheGet(key, () => siteModel.getUserSites(address))
|
||||
})
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue