diff --git a/requirements.txt b/requirements.txt
index 83d7719..c02e578 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,4 +2,5 @@ flask
 gunicorn
 requests
 python-dotenv
-pytz
\ No newline at end of file
+pytz
+Pillow
\ No newline at end of file
diff --git a/server.py b/server.py
index 635e9be..043fe75 100644
--- a/server.py
+++ b/server.py
@@ -9,6 +9,7 @@ from flask import (
     render_template,
     send_from_directory,
     send_file,
+    Response
 )
 import os
 import json
@@ -18,6 +19,9 @@ import dotenv
 from pytz import timezone
 import pytz
 import re
+from PIL import Image, ImageDraw, ImageFont
+import io
+import urllib.parse
 
 
 dotenv.load_dotenv()
@@ -78,7 +82,20 @@ def wellknown(path):
 # region Main routes
 @app.route("/")
 def index():
-    return render_template("index.html")
+    from_tz = request.args.get('from_tz', '')
+    time = request.args.get('time', '')
+    to_tzs = request.args.get('to_tzs', '')
+    
+    # Generate the OG image URL based on the parameters
+    # Make sure to encode the parameters
+    from_tz = urllib.parse.quote(from_tz)
+    time = urllib.parse.quote(time)
+    to_tzs = urllib.parse.quote(to_tzs)
+
+
+    og_image = f"og_image?from_tz={from_tz}&time={time}&to_tzs={to_tzs}"
+    
+    return render_template("index.html", og_image=og_image)
 
 # Mapping of short timezone names to full names
 SHORT_TZ_MAP = {
@@ -193,6 +210,80 @@ def convert_multiple():
 
     return jsonify(results)
 
+@app.route("/og_image")
+def og_image():
+    from_tz = request.args.get('from_tz', 'Unknown')
+    time = request.args.get('time', 'Unknown')
+    to_tzs = request.args.get('to_tzs', 'Unknown')
+
+    # Load the background image
+    img_path = "templates/assets/img/og_image.webp"
+    img = Image.open(img_path).convert("RGBA")
+    d = ImageDraw.Draw(img)
+
+    # Convert time format to 12-hour format and add AM/PM
+    try:
+        input_time = datetime.strptime(time, "%Y-%m-%dT%H:%M:%S")
+    except ValueError:
+        input_time = datetime.strptime(time, "%Y-%m-%dT%H:%M")
+    time = input_time.strftime("%I:%M %p")
+
+
+
+    # Prepare text
+    text = f"{time} {from_tz.replace("_","/")}"
+
+    from_tz = get_full_timezone(from_tz.replace("_", "/"))
+
+    # Check if multiple timezones are provided
+    if "," in to_tzs:
+        to_tzs = to_tzs.split(",")
+        to_tz_list = [(tz, get_full_timezone(tz.replace("_", "/"))) for tz in to_tzs if len(tz) > 0]
+    else:
+        to_tz_list = [(to_tzs, get_full_timezone(to_tzs.replace("_", "/")))]
+
+    if from_tz is None or any(tz[1] is None for tz in to_tz_list):
+        return send_from_directory("templates/assets/img", "og_image.webp")
+
+    
+
+    for tz in to_tz_list:
+        to_tz = tz[1]
+        to_tz_time = from_tz.localize(input_time).astimezone(to_tz)
+        text += f"\n{to_tz_time.strftime('%I:%M %p')} {tz[0].replace('_','/')}"
+        
+        
+
+    font_path = "/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf"
+    font_size = 200
+    # Shrink font size if text is too long
+    if (max(len(line) for line in text.split("\n")) > 13):
+        font_size = 150
+    
+    font_size -= (len(text.split("\n")) - 4) * 10
+    
+
+
+    font = ImageFont.truetype(font_path, font_size)
+
+    text_bbox = d.textbbox((0, 0), text, font=font)
+    text_width = text_bbox[2] - text_bbox[0]
+    text_height = text_bbox[3] - text_bbox[1]
+
+    # Calculate text position
+    x = (img.width - text_width) / 2
+    y = (img.height - text_height) / 2
+
+    # Add text to the image
+    d.text((x, y), text, fill=(255, 255, 255), font=font, align="center")
+
+    # Save the image to a BytesIO object in WebP format
+    img_io = io.BytesIO()
+    img.save(img_io, 'WEBP')
+    img_io.seek(0)
+
+    return Response(img_io, mimetype='image/webp')
+
 @app.route("/<path:path>")
 def catch_all(path: str):
     if os.path.isfile("templates/" + path):
diff --git a/templates/assets/img/og_image.webp b/templates/assets/img/og_image.webp
new file mode 100644
index 0000000..a6cc74e
Binary files /dev/null and b/templates/assets/img/og_image.webp differ
diff --git a/templates/index.html b/templates/index.html
index a1610af..1993ddb 100644
--- a/templates/index.html
+++ b/templates/index.html
@@ -7,6 +7,22 @@
     <title>Time Converter</title>
     <link rel="icon" href="/assets/img/favicon.png" type="image/png">
     <link rel="stylesheet" href="/assets/css/index.css">
+    <!-- og meta -->
+    <meta property="og:type" value="website" />
+    <meta property="og:title" value="Timezone Converter" />
+    <meta property="og:description" value="Convert between timezone | Nathan.Woodburn/" />
+    <meta property="og:url" value="https://time.c.woodburn.au" />
+    <meta property="og:image" value="https://time.c.woodburn.au/{{ og_image }}" />
+    <meta property="og:image:alt" value="Convert between timezone image" />
+
+    <!-- twitter meta -->
+    <meta name="twitter:card" value="summary" />
+    <meta name="twitter:site" value="@woodburn_nathan" />
+    <meta name="twitter:creator" value="@woodburn_nathan" />
+    <meta name="twitter:title" value="Timezone Converter" />
+    <meta name="twitter:description" value="Convert between timezone | Nathan.Woodburn/" />
+    <meta name="twitter:image" value="/{{ og_image }}" />
+    <meta name="twitter:image:alt" value="Convert between timezone image" />
 </head>
 
 <body>