91 return new Response(svg.toString(), {
92 headers: {
93 "Content-Type": "image/svg+xml",
94 "Cache-Control": "no cache",
95 },
114 return new Response(svg.toString(), {
115 headers: {
116 "Content-Type": "image/svg+xml",
117 "Cache-Control": "no cache",
118 },
144 return new Response(svg.toString(), {
145 headers: {
146 "Content-Type": "image/svg+xml",
147 "Cache-Control": "max-age=86400",
148 },
152app.get("/raw", (c) => {
153 const baseUrl = c.req.query("baseUrl") ?? DEFAULT_BASE_URL;
154 const imageSize = parseInt(c.req.query("imageSize") ?? "40", 10);
155 const redirect = c.req.query("redirect");
156
196 return (
197 <a key={x} href={paintUrl.toString()}>
198 <img src={pixelUrl} width={imageSize} />
199 </a>
200 );
88 appName: 'ValPush',
89 appIconUrl: '${iconURL}',
90 assetUrl: 'https://cdn.jsdelivr.net/gh/philfung/add-to-homescreen@1.9/dist/assets/img/', // Link to directory of library image assets.
91 maxModalDisplayCount: -1
92});
30 - **`proxy.ts`**: Proxy to the old blog for legacy content
31 - **`rss.ts`**: RSS feed generation
32 - **`favicon.ts`** & **`og-image.ts`**: Asset routes
33- **`/utils/`**: Utility functions for post processing, caching, etc.
34- **`/posts/`**: Markdown files for blog posts
69- Tables
70- Lists
71- Images
72- And other standard markdown features
73
91- Efficient proxy for legacy content
92- Minimal CSS with no external frameworks
93- Optimized image handling
94
95## Deployment
4const LINE_HEIGHT = 72;
5
6export default function OGImage({
7 title = "Val Town Blog",
8 ...props
3import { Hono } from "https://esm.sh/hono@3.12.0";
4import { renderToStaticMarkup } from "https://esm.sh/react-dom@18.2.0/server";
5import OGImage from "../components/OGImage.tsx";
6
7const app = new Hono();
10 const title = c.req.query("title");
11 const format = c.req.query("format");
12 const svg = renderToStaticMarkup(<OGImage title={title} />);
13
14 if (format === "svg") {
15 return new Response(svg, {
16 headers: {
17 "Content-Type": "image/svg+xml",
18 },
19 });
24 return new Response(png, {
25 headers: {
26 "Content-Type": "image/png",
27 "Content-Length": png.length.toString(),
28 },
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>
33 <meta property="og:description" content={description} />
34
35 <meta property="og:image" content={ogImage} />
36
37 {/* Twitter */}
38 <meta property="twitter:card" content="summary_large_image" />
39 <meta property="twitter:url" content={BLOG_URL} />
40 <meta property="twitter:title" content={title} />
41 <meta property="twitter:description" content={description} />
42
43 <meta property="twitter:image" content={ogImage} />
44
45 {
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