Improve OG images

This commit is contained in:
Jordan Eldredge 2022-11-11 22:41:26 -08:00
parent c434225c56
commit e08ebdd21b
4 changed files with 103 additions and 104 deletions

View file

@ -1,5 +0,0 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
export default function handler(req, res) {
res.status(200).json({ name: 'John Doe' })
}

View file

@ -1,42 +1,28 @@
import { ImageResponse } from "@vercel/og";
import Frame from "../../src/og/Frame";
import { fetchGraphql, stripExt } from "../../src/og/ogUtils";
export const config = {
runtime: "experimental-edge",
};
async function fetchGraphql(query, variables) {
const response = await fetch("https://api.webampskins.org/graphql", {
headers: {
accept: "application/json",
"content-type": "application/json",
},
referrer: "https://skins.webamp.org/",
referrerPolicy: "strict-origin-when-cross-origin",
body: JSON.stringify({ query, variables }),
method: "POST",
});
if (!response.ok) {
throw new Error("Failed to fetch skin info");
}
const json = await response.json();
const { data } = json;
return data;
}
function stripExt(filename) {
return filename.replace(/\.[^/.]+$/, "");
}
export const SCREENSHOT_WIDTH = 275;
export const SCREENSHOT_HEIGHT = 348;
const QUERY = `
query Skin($md5: String!) {
skin: fetch_skin_by_md5(md5: $md5) {
filename
screenshot_url
}
}`;
const aspectRatio = SCREENSHOT_WIDTH / SCREENSHOT_HEIGHT;
export default async function (req) {
const { searchParams } = req.nextUrl;
const skinMd5 = searchParams.get("md5");
const query = searchParams.get("query");
if (query) {
return searchImage(query);
}
if (skinMd5) {
return permalinkImage(skinMd5);
}
throw new Error("Expected skin md5 or query");
}
async function searchImage(query) {
const data = await fetchGraphql(
@ -52,7 +38,6 @@ async function searchImage(query) {
}`,
{ query }
);
const aspectRatio = SCREENSHOT_WIDTH / SCREENSHOT_HEIGHT;
return new ImageResponse(
(
<Frame>
@ -111,19 +96,18 @@ async function searchImage(query) {
);
}
export default async function (req) {
const { searchParams } = req.nextUrl;
const skinMd5 = searchParams.get("md5");
const query = searchParams.get("query");
if (query) {
return searchImage(query);
}
if (skinMd5 == null) {
throw new Error("Expected skin md5");
}
const data = await fetchGraphql(QUERY, { md5: skinMd5 });
const aspectRatio = SCREENSHOT_WIDTH / SCREENSHOT_HEIGHT;
const FOO = 900;
async function permalinkImage(skinMd5) {
const data = await fetchGraphql(
`
query Skin($md5: String!) {
skin: fetch_skin_by_md5(md5: $md5) {
filename
screenshot_url
}
}`,
{ md5: skinMd5 }
);
const size = 900;
return new ImageResponse(
(
<Frame>
@ -139,12 +123,12 @@ export default async function (req) {
>
<div style={{ display: "flex", marginTop: "40" }}>
<div
style={{ display: "flex", height: FOO / 3, overflow: "hidden" }}
style={{ display: "flex", height: size / 3, overflow: "hidden" }}
>
<img
src={data.skin.screenshot_url}
height={String(FOO)}
width={String(FOO * aspectRatio)}
height={String(size)}
width={String(size * aspectRatio)}
/>
</div>
</div>
@ -171,8 +155,8 @@ export default async function (req) {
>
<img
src={data.skin.screenshot_url}
height={String(FOO / 2)}
width={String((FOO / 2) * aspectRatio)}
height={String(size / 2)}
width={String((size / 2) * aspectRatio)}
/>
</div>
</Frame>
@ -183,53 +167,3 @@ export default async function (req) {
}
);
}
function Frame({ children }) {
return (
<div
style={{
background: "black",
color: "white",
width: "100%",
height: "100%",
display: "flex",
flexDirection: "column",
textAlign: "center",
alignItems: "center",
justifyContent: "center",
justifyContent: "space-between",
background: "linear-gradient(45deg,#000,#191927 66%,#000)",
}}
>
<div
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
justifyItems: "center",
width: "100%",
flexGrow: 10,
// border: "1px solid red",
alignItems: "stretch",
}}
>
{children}
</div>
<div
style={{
fontSize: 20,
background: "linear-gradient(90deg,#111119,#282742 66%,#191927)",
color: "white",
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
padding: "20px 30px",
width: "100%",
}}
>
<div>Winamp Skin Museum</div>
<div>skins.webamp.org</div>
</div>
</div>
);
}

View file

@ -0,0 +1,48 @@
export default function Frame({ children }) {
return (
<div
style={{
background: "black",
color: "white",
width: "100%",
height: "100%",
display: "flex",
flexDirection: "column",
textAlign: "center",
alignItems: "center",
justifyContent: "center",
justifyContent: "space-between",
background: "linear-gradient(45deg,#000,#191927 66%,#000)",
}}
>
<div
style={{
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
justifyItems: "center",
width: "100%",
flexGrow: 10,
alignItems: "stretch",
}}
>
{children}
</div>
<div
style={{
fontSize: 20,
background: "linear-gradient(90deg,#111119,#282742 66%,#191927)",
color: "white",
display: "flex",
flexDirection: "row",
justifyContent: "space-between",
padding: "20px 30px",
width: "100%",
}}
>
<div>Winamp Skin Museum</div>
<div>skins.webamp.org</div>
</div>
</div>
);
}

View file

@ -0,0 +1,22 @@
export async function fetchGraphql(query, variables) {
const response = await fetch("https://api.webampskins.org/graphql", {
headers: {
accept: "application/json",
"content-type": "application/json",
},
referrer: "https://skins.webamp.org/",
referrerPolicy: "strict-origin-when-cross-origin",
body: JSON.stringify({ query, variables }),
method: "POST",
});
if (!response.ok) {
throw new Error("Failed to fetch skin info");
}
const json = await response.json();
const { data } = json;
return data;
}
export function stripExt(filename) {
return filename.replace(/\.[^/.]+$/, "");
}