# Open Graph Image Generator by [SavvyCal](https://savvycal.com/?utm_source=github&utm_medium=oss&utm_campaign=og-image) `og-image` is a web service for generating [Open Graph images](https://opengraphprotocol.org/) for your webpages. This project was originally inspired by [Vercel OG image](https://github.com/vercel/og-image), with some additional features: ✅ Extensible templating system \ ✅ [Tailwind CSS](https://tailwindcss.com/) for styling image templates \ ✅ Emoji support \ ✅ Caching \ ✅ Ready for deployment to [Fly](https://fly.io/) The result: beautiful open graph images like this one, generated from custom HTML/CSS templates! ![OG image example](https://og-image.savvycal.com/image?template=simple_green&text=The+fresh+way+to+find+a+time+to+meet.) Source: https://og-image.savvycal.com/image?template=simple_green&text=The+fresh+way+to+find+a+time+to+meet. ## Getting started Fork this repository and clone it locally. You'll need the following prerequisites installed: - [Elixir](https://elixir-lang.org/install.html) - [Google Chrome](https://www.google.com/chrome/index.html) - [Node.js (22.x or later)](https://github.com/nvm-sh/nvm#installing-and-updating) Run the bootstrap script to install dependencies: ```bash script/bootstrap ``` Then, run the following to boot the server: ```bash script/server ``` Visit [http://localhost:4000/image?template=light&text=Hello+World!](http://localhost:4000/image?template=light&text=Hello+World!) to see it in action! ## Creating your own templates This projects contains `light` and `dark` templates that display a logo and some user-supplied text. These are just a starting point to give you a sense for how it works. Adding new templates and modifying existing ones is easy! To get started, open the [`OgImageWeb.ImageController`](https://github.com/svycal/og-image/blob/main/lib/og_image_web/controllers/image_controller.ex) file. ```elixir defmodule OgImageWeb.ImageController do use OgImageWeb, :controller import OgImageWeb.ImageHelpers import OgImageWeb.ImageRenderer # Match on the `template` param to decide which template to render. The # `render_image` function is a special helper that either renders the PNG # (when path is `/image`) or renders the HTML (when path is `/preview`). def show(conn, %{"template" => "light", "text" => text}) do conn |> assign(:text, prepare_html(text)) |> render_image(:light) end def show(conn, %{"template" => "dark", "text" => text}) do conn |> assign(:text, prepare_html(text)) |> render_image(:dark) end # -- Add more templates here -- def show(conn, _params) do render_image(conn, :fallback) end end ``` The template markup is defined in the [`OgImageWeb.ImageHTML`](https://github.com/svycal/og-image/blob/main/lib/og_image_web/controllers/image_html.ex) module. ```elixir defmodule OgImageWeb.ImageHTML do use OgImageWeb, :html @doc """ A logo and text on a light background. """ def light(assigns) do ~H"""
<.savvycal_logo />

<%= @text %>

""" end # -- truncated for brevity -- end ``` These templates are wired up for Tailwind CSS by default. You're welcome to define reuable components and helper functions (like we've done with the `<.savvycal_logo />` component, which is defined in the `OgImageWeb.SharedComponents` module). The image controller serves content over two different routes: - `/preview` for an HTML preview of the image contents - `/image` for the actual rendered image (in PNG format) > [!TIP] > Use the Responsive Mode and set the viewport to `1200 x 630` pixels to see the HTML preview in the same dimensions as the PNG image. This is great for testing and dialing in your designs quickly (without re-rendering the PNG on every change). ## Customizing styles The CSS styles for image templates are defined in the [`OgImageWeb.Layouts.image_template_styles/1`](https://github.com/svycal/og-image/blob/main/lib/og_image_web/components/layouts.ex) component. For performance, all definitions (including fonts) are inlined inside a `