my blog https://overreacted.io

try to add og (#845)

* try to add og

* oops

authored by danabra.mov and committed by GitHub 78099db6 2bb73b0b

+17
app/[slug]/opengraph-image.tsx
··· 1 + import { readFile } from "node:fs/promises"; 2 + import matter from "gray-matter"; 3 + import { size, contentType, generatePostImage } from "../../og/generateImage"; 4 + 5 + export const dynamic = "force-static"; 6 + export const alt = "Overreacted"; 7 + export { size, contentType }; 8 + 9 + export default async function Image({ params }) { 10 + const { slug } = await params; 11 + const filename = "./public/" + slug + "/index.md"; 12 + const file = await readFile(filename, "utf8"); 13 + const { data } = matter(file); 14 + return generatePostImage({ title: data.title }); 15 + } 16 + 17 + export { generateStaticParams } from "./page";
+4
app/layout.js
··· 4 4 import { serif } from "./fonts"; 5 5 import "./global.css"; 6 6 7 + export const metadata = { 8 + metadataBase: new URL("https://overreacted.io"), 9 + }; 10 + 7 11 export default function RootLayout({ children }) { 8 12 return ( 9 13 <html lang="en" className={serif.className}>
+9
app/opengraph-image.tsx
··· 1 + import { size, contentType, generateHomeImage } from "../og/generateImage"; 2 + 3 + export const dynamic = "force-static"; 4 + export const alt = "Overreacted"; 5 + export { size, contentType }; 6 + 7 + export default async function Image() { 8 + return generateHomeImage(); 9 + }
og/Merriweather-Italic.ttf

This is a binary file and will not be displayed.

og/Merriweather-Regular.ttf

This is a binary file and will not be displayed.

og/Montserrat-ExtraBold.ttf

This is a binary file and will not be displayed.

+174
og/generateImage.js
··· 1 + import { ImageResponse } from "next/og"; 2 + import { readFile } from "node:fs/promises"; 3 + import { join } from "node:path"; 4 + 5 + export const size = { 6 + width: 1200, 7 + height: 630, 8 + }; 9 + 10 + export const contentType = "image/png"; 11 + 12 + export async function generateHomeImage() { 13 + return generateImage( 14 + <div 15 + style={{ 16 + display: "flex", 17 + width: "100%", 18 + height: "100%", 19 + backgroundColor: "rgb(40, 44, 53)", 20 + color: "white", 21 + }} 22 + > 23 + <div 24 + style={{ 25 + display: "flex", 26 + fontSize: 150, 27 + width: "100%", 28 + height: "100%", 29 + flexDirection: "column", 30 + justifyContent: "center", 31 + alignItems: "center", 32 + gap: 80, 33 + }} 34 + > 35 + <span 36 + style={{ 37 + backgroundImage: "linear-gradient(45deg, #ffb3d8, #cbb6ff)", 38 + backgroundClip: "text", 39 + WebkitBackgroundClip: "text", 40 + color: "transparent", 41 + }} 42 + > 43 + overreacted 44 + </span> 45 + <span 46 + style={{ 47 + fontFamily: "Merriweather", 48 + fontStyle: "italic", 49 + fontSize: 60, 50 + alignItems: "center", 51 + }} 52 + > 53 + by 54 + <img 55 + alt="Dan Abramov" 56 + src="https://github.com/gaearon.png" 57 + style={{ 58 + height: 120, 59 + width: 120, 60 + borderRadius: "50%", 61 + marginLeft: 20, 62 + }} 63 + /> 64 + </span> 65 + </div> 66 + </div>, 67 + ); 68 + } 69 + 70 + export async function generatePostImage({ title }) { 71 + return generateImage( 72 + <div 73 + style={{ 74 + padding: 40, 75 + display: "flex", 76 + flexDirection: "column", 77 + width: "100%", 78 + height: "100%", 79 + backgroundColor: "rgb(40, 44, 53)", 80 + color: "white", 81 + }} 82 + > 83 + <div 84 + style={{ 85 + display: "flex", 86 + fontSize: 40, 87 + width: "100%", 88 + justifyContent: "space-between", 89 + alignItems: "center", 90 + paddingBottom: 20, 91 + }} 92 + > 93 + <span 94 + style={{ 95 + backgroundImage: "linear-gradient(45deg, #ffb3d8, #cbb6ff)", 96 + backgroundClip: "text", 97 + WebkitBackgroundClip: "text", 98 + color: "transparent", 99 + fontSize: 60, 100 + }} 101 + > 102 + overreacted 103 + </span> 104 + <span 105 + style={{ 106 + fontFamily: "Merriweather", 107 + fontStyle: "italic", 108 + fontSize: 35, 109 + alignItems: "center", 110 + }} 111 + > 112 + by 113 + <img 114 + alt="Dan Abramov" 115 + src="https://github.com/gaearon.png" 116 + style={{ 117 + height: 80, 118 + width: 80, 119 + borderRadius: "50%", 120 + marginLeft: 20, 121 + }} 122 + /> 123 + </span> 124 + </div> 125 + <div 126 + style={{ 127 + fontSize: 90, 128 + display: "flex", 129 + alignItems: "center", 130 + flex: 1, 131 + paddingBottom: 30, 132 + }} 133 + > 134 + {title} 135 + </div> 136 + </div>, 137 + ); 138 + } 139 + 140 + async function generateImage(jsx) { 141 + return new ImageResponse(jsx, { 142 + ...size, 143 + fonts: [ 144 + { 145 + name: "Montserrat", 146 + data: await montserratExtraBold, 147 + style: "normal", 148 + weight: 900, 149 + }, 150 + { 151 + name: "Merriweather", 152 + data: await merriweatherRegular, 153 + style: "normal", 154 + weight: 500, 155 + }, 156 + { 157 + name: "Merriweather", 158 + data: await merriweatherItalic, 159 + style: "italic", 160 + weight: 500, 161 + }, 162 + ], 163 + }); 164 + } 165 + 166 + const montserratExtraBold = readFile( 167 + join(process.cwd(), "og/Montserrat-ExtraBold.ttf"), 168 + ); 169 + const merriweatherRegular = readFile( 170 + join(process.cwd(), "og/Merriweather-Regular.ttf"), 171 + ); 172 + const merriweatherItalic = readFile( 173 + join(process.cwd(), "og/Merriweather-Italic.ttf"), 174 + );