mirror of
https://github.com/d0zingcat/nextjs-notion-starter-kit.git
synced 2026-05-18 07:26:43 +00:00
feat: switch to static tweets
This commit is contained in:
@@ -18,3 +18,6 @@
|
||||
|
||||
# Optional (for fathom analytics)
|
||||
#NEXT_PUBLIC_FATHOM_ID=
|
||||
|
||||
# Optional (for rendering tweets efficiently)
|
||||
TWITTER_ACCESS_TOKEN=
|
||||
|
||||
25
api/get-tweet-ast/[tweetId].ts
Normal file
25
api/get-tweet-ast/[tweetId].ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { NextApiRequest, NextApiResponse } from 'next'
|
||||
import { fetchTweetAst } from 'static-tweets'
|
||||
|
||||
export default async (
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse
|
||||
): Promise<void> => {
|
||||
if (req.method !== 'GET') {
|
||||
return res.status(405).send({ error: 'method not allowed' })
|
||||
}
|
||||
|
||||
const tweetId = req.query.tweetId as string
|
||||
|
||||
if (!tweetId) {
|
||||
return res
|
||||
.status(400)
|
||||
.send({ error: 'missing required parameter "tweetId"' })
|
||||
}
|
||||
|
||||
console.log('getTweetAst', tweetId)
|
||||
const tweetAst = await fetchTweetAst(tweetId)
|
||||
console.log('tweetAst', tweetId, tweetAst)
|
||||
|
||||
res.status(200).json(tweetAst)
|
||||
}
|
||||
@@ -9,6 +9,8 @@ import BodyClassName from 'react-body-classname'
|
||||
import useDarkMode from 'use-dark-mode'
|
||||
import { PageBlock } from 'notion-types'
|
||||
|
||||
import { Tweet, Twitter } from 'react-static-tweets'
|
||||
|
||||
// core notion renderer
|
||||
import { NotionRenderer, Code, Collection, CollectionRow } from 'react-notion-x'
|
||||
|
||||
@@ -57,12 +59,9 @@ const Equation = dynamic(() =>
|
||||
import('react-notion-x').then((notion) => notion.Equation)
|
||||
)
|
||||
|
||||
const Tweet = dynamic(
|
||||
() => import('react-notion-x').then((notion) => notion.Tweet),
|
||||
{
|
||||
ssr: false
|
||||
}
|
||||
)
|
||||
// we're now using a much lighter-weight tweet renderer react-static-tweets
|
||||
// instead of the official iframe-based embed widget from twitter
|
||||
// const Tweet = dynamic(() => import('react-tweet-embed'))
|
||||
|
||||
const Modal = dynamic(
|
||||
() => import('react-notion-x').then((notion) => notion.Modal),
|
||||
@@ -162,7 +161,15 @@ export const NotionPage: React.FC<types.PageProps> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Twitter.Provider
|
||||
value={{
|
||||
tweetAstMap: recordMap.tweetAstMap || {},
|
||||
swrOptions: {
|
||||
fetcher: (id) =>
|
||||
fetch(`/api/get-tweet-ast/${id}`).then((r) => r.json())
|
||||
}
|
||||
}}
|
||||
>
|
||||
<PageHead site={site} />
|
||||
|
||||
<Head>
|
||||
@@ -274,6 +281,6 @@ export const NotionPage: React.FC<types.PageProps> = ({
|
||||
<GitHubShareButton />
|
||||
|
||||
<CustomHtml site={site} />
|
||||
</>
|
||||
</Twitter.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ import { NotionAPI } from 'notion-client'
|
||||
import { ExtendedRecordMap, SearchParams, SearchResults } from 'notion-types'
|
||||
import { getPreviewImages } from './get-preview-images'
|
||||
import { mapNotionImageUrl } from './map-image-url'
|
||||
import { fetchTweetAst, getTweetAst } from 'static-tweets'
|
||||
import pMap from 'p-map'
|
||||
|
||||
const notion = new NotionAPI({
|
||||
apiBaseUrl: process.env.NOTION_API_BASE_URL
|
||||
@@ -47,6 +49,50 @@ export async function getPage(pageId: string): Promise<ExtendedRecordMap> {
|
||||
const previewImageMap = await getPreviewImages(urls)
|
||||
;(recordMap as any).preview_images = previewImageMap
|
||||
|
||||
const tweetIds: string[] = blockIds
|
||||
.map((blockId) => {
|
||||
const block = recordMap.block[blockId]?.value
|
||||
|
||||
if (block) {
|
||||
if (block.type === 'tweet') {
|
||||
const src = block.properties?.source?.[0]?.[0]
|
||||
|
||||
if (src) {
|
||||
const id = src.split('?')[0].split('/').pop()
|
||||
if (id) return id
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.filter(Boolean)
|
||||
|
||||
const tweetAsts = await pMap(
|
||||
tweetIds,
|
||||
async (tweetId) => {
|
||||
try {
|
||||
return {
|
||||
tweetId,
|
||||
tweetAst: await fetchTweetAst(tweetId)
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('error fetching tweet info', tweetId, err)
|
||||
}
|
||||
},
|
||||
{
|
||||
concurrency: 4
|
||||
}
|
||||
)
|
||||
|
||||
const tweetAstMap = tweetAsts.filter(Boolean).reduce(
|
||||
(acc, t) => ({
|
||||
...acc,
|
||||
[t.tweetId]: t.tweetAst
|
||||
}),
|
||||
{}
|
||||
)
|
||||
|
||||
;(recordMap as any).tweetAstMap = tweetAstMap
|
||||
|
||||
return recordMap
|
||||
}
|
||||
|
||||
|
||||
@@ -4,4 +4,8 @@ const withBundleAnalyzer = require('@next/bundle-analyzer')({
|
||||
enabled: process.env.ANALYZE === 'true'
|
||||
})
|
||||
|
||||
module.exports = withBundleAnalyzer({})
|
||||
module.exports = withBundleAnalyzer({
|
||||
images: {
|
||||
domains: ['pbs.twimg.com']
|
||||
}
|
||||
})
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
"start": "next start",
|
||||
"deploy": "vercel --prod",
|
||||
"deps": "run-s deps:*",
|
||||
"deps:update": "[ -z $GITHUB_ACTIONS ] && yarn add notion-client notion-types notion-utils react-notion-x || echo 'Skipping deps:update on CI'",
|
||||
"deps:link": "[ -z $GITHUB_ACTIONS ] && yarn link notion-client notion-types notion-utils react-notion-x || echo 'Skipping deps:link on CI'",
|
||||
"deps:update": "[ -z $GITHUB_ACTIONS ] && yarn add notion-client notion-types notion-utils react-notion-x static-tweets react-static-tweets || echo 'Skipping deps:update on CI'",
|
||||
"deps:link": "[ -z $GITHUB_ACTIONS ] && yarn link notion-client notion-types notion-utils react-notion-x static-tweets react-static-tweets || echo 'Skipping deps:link on CI'",
|
||||
"analyze": "cross-env ANALYZE=true next build",
|
||||
"analyze:server": "cross-env BUNDLE_ANALYZE=server next build",
|
||||
"analyze:browser": "cross-env BUNDLE_ANALYZE=browser next build",
|
||||
@@ -47,7 +47,9 @@
|
||||
"react-dom": "17.0.1",
|
||||
"react-icons": "^4.1.0",
|
||||
"react-notion-x": "^4.2.17",
|
||||
"react-static-tweets": "^0.2.3",
|
||||
"react-use": "^15.3.3",
|
||||
"static-tweets": "^0.2.1",
|
||||
"use-dark-mode": "^2.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -23,6 +23,9 @@ import 'styles/notion.css'
|
||||
// global style overrides for prism theme
|
||||
import 'styles/prism-theme.css'
|
||||
|
||||
// core styles for static tweet renderer
|
||||
import 'react-static-tweets/styles.css'
|
||||
|
||||
// here we're bringing in any languages we want to support for
|
||||
// syntax highlighting via Notion's Code block
|
||||
import 'prismjs'
|
||||
|
||||
@@ -22,3 +22,16 @@ body {
|
||||
.utterances {
|
||||
max-width: 100% !important;
|
||||
}
|
||||
|
||||
.static-tweet blockquote {
|
||||
margin: 0;
|
||||
margin-block-start: 0;
|
||||
margin-block-end: 0;
|
||||
margin-inline-start: 0;
|
||||
margin-inline-end: 0;
|
||||
}
|
||||
|
||||
.static-tweet-emoji {
|
||||
height: 1.2em !important;
|
||||
width: 1.2em !important;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user