56 "Speed Optimization",
57 "Code Minification",
58 "Image Optimization",
59 "Caching Strategies"
60 ]
37
38 <div className="grid lg:grid-cols-2 gap-12 items-center mb-16">
39 {/* Left Column - Image and Info */}
40 <div>
41 <div className="relative">
22 <div className="container mx-auto px-6 text-center relative z-10">
23 <div className="max-w-4xl mx-auto">
24 {/* Profile Image */}
25 <div className="mb-8">
26 <div className="w-32 h-32 mx-auto rounded-full bg-white/20 backdrop-blur-sm border-4 border-white/30 flex items-center justify-center text-6xl animate-float">
9
10 <!-- Favicon -->
11 <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>💼</text></svg>">
12
13 <!-- TailwindCSS -->
4 category: 'web-development' | 'web-design' | 'graphic-design';
5 description: string;
6 imageUrl: string;
7 technologies?: string[];
8 projectUrl?: string;
44 - **`proxy.ts`**: Proxy to the old blog for legacy content
45 - **`rss.ts`**: RSS feed generation
46 - **`favicon.ts`** & **`og-image.ts`**: Asset routes
47- **`/utils/`**: Utility functions for post processing, caching, etc.
48- **`/posts/`**: Markdown files for blog posts
84- Tables
85- Lists
86- Images
87- And other standard markdown features
88
118- Efficient proxy for legacy content
119- Minimal CSS with no external frameworks
120- Optimized image handling
121
122## Deployment
13}) {
14 const description = post?.description ?? SITE_DESCRIPTION;
15 const ogImage = new URL("/og-image.png", BLOG_URL);
16 ogImage.searchParams.append("title", title);
17
18 return (
20 <meta charSet="UTF-8" />
21 <meta name="viewport" content="width=device-width, initial-scale=1.0" />
22 <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
23
24 <title>{title === "Val Town Blog" ? title : `${title} | Val Town Blog`}</title>
34 <meta property="og:description" content={description} />
35
36 <meta property="og:image" content={ogImage} />
37
38 {/* Twitter */}
39 <meta property="twitter:card" content="summary_large_image" />
40 <meta property="twitter:url" content={BLOG_URL} />
41 <meta property="twitter:title" content={title} />
42 <meta property="twitter:description" content={description} />
43
44 <meta property="twitter:image" content={ogImage} />
45
46 {
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 },
4import faviconRoute from "./routes/favicon.ts";
5import homeRoutes from "./routes/home.ts";
6import ogImageRoute from "./routes/og-image.ts";
7import proxyRoutes from "./routes/proxy.ts";
8import rssRoute from "./routes/rss.ts";
28app.route("/rss.xml", rssRoute);
29app.route("/favicon.svg", faviconRoute);
30app.route("/og-image.png", ogImageRoute);
31app.route("/", blogRoutes);
32