All Articles

Facebook post preview with ReactJS and AWS Lambda

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)
  };
}

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"
  },

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