Skrypt przed budowaniem wpisuje `image:` do front matter.
GitHub Pages uruchamia Jekylla w trybie bezpiecznym, więc własne wtyczki wołające API przy budowaniu odpadają. Mały skrypt, który raz uzupełnia `image:` i trafia do repozytorium razem z wpisem, działa na GitHub Pages i wszędzie indziej — a jekyll-seo-tag sam bierze to pole jako og:image, bez zmian w szablonie.
_scripts/og_images.rb
#!/usr/bin/env ruby
# Usage: IMAGE_API_KEY=sk_live_... ruby _scripts/og_images.rb
require "json"
require "net/http"
require "yaml"
ENDPOINT = URI("https://imageapi.dev/v1/images?wait=true")
Dir.glob("_posts/*.{md,markdown}").each do |path|
source = File.read(path)
_, front, body = source.split(/^---\s*$/, 3)
meta = YAML.safe_load(front, permitted_classes: [Date, Time]) || {}
next if meta["image"] # already has one
request = Net::HTTP::Post.new(ENDPOINT, "Content-Type" => "application/json",
"Authorization" => "Bearer #{ENV.fetch("IMAGE_API_KEY")}")
request.body = { template: "blog-og", modifications: { title: meta["title"], site: "yourblog.com" } }.to_json
response = Net::HTTP.start(ENDPOINT.host, ENDPOINT.port, use_ssl: true) { |http| http.request(request) }
response.value
url = JSON.parse(response.body).fetch("url")
# `image` is the key jekyll-seo-tag reads for og:image.
File.write(path, "---#{front.rstrip}\nimage: \"#{url}\"\n---#{body}")
puts "#{path} -> #{url}"
end
Sprawdzaj, czy front matter nie ma już `image:`, zanim wygenerujesz — inaczej każde uruchomienie robi nowy obrazek dla każdego wpisu. Nasz cache zwróci ten sam adres dla tego samego tytułu, ale zmieniona nazwa strony czy szablon znów zużyje limit.
Z ?wait=true czekasz na gotowy obrazek w tym samym połączeniu — zwykle około sekundy.
{
"id": "img_01m08s3ez1zcv28h335g9923bw",
"status": "completed",
"url": "https://cdn.imageapi.dev/renders/img_01m08s3ez1zcv28h335g9923bw.png",
"duration_ms": 912
}
Sto obrazków miesięcznie za darmo, potem $9 za dwa tysiące. Ten sam wpis wyrenderowany drugi raz zwraca istniejący adres i nie zużywa limitu — więc przebudowanie strony nic nie kosztuje.