DEV Community

Cover image for Facebook post preview with ReactJS and AWS Lambda
Hugo Dias
Hugo Dias

Posted on

Facebook post preview with ReactJS and AWS Lambda

I'm currently focused on learning more about React. For me, the best way to learn something is to build a small project that's not a todo list (lol).

That being said, I've decided to build a small app that receives an URL, fetch the meta tags (especially the open graph tags) and build a preview based on facebook.

To accomplish this task I've chosen ReactJS and AWS Lambda (hosted on Netlify).

The Lambda function

The lambdas task is pretty simple. Receive an URL, parse and fetch the meta tags, looking for the Open Graph tags.

The open-graph-scraper npm package almost got the entire job done, so here is the final code of the lambda:

import ogs from "open-graph-scraper";
import getUrl from "get-urls";
import urlParser from "url";

export function handler(event, context, callback) {
  const text = event.queryStringParameters.q;
  const urls = getUrl(text);

  // Return if there is no urls in text
  if (!urls.size) {
    return callback(null, {
      statusCode: 200,
      body: JSON.stringify({
        text: text,
        meta: null,
        error: ["Empty url in text"]
      })
    });
  }

  // Retrieve first URL in text - urls are already normalized
  const url = [...urls][0];
  const options = { url };

  ogs(options, (error, results) => {
    const statusCode = results.success ? 200 : 500;
    callback(null, buildResponseObject(statusCode, results, text));
  });
}

function getUrlDomain(url) {
  const urlObj = urlParser.parse(url);
  return urlObj.host;
}

function cleanText(text) {
  return text.replace(/(?:https?|ftp):\/\/[\n\S]+/g, "");
}

function buildResponseObject(statusCode, result, text) {
  let meta = statusCode === 200 ? result.data : null;

  if (meta) {
    let images = meta.ogImage;

    if (images instanceof Array) {
      meta.ogImage = images[0];
    }

    let domain = meta.ogUrl;

    if (domain) {
      meta.ogUrl = getUrlDomain(meta.ogUrl);
    }
  }

  const body = {
    meta: meta,
    text: cleanText(text),
    error: statusCode !== 200 ? result.error : null
  };

  return {
    statusCode,
    body: JSON.stringify(body)
  };
}
Enter fullscreen mode Exit fullscreen mode

The Frontend

As I mentioned at the beginning of the post, react was chosen to build the client interface.

The packages used are:

  "dependencies": {
    "get-urls": "^7.2.0",
    "netlify-lambda": "^0.4.0",
    "open-graph-scraper": "^3.3.0",
    "react": "^16.4.1",
    "react-content-loader": "^3.1.2",
    "react-dom": "^16.4.1",
    "react-scripts": "1.1.4",
    "styled-components": "^3.3.2"
  },
Enter fullscreen mode Exit fullscreen mode

And here is the result:

screenshot

Contributing

It's free and open source!

The code is hosted on Github and you can see it in action here.

I'm looking forward to your feedback, folks.

Thanks

Top comments (10)

Collapse
 
dance2die profile image
Sung M. Kim • Edited

Ah, this is a nice site.

Using your site, I found out my home page looks boring without an image.

preview

Collapse
 
hugodias profile image
Hugo Dias

Hahahah it’s time to fix it! :)

Collapse
 
dance2die profile image
Sung M. Kim

Definitely.

And also, may I request for more meaningful sub-domain?
(So others can find & memorize easily?)

Netlify lets you set it like below.

edit site name

Thread Thread
 
hugodias profile image
Hugo Dias

Oh yes! Thanks for the tip. Just changed it to facebook-preview.netlify.com/

:)

Thread Thread
 
dance2die profile image
Sung M. Kim

🎉 Yay!
You're welcome
& and much appreciate the name change ✌️

Collapse
 
shtefcs profile image
Stefan Smiljkovic

Nice work, we could use this for moon.ly our open source project, since current data grabber is failing on some sites. I just compared with your tool:

Moonly: i.imgur.com/fdrmfaw.png
OG grabber: i.imgur.com/WuuC0mo.png

In case you want to contribute, check this github.com/Moonly-App/moonly-exten...

Also, this is how your website looks in mirror i.imgur.com/LkBDhXd.png :D.

Collapse
 
guidovizoso profile image
Guido Vizoso

That's a really good project to learn React and the final result is awesome. Keep the good work!

Collapse
 
pavanbelagatti profile image
Pavan Belagatti

This is going to help most of the marketing folks out there to see how their article is going to look. Good job there

Collapse
 
andy profile image
Andy Zhao (he/him)

Awesome! This is like Twitter's card validator:
cards-dev.twitter.com/validator

Except much more up-to-date :)

Collapse
 
mohamedali profile image
Mohamed Ali Chakhari

Bro, i'm struggling with using the function, can you explain it for me plze (i'm new to react)