og-image.tsx 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import { ImageResponse } from "next/og";
  2. import { readFile } from "node:fs/promises";
  3. import { join } from "node:path";
  4. export { getPageTitle } from "@/lib/page-titles";
  5. // Cache font data in memory after first load
  6. let fontCache: { geistRegular: Buffer } | null = null;
  7. async function loadFonts() {
  8. if (fontCache) return fontCache;
  9. const geistRegular = await readFile(
  10. join(process.cwd(), "public/Geist-Regular.ttf"),
  11. );
  12. fontCache = { geistRegular };
  13. return fontCache;
  14. }
  15. export async function renderOgImage(title: string) {
  16. const { geistRegular } = await loadFonts();
  17. return new ImageResponse(
  18. <div
  19. style={{
  20. width: "100%",
  21. height: "100%",
  22. display: "flex",
  23. flexDirection: "column",
  24. backgroundColor: "black",
  25. padding: "60px 80px",
  26. }}
  27. >
  28. <div
  29. style={{
  30. display: "flex",
  31. alignItems: "center",
  32. gap: "16px",
  33. }}
  34. >
  35. <svg width="36" height="36" viewBox="0 0 16 16" fill="white">
  36. <path fillRule="evenodd" clipRule="evenodd" d="M8 1L16 15H0L8 1Z" />
  37. </svg>
  38. <span
  39. style={{
  40. fontSize: 36,
  41. color: "#666",
  42. fontFamily: "Geist",
  43. fontWeight: 400,
  44. }}
  45. >
  46. /
  47. </span>
  48. <span
  49. style={{
  50. fontSize: 36,
  51. fontFamily: "Geist",
  52. fontWeight: 400,
  53. color: "white",
  54. }}
  55. >
  56. json-render
  57. </span>
  58. </div>
  59. <div
  60. style={{
  61. display: "flex",
  62. flex: 1,
  63. alignItems: "center",
  64. justifyContent: "center",
  65. }}
  66. >
  67. <span
  68. style={{
  69. fontSize: 72,
  70. fontFamily: "Geist",
  71. fontWeight: 400,
  72. color: "white",
  73. letterSpacing: "-0.02em",
  74. textAlign: "center",
  75. lineHeight: 1.2,
  76. }}
  77. >
  78. {title}
  79. </span>
  80. </div>
  81. </div>,
  82. {
  83. width: 1200,
  84. height: 630,
  85. fonts: [
  86. {
  87. name: "Geist",
  88. data: geistRegular.buffer as ArrayBuffer,
  89. style: "normal",
  90. weight: 400,
  91. },
  92. ],
  93. },
  94. );
  95. }