nuuklu blog

Next.js'e dinamik sosyal kart ekleme

12 Aralık 2023

Bir önceki yazımda Next.js’e nasıl statik kart ekleyebileceğinizi aktarmıştım.

Paylaştığımız içeriğin dinamik bir kartının olması sosyal medyada daha fazla ilgi çekeceğinden; sitemize daha fazla trafik almamızı sağlayacaktır. Bu yazıda Next.js App Router uygulamanıza dinamik olarak kartınızı nasıl ekleyebileceğimizi yazacağım.

Next.js'in konuyla ilgili dökümanını kontrol etmenizi tavsiye ederim

Dinamik bir yapıya ihtiyaç duyuyorsanız çok yüksek ihtimalle bir api‘a istek atıyorsunuzdur. Bu örnek için jsonplaceholder sitesine istek atıp, gelen response’a göre sitemizin opengraph image‘ini oluşturalım.

Örnek üzerinden göstereceğim

Projenin github linki

Öncelikle dosya yapısını ekleyeyim

├── src/
    └── app/
    │   └──users/
    │        └──[id]/
    │            └──opengraph-image.tsx
    │            └──page.tsx
    └──lib/
        └──userFunctions.ts

Api’a istek attığım bölümü farklı bir dosyada yazdım. userFunctions.ts

//src/lib/userFunctions.ts
import { User, Users } from "@/types/user";
export const getAllUsers = async (): Promise<Users> => {
  let allUsers = await fetch("https://jsonplaceholder.typicode.com/users");
  let allUsersJson = await allUsers.json();
  return allUsersJson;
};

export const getUserByID = async (id: string): Promise<User> => {
  let users = await getAllUsers();
  let user = users.find((user) => user.id.toString() == id);
  if (!user) throw new Error("no user found with this id: ");
  return user;
};

Next.js dökümantasyonunu okuyarak hem fotoğraflardaki ‘alt’ açıklamasını hem de sosyal kartımdaki yazıyı dinamik bir hale getirdim.

// generatedynamicogimages/src/app/users/[id]/opengraph-image.tsx
import { ImageResponse } from "next/og";
import { getUserByID } from "@/lib/userFunctions";

export const runtime = "edge";
export const size = {
  width: 1200,
  height: 630,
};

export async function generateImageMetadata({
  params,
}: {
  params: { id: string };
}) {
  const user = await getUserByID(params.id);

  return [
    {
      alt: user.address.city,
      contentType: "image/png",
    },
  ];
}

export default async function Image({ params }: { params: { id: string } }) {
  const user = await getUserByID(params.id);
  return new ImageResponse(
    (
      <div
        style={{
          fontSize: 48,
          background: "white",
          width: "100%",
          height: "100%",
          display: "flex",
          alignItems: "center",
          justifyContent: "center",
        }}
      >
        {user.phone}
      </div>
    ),
    {
      ...size,
    }
  );
}