Skip to content

Commit

Permalink
feat: change social image urls
Browse files Browse the repository at this point in the history
  • Loading branch information
transitive-bullshit committed Apr 6, 2022
1 parent 03c12f9 commit 0b7d618
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 124 deletions.
38 changes: 2 additions & 36 deletions components/NotionPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,7 @@ import { Tweet, TwitterContextProvider } from 'react-static-tweets'
import { NotionRenderer } from 'react-notion-x'

// utils
import {
getBlockTitle,
getBlockIcon,
getPageProperty,
isUrl
} from 'notion-utils'
import { getBlockTitle, getPageProperty } from 'notion-utils'
import { mapPageUrl, getCanonicalPageUrl } from 'lib/map-page-url'
import { mapImageUrl } from 'lib/map-image-url'
import { getPageTweet } from 'lib/get-page-tweet'
Expand Down Expand Up @@ -134,36 +129,10 @@ export const NotionPage: React.FC<types.PageProps> = ({
block
)

const socialImageCoverPosition =
(block as PageBlock).format?.page_cover_position ??
config.defaultPageCoverPosition
const socialImageObjectPosition = socialImageCoverPosition
? `center ${(1 - socialImageCoverPosition) * 100}%`
: null

const blockIcon = getBlockIcon(block, recordMap)
const socialAuthorImage = mapImageUrl(
blockIcon && isUrl(blockIcon) ? blockIcon : config.defaultPageIcon,
block
)

const socialAuthor =
getPageProperty<string>('Author', block, recordMap) || config.author

const socialDescription =
getPageProperty<string>('Description', block, recordMap) ||
config.description

const timePublished = getPageProperty<number>('Published', block, recordMap)
const datePublished = timePublished ? new Date(timePublished) : undefined
const socialDate =
isBlogPost && datePublished
? `${datePublished.toLocaleString('en-US', {
month: 'long'
})} ${datePublished.getFullYear()}`
: undefined
const socialDetail = socialDate || site.domain

let pageAside: React.ReactNode = null

// only display comments and page actions on blog post pages
Expand All @@ -187,14 +156,11 @@ export const NotionPage: React.FC<types.PageProps> = ({
}}
>
<PageHead
pageId={pageId}
site={site}
title={title}
description={socialDescription}
image={socialImage}
imageObjectPosition={socialImageObjectPosition}
author={socialAuthor}
authorImage={socialAuthorImage}
detail={socialDetail}
url={canonicalPageUrl}
/>

Expand Down
25 changes: 2 additions & 23 deletions components/PageHead.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,34 +10,13 @@ export const PageHead: React.FC<
title?: string
description?: string
image?: string
imageObjectPosition?: string
author?: string
authorImage?: string
detail?: string
url?: string
}
> = ({
site,
title,
description,
image,
imageObjectPosition,
author,
authorImage,
detail,
url
}) => {
> = ({ site, title, description, pageId, image, url }) => {
title = title ?? site?.name
description = description ?? site?.description

const socialImageUrl = getSocialImageUrl({
title,
image,
imageObjectPosition,
author,
authorImage,
detail
})
const socialImageUrl = getSocialImageUrl(pageId) || image

return (
<Head>
Expand Down
51 changes: 11 additions & 40 deletions lib/get-social-image-url.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,16 @@
import { api, host } from './config'

export function getSocialImageUrl({
title,
image,
imageObjectPosition,
author,
authorImage,
detail
}: {
title: string
image?: string
imageObjectPosition?: string
author?: string
authorImage?: string
detail?: string
}) {
const url = new URL(api.getSocialImage, host)

if (title) {
url.searchParams.set('title', title)
}

if (image) {
url.searchParams.set('image', image)
}

if (imageObjectPosition) {
url.searchParams.set('imageObjectPosition', imageObjectPosition)
}

if (author) {
url.searchParams.set('author', author)
}

if (authorImage) {
url.searchParams.set('authorImage', authorImage)
}

if (detail) {
url.searchParams.set('detail', detail)
export function getSocialImageUrl(pageId: string) {
try {
const url = new URL(api.getSocialImage, host)

if (pageId) {
url.searchParams.set('id', pageId)
return url.toString()
}
} catch (err) {
console.warn('error invalid social image url', pageId, err.message)
}

return url.toString()
return null
}
6 changes: 0 additions & 6 deletions lib/preview-images.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,6 @@ import { defaultPageIcon, defaultPageCover } from './config'
import { db } from './db'
import { mapImageUrl } from './map-image-url'

// NOTE: this is just an example of how to pre-compute preview images.
// Depending on how many images you're working with, this can potentially be
// very expensive to recompute, so in production we recommend that you cache
// the preview image results in a key-value database of your choosing.
// If you're not sure where to start, check out https://github.com/jaredwray/keyv

export async function getPreviewImageMap(
recordMap: ExtendedRecordMap
): Promise<PreviewImageMap> {
Expand Down
98 changes: 79 additions & 19 deletions pages/api/social-image.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
import React from 'react'
import { withOGImage } from 'next-api-og-image'
import { interRegular } from '../../lib/fonts'

import {
getBlockTitle,
getBlockIcon,
getPageProperty,
isUrl,
parsePageId
} from 'notion-utils'
import { PageBlock } from 'notion-types'

import { notion } from 'lib/notion'
import { getSiteForDomain } from 'lib/get-site-for-domain'
import { mapImageUrl } from 'lib/map-image-url'
import * as config from 'lib/config'
import { interRegular } from 'lib/fonts'

/**
* Social image generation via headless chrome.
Expand All @@ -12,24 +26,69 @@ import { interRegular } from '../../lib/fonts'
*/
const debugInspectHtml = false

export default withOGImage<
'query',
| 'title'
| 'image'
| 'author'
| 'authorImage'
| 'detail'
| 'imageObjectPosition'
>({
export default withOGImage<'query', 'id'>({
template: {
react: ({
title,
image,
author,
authorImage,
detail,
imageObjectPosition
}) => {
react: async ({ id }) => {
const pageId = parsePageId(id)

if (!pageId) {
throw new Error('Invalid notion page id')
}

const site = await getSiteForDomain(config.domain)
const recordMap = await notion.getPage(pageId)

const keys = Object.keys(recordMap?.block || {})
const block = recordMap?.block?.[keys[0]]?.value

if (!block) {
throw new Error('Invalid recordMap for page')
}

const isBlogPost =
block.type === 'page' && block.parent_table === 'collection'
const title = getBlockTitle(block, recordMap) || site.name
const image = mapImageUrl(
getPageProperty<string>('Social Image', block, recordMap) ||
(block as PageBlock).format?.page_cover ||
config.defaultPageCover,
block
)

const imageCoverPosition =
(block as PageBlock).format?.page_cover_position ??
config.defaultPageCoverPosition
const imageObjectPosition = imageCoverPosition
? `center ${(1 - imageCoverPosition) * 100}%`
: null

const blockIcon = getBlockIcon(block, recordMap)
const authorImage = mapImageUrl(
blockIcon && isUrl(blockIcon) ? blockIcon : config.defaultPageIcon,
block
)

const author =
getPageProperty<string>('Author', block, recordMap) || config.author

// const socialDescription =
// getPageProperty<string>('Description', block, recordMap) ||
// config.description

const timePublished = getPageProperty<number>(
'Published',
block,
recordMap
)
const datePublished = timePublished ? new Date(timePublished) : undefined
const date =
isBlogPost && datePublished
? `${datePublished.toLocaleString('en-US', {
month: 'long'
})} ${datePublished.getFullYear()}`
: undefined
const detail = date || site.domain

return (
<html>
<head>
Expand Down Expand Up @@ -142,7 +201,8 @@ body {
}
.title {
font-size: 3em;
font-size: 3.2em;
line-height: 1.3;
}
.metadata {
Expand Down

0 comments on commit 0b7d618

Please sign in to comment.