1Eventually we should host all our images properly, but for now, drag and drop them here 👇
2
3* https://imagedelivery.net/iHX6Ovru0O7AjmyT5yZRoA/4d90a6f7-247c-4df4-3de6-928364e10000/public
4* https://imagedelivery.net/iHX6Ovru0O7AjmyT5yZRoA/f175100b-a190-4772-7056-04c09f273a00/public
12}) {
13 const description = post?.description ?? SITE_DESCRIPTION;
14 const ogImage = new URL("/og-image.png", BLOG_URL);
15 ogImage.searchParams.append("title", title);
16
17 return (
19 <meta charSet="UTF-8" />
20 <meta name="viewport" content="width=device-width, initial-scale=1.0" />
21 <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
22
23 <title>{title === "Val Town Blog" ? title : `${title} | Val Town Blog`}</title>
30 <meta property="og:description" content={description} />
31
32 <meta property="og:image" content={ogImage} />
33
34 {/* Twitter */}
35 <meta property="twitter:card" content="summary_large_image" />
36 <meta property="twitter:url" content={BLOG_URL} />
37 <meta property="twitter:title" content={title} />
38 <meta property="twitter:description" content={description} />
39
40 <meta property="twitter:image" content={ogImage} />
41
42 {
79 "slug": "fal",
80 "link": "/blog/fal",
81 "description": "Bringing lightning fast AI image generation to Val Town",
82 "pubDate": "Thu, 31 Oct 2024 00:00:00 GMT",
83 "author": "Steve Krouse",
13 {
14 headers: {
15 "Content-Type": "image/svg+xml",
16 },
17 },
40- Item 3
41
42### Images
43
44Images can be included using markdown syntax.
45
46## Conclusion
6---
7
8
9
10We migrated our blog to Val Town 🥳
79## A fast migration
80
81How did we migrate 65 blog posts – with images, videos, and intricate formatting and styles – to an entirely new blog in a single day?
82
83We didn't. We left them where they are, and proxy to them.
5import satori from "npm:satori";
6
7export function handleImageEndpoints(app: Hono) {
8 const headers = {
9 "Content-Type": "image/png",
10 "cache-control": "public, max-age=86400",
11 };
12 // app.get("/image", async (c) => {
13 // return c.body(await homeImage(), 200, headers);
14 // });
15 app.get("/icon", async (c) => {
16 return c.body(await iconImage(), 200, headers);
17 });
18}
19
20// export async function homeImage() {
21// return await ogImage(
22// <div tw="w-full h-full flex justify-start items-end text-[100px] bg-black text-white p-[50px]">
23// <div tw="flex flex-col items-start gap-[10px]">
31// }
32
33export async function iconImage() {
34 return await ogImage(
35 <div tw="w-full h-full flex justify-center items-center text-[100px] bg-black text-white p-[50px]">
36 <img tw="w-[350px] h-[350px]" src={base64Icon(Grid3x3)} />
45//////////
46
47export async function ogImage(body, options = {}) {
48 const svg = await satori(
49 body,
57 if (code === "emoji") {
58 const unicode = segment.codePointAt(0).toString(16).toUpperCase();
59 return `data:image/svg+xml;base64,` + btoa(await loadEmoji(unicode));
60 }
61 return "";
94 const base64 = Buffer.from(svg).toString("base64");
95 // console.log('getIconDataUrl', name, svg, base64)
96 return `data:image/svg+xml;base64,${base64}`;
97};
3export const name = "Gallery";
4// export const iconUrl = "https://imgur.com/TrJLlwp.png";
5export const ogImageUrl = "https://imgur.com/aKfqufa.png";
6
7export function embedMetadata(baseUrl: string, path: string = "/") {
9 return {
10 version: "next",
11 imageUrl: ogImageUrl,
12 button: {
13 title: pathName,
16 name: name,
17 url: baseUrl + path,
18 splashImageUrl: baseUrl + "/icon",
19 splashBackgroundColor: "#111111",
20 },
45 "iconUrl": baseUrl + "/icon",
46 "homeUrl": baseUrl,
47 "splashImageUrl": baseUrl + "/icon",
48 "splashBackgroundColor": "#111111",
49 "webhookUrl": baseUrl + "/webhook",
3import { Hono } from "npm:hono";
4
5import { embedMetadata, handleFarcasterEndpoints, name, ogImageUrl } from "./farcaster.ts";
6import { handleImageEndpoints } from "./image.tsx";
7
8const app = new Hono();
9
10handleImageEndpoints(app);
11handleFarcasterEndpoints(app);
12
38 <meta name="fc:frame" content={JSON.stringify(embedMetadata(baseUrl, path))} />
39 <link rel="icon" href={baseUrl + "/icon"} />
40 <meta property="og:image" content={ogImageUrl} />
41
42 <link rel="preconnect" href="https://fonts.googleapis.com" />
5import { handleAgoraEndpoints } from "./agora.ts";
6import { embedMetadata, handleFarcasterEndpoints, name } from "./farcaster.ts";
7import { handleImageEndpoints } from "./image.tsx";
8import { fetchGet as fetchNeynarGet } from "./neynar.ts";
9
10const app = new Hono();
11
12handleImageEndpoints(app);
13handleFarcasterEndpoints(app);
14handleAgoraEndpoints(app);
51 <meta name="fc:frame" content={JSON.stringify(embedMetadata(baseUrl, path))} />
52 <link rel="icon" href={baseUrl + "/icon"} />
53 <meta property="og:image" content={baseUrl + "/image"} />
54 </head>
55 <body class="bg-white text-black dark:bg-black dark:text-white">