mazipan / tanyaaja.in

❓Kumpulkan pertanyaan secara anonim dari siapa saja dengan mudah
https://tanyaaja.in
MIT License
134 stars 36 forks source link

Custom OG Image #15

Closed mazipan closed 7 months ago

mazipan commented 11 months ago

For an advanced user, maybe give a link to vercel og playground.

mazipan commented 11 months ago

Versi simple --> sudah Versi rumit --> Form UI sudah, hit API-nya belum

yogiprsetya commented 11 months ago

Versi simple --> sudah Versi rumit --> Form UI sudah, hit API-nya belum

OG untuk halaman /p/[username] kah?

mazipan commented 11 months ago

OG image yang versi simple sudah ada, yang versi rumit ini yang belum dikerjain. Terutama endpoint untuk generate image nya.

Kodenya under src/app/api/og/route.tsx harusnya dia bisa baca kolom code_public dan code_question kalau tersedia. Sekarang beluman.

Masih gak kepikiran juga gimana passing-nya, idealnya gak boleh passing code lewat URL. Jadi mestinya proses select datanya ada di sini. Tapi sekarang ada di level page, apinya cuma terima bersih.

jackyef commented 11 months ago

Masih gak kepikiran juga gimana passing-nya, idealnya gak boleh passing code lewat URL.

Mau ngasih sedikit input. Code dari user bisa dicompress pakai LZString (contoh: aku pakai di code playground aku di jackyef.com)

Ini harusnya udah bisa cover code yang panjang banget. Jadi kalau mau tetap passing via URL (gak nge-fetch data di /og/route) bisa approach ini.

Lalu ini agak gak related. Kalau bisa custom code yang disimpan di DB udah dalam bentuk JSON, representasi dari JSX nya.

✅
const customOgJsxJson = `{"type":"div","key":null,"ref":null,"props":{"style":{"height":"100%","width":"100%","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center","backgroundColor":"#fff","fontSize":32,"fontWeight":600},"children":[{"type":"svg","key":null,"ref":null,"props":{"width":"75","viewBox":"0 0 75 65","fill":"#000","style":{"margin":"0 75px"},"children":{"type":"path","key":null,"ref":null,"props":{"d":"M37.59.25l36.95 64H.64l36.95-64z"},"_owner":null,"_store":{}}},"_owner":null,"_store":{}},{"type":"div","key":null,"ref":null,"props":{"style":{"marginTop":40},"children":"[question]"},"_owner":null,"_store":{}}]},"_owner":null,"_store":{}}`

❌
const customOgJSx = `<div
  style={{
    height: '100%',
    width: '100%',
    display: 'flex',
    flexDirection: 'column',
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: '#fff',
    fontSize: 32,
    fontWeight: 600,
  }}
>
  <svg
    width="75"
    viewBox="0 0 75 65"
    fill="#000"
    style={{ margin: '0 75px' }}
  >
    <path d="M37.59.25l36.95 64H.64l36.95-64z"></path>
  </svg>
  <div style={{ marginTop: 40 }}>[question]</div>
</div>`

Alasannya:

  1. Lebih gampang untuk implementasi. Memang JSX dirancang untuk bisa di-serialize ke bentuk JSON.
  2. Nge-hindarin remote code execution (kalau misalnya perlu eval atau manually transpile JSX di runtime)
  3. satori, engine dari ImageResponse-nya Next.js udah support untuk nge-render representasi JSX dalam bentuk JSON, jadi tinggal:
    return new ImageResponse(
      JSON.parse(customOgJsxJson.replaceAll('[question]', question)),
      {
        width: 800,
        height: 600,
      },
    )