]> git.otsuka.systems Git - cotsuka.github.io/commitdiff
upgrade to astro 5.12, add og images for reviews and links, remove excessive console log
authorCameron Otsuka <cameron@otsuka.haus>
Fri, 8 Aug 2025 20:36:54 +0000 (13:36 -0700)
committerCameron Otsuka <cameron@otsuka.haus>
Fri, 8 Aug 2025 20:36:54 +0000 (13:36 -0700)
bun.lock
package.json
src/components/ratingdistribution/chart.tsx
src/pages/links/[date]-[id]/index.astro [moved from src/pages/links/[date]-[id].astro with 100% similarity]
src/pages/links/[date]-[id]/opengraph.png.ts [new file with mode: 0644]
src/pages/reviews/[date]-[id]/index.astro [moved from src/pages/reviews/[date]-[id].astro with 100% similarity]
src/pages/reviews/[date]-[id]/opengraph.png.ts [new file with mode: 0644]

index bf6d68b18011cb53513892f5398c578c0a97ffe2..7bf8118b73bf9d06f4457fe6b59897455e4435dd 100644 (file)
--- a/bun.lock
+++ b/bun.lock
@@ -13,7 +13,7 @@
         "@types/react": "^19.1.9",
         "@types/react-dom": "^19.1.7",
         "@vercel/og": "^0.6.8",
-        "astro": "5.11.0",
+        "astro": "5.12.9",
         "react": "^19.1.1",
         "react-dom": "^19.1.1",
         "recharts": "^3.1.0",
@@ -28,7 +28,7 @@
 
     "@astrojs/compiler": ["@astrojs/compiler@2.12.2", "", {}, "sha512-w2zfvhjNCkNMmMMOn5b0J8+OmUaBL1o40ipMvqcG6NRpdC+lKxmTi48DT8Xw0SzJ3AfmeFLB45zXZXtmbsjcgw=="],
 
-    "@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.6.1", "", {}, "sha512-l5Pqf6uZu31aG+3Lv8nl/3s4DbUzdlxTWDof4pEpto6GUJNhhCbelVi9dEyurOVyqaelwmS9oSyOWOENSfgo9A=="],
+    "@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.7.1", "", {}, "sha512-7dwEVigz9vUWDw3nRwLQ/yH/xYovlUA0ZD86xoeKEBmkz9O6iELG1yri67PgAPW6VLL/xInA4t7H0CK6VmtkKQ=="],
 
     "@astrojs/markdown-remark": ["@astrojs/markdown-remark@6.3.5", "", { "dependencies": { "@astrojs/internal-helpers": "0.7.1", "@astrojs/prism": "3.3.0", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "hast-util-to-text": "^4.0.2", "import-meta-resolve": "^4.1.0", "js-yaml": "^4.1.0", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", "rehype-stringify": "^10.0.1", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", "remark-smartypants": "^3.0.2", "shiki": "^3.2.1", "smol-toml": "^1.3.4", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.1", "vfile": "^6.0.3" } }, "sha512-MiR92CkE2BcyWf3b86cBBw/1dKiOH0qhLgXH2OXA6cScrrmmks1Rr4Tl0p/lFpvmgQQrP54Pd1uidJfmxGrpWQ=="],
 
 
     "astring": ["astring@1.9.0", "", { "bin": { "astring": "bin/astring" } }, "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg=="],
 
-    "astro": ["astro@5.11.0", "", { "dependencies": { "@astrojs/compiler": "^2.12.2", "@astrojs/internal-helpers": "0.6.1", "@astrojs/markdown-remark": "6.3.2", "@astrojs/telemetry": "3.3.0", "@capsizecss/unpack": "^2.4.0", "@oslojs/encoding": "^1.1.0", "@rollup/pluginutils": "^5.1.4", "acorn": "^8.14.1", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", "boxen": "8.0.1", "ci-info": "^4.2.0", "clsx": "^2.1.1", "common-ancestor-path": "^1.0.1", "cookie": "^1.0.2", "cssesc": "^3.0.0", "debug": "^4.4.0", "deterministic-object-hash": "^2.0.2", "devalue": "^5.1.1", "diff": "^5.2.0", "dlv": "^1.1.3", "dset": "^3.1.4", "es-module-lexer": "^1.6.0", "esbuild": "^0.25.0", "estree-walker": "^3.0.3", "flattie": "^1.1.1", "fontace": "~0.3.0", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", "http-cache-semantics": "^4.1.1", "import-meta-resolve": "^4.1.0", "js-yaml": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.17", "magicast": "^0.3.5", "mrmime": "^2.0.1", "neotraverse": "^0.6.18", "p-limit": "^6.2.0", "p-queue": "^8.1.0", "package-manager-detector": "^1.1.0", "picomatch": "^4.0.2", "prompts": "^2.4.2", "rehype": "^13.0.2", "semver": "^7.7.1", "shiki": "^3.2.1", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.12", "tsconfck": "^3.1.5", "ultrahtml": "^1.6.0", "unifont": "~0.5.0", "unist-util-visit": "^5.0.0", "unstorage": "^1.15.0", "vfile": "^6.0.3", "vite": "^6.3.4", "vitefu": "^1.0.6", "xxhash-wasm": "^1.1.0", "yargs-parser": "^21.1.1", "yocto-spinner": "^0.2.1", "zod": "^3.24.2", "zod-to-json-schema": "^3.24.5", "zod-to-ts": "^1.2.0" }, "optionalDependencies": { "sharp": "^0.33.3" }, "bin": { "astro": "astro.js" } }, "sha512-MEICntERthUxJPSSDsDiZuwiCMrsaYy3fnDhp4c6ScUfldCB8RBnB/myYdpTFXpwYBy6SgVsHQ1H4MuuA7ro/Q=="],
+    "astro": ["astro@5.12.9", "", { "dependencies": { "@astrojs/compiler": "^2.12.2", "@astrojs/internal-helpers": "0.7.1", "@astrojs/markdown-remark": "6.3.5", "@astrojs/telemetry": "3.3.0", "@capsizecss/unpack": "^2.4.0", "@oslojs/encoding": "^1.1.0", "@rollup/pluginutils": "^5.1.4", "acorn": "^8.14.1", "aria-query": "^5.3.2", "axobject-query": "^4.1.0", "boxen": "8.0.1", "ci-info": "^4.2.0", "clsx": "^2.1.1", "common-ancestor-path": "^1.0.1", "cookie": "^1.0.2", "cssesc": "^3.0.0", "debug": "^4.4.0", "deterministic-object-hash": "^2.0.2", "devalue": "^5.1.1", "diff": "^5.2.0", "dlv": "^1.1.3", "dset": "^3.1.4", "es-module-lexer": "^1.6.0", "esbuild": "^0.25.0", "estree-walker": "^3.0.3", "flattie": "^1.1.1", "fontace": "~0.3.0", "github-slugger": "^2.0.0", "html-escaper": "3.0.3", "http-cache-semantics": "^4.1.1", "import-meta-resolve": "^4.1.0", "js-yaml": "^4.1.0", "kleur": "^4.1.5", "magic-string": "^0.30.17", "magicast": "^0.3.5", "mrmime": "^2.0.1", "neotraverse": "^0.6.18", "p-limit": "^6.2.0", "p-queue": "^8.1.0", "package-manager-detector": "^1.1.0", "picomatch": "^4.0.2", "prompts": "^2.4.2", "rehype": "^13.0.2", "semver": "^7.7.1", "shiki": "^3.2.1", "smol-toml": "^1.3.4", "tinyexec": "^0.3.2", "tinyglobby": "^0.2.12", "tsconfck": "^3.1.5", "ultrahtml": "^1.6.0", "unifont": "~0.5.0", "unist-util-visit": "^5.0.0", "unstorage": "^1.15.0", "vfile": "^6.0.3", "vite": "^6.3.4", "vitefu": "^1.0.6", "xxhash-wasm": "^1.1.0", "yargs-parser": "^21.1.1", "yocto-spinner": "^0.2.1", "zod": "^3.24.4", "zod-to-json-schema": "^3.24.5", "zod-to-ts": "^1.2.0" }, "optionalDependencies": { "sharp": "^0.33.3" }, "bin": { "astro": "astro.js" } }, "sha512-cZ7kZ61jyE5nwSrFKSRyf5Gds+uJELqQxJFqMkcgiWQvhWZJUSShn8Uz3yc9WLyLw5Kim5P5un9SkJSGogfEZQ=="],
 
     "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="],
 
 
     "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="],
 
-    "@astrojs/markdown-remark/@astrojs/internal-helpers": ["@astrojs/internal-helpers@0.7.1", "", {}, "sha512-7dwEVigz9vUWDw3nRwLQ/yH/xYovlUA0ZD86xoeKEBmkz9O6iELG1yri67PgAPW6VLL/xInA4t7H0CK6VmtkKQ=="],
-
     "@babel/core/@babel/parser": ["@babel/parser@7.27.7", "", { "dependencies": { "@babel/types": "^7.27.7" }, "bin": "./bin/babel-parser.js" }, "sha512-qnzXzDXdr/po3bOTbTIQZ7+TxNKxpkN5IifVLXS+r7qwynkZfPyjZfE7hCXbo7IoO9TNcSyibgONsf2HauUd3Q=="],
 
     "@babel/core/@babel/types": ["@babel/types@7.27.7", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-8OLQgDScAOHXnAz2cV+RfzzNMipuLVBz2biuAJFMV9bfkNf393je3VM8CLkjQodW5+iWsSJdSgSWT6rsZoXHPw=="],
 
     "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
 
-    "astro/@astrojs/markdown-remark": ["@astrojs/markdown-remark@6.3.2", "", { "dependencies": { "@astrojs/internal-helpers": "0.6.1", "@astrojs/prism": "3.3.0", "github-slugger": "^2.0.0", "hast-util-from-html": "^2.0.3", "hast-util-to-text": "^4.0.2", "import-meta-resolve": "^4.1.0", "js-yaml": "^4.1.0", "mdast-util-definitions": "^6.0.0", "rehype-raw": "^7.0.0", "rehype-stringify": "^10.0.1", "remark-gfm": "^4.0.1", "remark-parse": "^11.0.0", "remark-rehype": "^11.1.2", "remark-smartypants": "^3.0.2", "shiki": "^3.2.1", "smol-toml": "^1.3.1", "unified": "^11.0.5", "unist-util-remove-position": "^5.0.0", "unist-util-visit": "^5.0.0", "unist-util-visit-parents": "^6.0.1", "vfile": "^6.0.3" } }, "sha512-bO35JbWpVvyKRl7cmSJD822e8YA8ThR/YbUsciWNA7yTcqpIAL2hJDToWP5KcZBWxGT6IOdOkHSXARSNZc4l/Q=="],
-
     "brotli/base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="],
 
     "hast-util-to-parse5/property-information": ["property-information@6.5.0", "", {}, "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig=="],
index 6f56c77465ef2b13e82037409283bfb35b4cfa44..956b5c4e8b899056d58f7589f09db4669bfdf8d1 100644 (file)
@@ -29,7 +29,7 @@
     "@types/react": "^19.1.9",
     "@types/react-dom": "^19.1.7",
     "@vercel/og": "^0.6.8",
-    "astro": "5.11.0",
+    "astro": "5.12.9",
     "react": "^19.1.1",
     "react-dom": "^19.1.1",
     "recharts": "^3.1.0"
index e9d5f9b6512001fb263433ef544df7d359fa9cf5..e3fbe309b7d71720061232d6a631c0337f447145 100644 (file)
@@ -1,7 +1,6 @@
 import { BarChart, Bar, XAxis, YAxis, CartesianGrid, ResponsiveContainer, Tooltip } from 'recharts';
 
 export default function Chart({ chartData }) {
-    console.log(chartData);
     return (
         <ResponsiveContainer width="100%" height={150}>
             <BarChart data={chartData}>
diff --git a/src/pages/links/[date]-[id]/opengraph.png.ts b/src/pages/links/[date]-[id]/opengraph.png.ts
new file mode 100644 (file)
index 0000000..7da9516
--- /dev/null
@@ -0,0 +1,107 @@
+import type { APIRoute } from 'astro';
+import { getCollection } from 'astro:content';
+import { formatDate } from '@utils/format.ts';
+import { ImageResponse } from '@vercel/og';
+import SiteMetadata from '@data/metadata.json';
+
+export async function getStaticPaths() {
+    const links = await getCollection('links');
+    return links.map(article => ({
+        params: { date: formatDate(article.data.date), id: article.id },
+        props: { article },
+    }));
+};
+
+async function loadFont() {
+    const url = `https://cdn.jsdelivr.net/fontsource/fonts/public-sans@latest/latin-400-normal.ttf`
+    const font = await fetch(url);
+    if (font) {
+        return await font.arrayBuffer();
+    }
+    throw new Error('failed to load font data');
+};
+
+export const GET: APIRoute = async ({ props }) => {
+    const element = {
+        type: 'div',
+        props: {
+            style: {
+                display: 'flex',
+                flexDirection: 'column',
+                justifyContent: 'center',
+                alignItems: 'center',
+                backgroundColor: '#555555',
+                color: '#ffffff',
+                width: '100%',
+                height: '100%',
+                padding: 80,
+                fontFamily: 'Public Sans Variable',
+            },
+            children: [
+                {
+                    type: 'h1',
+                    props: {
+                        style: {
+                            fontSize: 64,
+                            fontWeight: 600,
+                            marginBottom: 20,
+                        },
+                        children: props.article.data.title,
+                    },
+                },
+                {
+                    type: 'p',
+                    props: {
+                        style: {
+                            fontSize: 32,
+                            marginBottom: 40,
+                        },
+                        children: props.article.data.description,
+                    },
+                },
+                {
+                    type: 'div',
+                    props: {
+                        style: {
+                            marginTop: 'auto',
+                            textTransform: 'uppercase',
+                            fontSize: 20,
+                            fontWeight: 500,
+                            letterSpacing: '0.1em',
+                            display: 'flex',
+                            flexDirection: 'column',
+                            justifyContent: 'center',
+                            alignItems: 'center',
+                        },
+                        children: [
+                            {
+                                type: 'div',
+                                props: {
+                                    style: {
+                                        borderTop: '2px solid #ffffff',
+                                        width: 240,
+                                        margin: '0 auto 8px',
+                                        display: 'flex',
+                                        textAlign: 'center'
+                                    },
+                                },
+                            },
+                            SiteMetadata.author.name,
+                        ],
+                    },
+                },
+            ],
+        },
+    }
+    return new ImageResponse(element, {
+        width: 1200,
+        height: 630,
+        fonts: [
+            {
+                name: 'Public Sans Variable',
+                data: await loadFont(),
+                style: 'normal'
+            }
+        ]
+    });
+};
\ No newline at end of file
diff --git a/src/pages/reviews/[date]-[id]/opengraph.png.ts b/src/pages/reviews/[date]-[id]/opengraph.png.ts
new file mode 100644 (file)
index 0000000..59bb8a8
--- /dev/null
@@ -0,0 +1,107 @@
+import type { APIRoute } from 'astro';
+import { getCollection } from 'astro:content';
+import { formatDate } from '@utils/format.ts';
+import { ImageResponse } from '@vercel/og';
+import SiteMetadata from '@data/metadata.json';
+
+export async function getStaticPaths() {
+    const reviews = await getCollection('reviews');
+    return reviews.map(article => ({
+        params: { date: formatDate(article.data.date), id: article.id },
+        props: { article },
+    }));
+};
+
+async function loadFont() {
+    const url = `https://cdn.jsdelivr.net/fontsource/fonts/public-sans@latest/latin-400-normal.ttf`
+    const font = await fetch(url);
+    if (font) {
+        return await font.arrayBuffer();
+    }
+    throw new Error('failed to load font data');
+};
+
+export const GET: APIRoute = async ({ props }) => {
+    const element = {
+        type: 'div',
+        props: {
+            style: {
+                display: 'flex',
+                flexDirection: 'column',
+                justifyContent: 'center',
+                alignItems: 'center',
+                backgroundColor: '#555555',
+                color: '#ffffff',
+                width: '100%',
+                height: '100%',
+                padding: 80,
+                fontFamily: 'Public Sans Variable',
+            },
+            children: [
+                {
+                    type: 'h1',
+                    props: {
+                        style: {
+                            fontSize: 64,
+                            fontWeight: 600,
+                            marginBottom: 20,
+                        },
+                        children: props.article.data.title,
+                    },
+                },
+                {
+                    type: 'p',
+                    props: {
+                        style: {
+                            fontSize: 32,
+                            marginBottom: 40,
+                        },
+                        children: props.article.data.description,
+                    },
+                },
+                {
+                    type: 'div',
+                    props: {
+                        style: {
+                            marginTop: 'auto',
+                            textTransform: 'uppercase',
+                            fontSize: 20,
+                            fontWeight: 500,
+                            letterSpacing: '0.1em',
+                            display: 'flex',
+                            flexDirection: 'column',
+                            justifyContent: 'center',
+                            alignItems: 'center',
+                        },
+                        children: [
+                            {
+                                type: 'div',
+                                props: {
+                                    style: {
+                                        borderTop: '2px solid #ffffff',
+                                        width: 240,
+                                        margin: '0 auto 8px',
+                                        display: 'flex',
+                                        textAlign: 'center'
+                                    },
+                                },
+                            },
+                            SiteMetadata.author.name,
+                        ],
+                    },
+                },
+            ],
+        },
+    }
+    return new ImageResponse(element, {
+        width: 1200,
+        height: 630,
+        fonts: [
+            {
+                name: 'Public Sans Variable',
+                data: await loadFont(),
+                style: 'normal'
+            }
+        ]
+    });
+};
\ No newline at end of file