Skip to content

kiwilan/social-oembed

Repository files navigation

Social oEmbed

Social oEmbed

API to offer OpenGraph meta or oEmbed media.

Node.js Fastify TypeScript

esbuild Pipeline CI


Warning In early development, not stable.

Why ?

OpenGraph protocol offer a way to get meta data from a website to display a nice preview in social media and oEmbed offer to display an iframe from another website like social network.

With OpenGraph, from JavaScript application, on client side, you can't crawl website to extract metadata, you have to call an API to get these data, some services offer this API, but mostly aren't open source. About these services, you can find opengraph.io (free with API limit requests) or iframely (with own hosted solution).

With oEmbed, it's really complicated, each social network have their own API, with some limitations, some services offer to get these data but you have to pay for it, and it's really expensive (smashballoon, embedsocial...). Only iframely offer a free plan with some limitations, with own hosted, but with some limitations with Instagram or Facebook cause by Meta*.

This project is an attempt to offer a free (with own hosted solution) and open source API to get OpenGraph and oEmbed data.

*: to get Instagram or Facebook data, with iframely or with Meta API, you have to register your application on Meta, with many validations. Social oEmbed offer another solution without any key from Meta.

You could check the React demo app to see how it works.

Features

  • OpenGraph
    • Dark mode with dark=true query parameter
    • Twitter card query with opengraph=twitter query parameter
    • Opiniated HTML render
  • oEmbed
    • Social network providers
    • Fallback on OpenGraph if no oEmbed provider
    • HTML render
      • Rebuilt HTML iframe from url query parameter (oembed=nofetch) : use some rules to find media ID from URL and rebuild HTML iframe without external request
      • Get HTML and metadata from oEmbed API (oembed=fetch) : some API have request limit or API key limit, if request is rejected, fallback on OpenGraph
      • Get metadata from website (oembed=opengraph) : some social networks use a lot of JavaScript, crawl can be limited
    • Smart queries, customize render for each social network [ ]
  • Host your own instance [ ]
    • Docker [ ]
  • Middleware
    • auth with api_key query parameter or Bearer token
    • url query parameter

Social providers

  • Dailymotion: regex
  • Instagram: regex
  • Facebook: regex
  • Flickr
  • Giphy
  • Imgur
  • Kickstarter
  • Linkedin
  • Pinterest
  • Reddit
  • Snapchat
  • Soundcloud
  • Spotify: regex, API
  • Ted
  • Tumblr
  • Tiktok: regex, API
  • Twitch
  • Twitter: regex, API
  • Vimeo
  • Youtube: regex

Roadmap

  • OpenGraph
    • og:title, og:description, og:image, og:url, og:type, og:site_name, og:locale
    • Color theme-color
    • Fallback to twitter:title, twitter:description, twitter:image, twitter:url, twitter:card, twitter:site, twitter:creator
    • All meta
    • twitter query for card
    • Opiniated render
  • oEmbed
    • Major social networks support
    • Providers system
    • smart queries for each social network
    • queries for iframe
    • fallback to OpenGraph if no oEmbed, no provider or oEmbed error
    • oEmbed rebuilt with match
    • add api key for each provider
  • Host your own instance
  • Auth middleware https://github.com/fastify/middie
  • Documentation
    • Usage from JS client side with fetch
    • Usage response example, typescript interfaces
    • Usage oembed
    • Social networks providers specs
    • examples alpinejs/react/vuejs
    • Deploy nginx and pm2 docs
  • Vite with https://github.com/fastify/fastify-dx
  • social providers like https://iframely.com/links
  • meta crawler like https://debug.iframely.com and https://iframely.com/embed
  • Use Mongo to cache data
  • Use Bun when it will be stable

Usage

API documentation

Demo instance: https://social-oembed.git-projects.xyz.

On this instance, api_key is disabled and HTTP header Access-Control-Allow-Origin use localhost:3000,127.0.0.1:3000,localhost:5173,127.0.0.1:5173, so you can test it from your browser or from any localhost application with port 3000 or 5173.

GET /api
Parameter Type Required Description
url string true URL of website like https://github.com.
format opengraph, oembed false Format of data, default is opengraph.
api_key string Depend of .env API_KEY variable API key.
GET /instance

Information about API.

OpenGraph

Example: https://social-oembed.git-projects.xyz/api?url=https://github.com&format=opengraph

curl --request GET \
    --data-urlencode "format=opengraph" \
    --data-urlencode "url=https://github.com" \
    --get "https://social-oembed.git-projects.xyz/api" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"

oEmbed

Example: https://social-oembed.git-projects.xyz/api?url=https://www.youtube.com/watch?v=fXmAurh012s&format=oembed

curl --request GET \
    --data-urlencode "format=oembed" \
    --data-urlencode "url=https://www.youtube.com/watch?v=fXmAurh012s" \
    --get "https://social-oembed.git-projects.xyz/api" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"

How it works ?

OpenGraph

Social oEmbed will parse url website with cheerio and extract OpenGraph data from meta tags. If open graph data are not found, it will try to extract Twitter data or meta tags. If no data are found, it won't return an error, will have just an empty result. The response will be available into data, another metadata you will find an an opiniated HTML render into data.render, you could just display this into your application.

All data about fetch are available into meta.fetch object.

oEmbed

Social oEmbed will try to find a provider from url, if exists, it will use it to get oEmbed data from social network API. The API have to return a correct response to display an iframe, but sometimes oEmbed API have limits. If the request failed, the provider will try to rebuild embed url to inject it into an iframe. Like OpenGraph, you will have some metadata (built on OpenGraph type) into data and a data.render with an iframe. If no provider exists, you will have a fallback to OpenGraph.

All data about fetch are available into meta.fetch object.

Note: if Social oEmbed can't find a provider from url, your social network could be not supported by Social oEmbed and you can contribute to add it. But if provider exists, it could be the url parse bug, you can open an issue.

// TODO contribute and issue

data object

title?: string
description?: string
image?: string
siteUrl?: string
type?: string
siteName?: string
locale?: string
audio?: string
video?: string
determiner?: string
article:author?: string
themeColor?: string
icon?: string
width?: string
height?: string
social: Social
embedUrl?: string # oEmbed only
render: string

meta object

url: string # original url
format: string # opengraph or oembed
message: string # error message
instance: string # documentation url
fetch:
  message: string
  status: number
  ok: boolean
  type: string # json, text or unknown

Setup

Local

Download dependencies

pnpm i

Create .env

cp .env.example .env

Execute dev

pnpm dev

Server is available on http://localhost:3000.

.env

Variable Type Default Description
NODE_ENV development,test,production development Current environment.
LOG_LEVEL debug,error,fatal,info,trace,warn,silent debug Log level for debug.
API_PORT number 3000 Port used by your application
API_HOST string localhost Host of your application
API_HTTPS boolean false Enable https for you application
API_KEY string, undefined, false false API key if you want to set it, if undefined or false API key protection is disabled
API_DOMAINS string localhost:3000,127.0.0.1:3000 Domains allowed to use the API, seperated by commans, use * to allow all domains

Production

Build application

pnpm build

Start application from build

pnpm start

You have to serve application with a manager like pm2. A command offer to start application with pm2.

pnpm pm2

But the best way is to use Nginx with pm2.

Tests

Linter

Show errors with ESLint.

pnpm lint

Automatically fix errors.

pnpm lint:fix

Technical environment

Based on Fastify and TypeScript, with ESBuild for bundling (ESM format).

From template fastify-esbuild by davipon.

  • node >= 16.x
  • pnpm >= 7.x
  • fastify 4.x
  • react 18.x
  • esbuild 0.15.x

License

BSD 2-Clause

Credits