Add Dynamic Content to Static Sites powered by Jekyll, Hugo, Hexo, Middleman and Gatsby

Add dynamic content to static websites

Static Sites and Dynamic Content

Static site generators have really taken the web development world by storm. Without using a database, you can publish a complete, full-featured website using markdown files. They’re fast, cheap and secure. In fact, the tutorial you are reading was published using Hexo; we love it.

One of the catalysts for static site popularity is GitHub Pages, which enables users to host static websites for free. GitHub Pages is powered by the Jekyll static site engine. There are now a wide-range of static site generators, each written in different languages and having their own benefits, including Hugo, Hexo, Gatsby, Pelican, and Middleman.

Despite the overwhelming upside of static sites, one drawback is that they don’t support server-side code. As such, you can’t easily do things like display interactive data visualizations and other dynamic content using a traditional server-based approach.

Thankfully, third-party APIs have come to the rescue. This tutorial will provide you with a simple example of how to utilize the Flex.io API to populate your static site with live third-party content.

Demonstration: Live Examples and Code

For this tutorial, we’re going to create a Webpage Thumbnail Generator. Below is a live demonstration along with its source code. In addition, we’ve inlcuded two other example applications that utilize dynamic content on static sites.


Example 1: Webpage Thumbnail Generator

View a Live Demonstration Here | Fork the Source Code Here

Summary: This static site is hosted on GitHub Pages and uses a Flex.io API pipe to take a user-provided URL, render the URL into an image, create a thumbnail of the image and return it for display on the website.


Example 2: Live Charts.js Bar Chart

View a Live Demonstration Here | Fork the Source Code Here | Read a Tutorial Here

Summary: This static site is hosted on GitHub Pages and uses a Chart.js bar chart to visualize the mobile phone operating system market share over time. Charts.js requires JSON, but the market share data was in a CSV file. It utilizes the Flex.io API to pull the CSV file and convert it to JSON to be utilized by the chart.


Example 3: URL Keyword Search Visualization

View a Live Demonstration Here | Fork the Source Code Here

Summary: This static site is hosted on GitHub Pages and uses a Flex.io API pipe to take a user-provided URL, scan the URL for top keywords and return the result to populate a D3.js Bubble Chart visualization. The user can then specify word count precision using a slider element.


NOTE: For each application above, the static site routes live, custom content to populate front-end elements and could be applied to components like widgets, dashboard elements and reporting. The same concept can be applied to data delivery, such as an upload form on a static site that takes a user file, validates it and delivers it to a cloud storage account.

Build an Application: Convert a Webpage into a Thumbnail Image

Webpage Thumbnail Generator

In this tutorial, we’ll do the following:

  1. Build a website front-end. Add a data entry form and button to submit a URL.
  2. Build a data feed. Use the Flex.io API to lookup the URL, render it as an image, convert into a thumbnail image and then return the result.
  3. Put it all together. Combine the front-end code with the Flex.io pipe to display the thumbnail image.

 

To get started, you’ll need the following:

 

NOTE: GitHub Pages with Jekyll is a really simple, free way to get going with a static site. Also, check out Netlify for a free static site in about one minute. Netlify lets you sign in with GitHub and then populates the repo for you. For example, here’s the link for Jekyll. For this demonstration, we’re using GitHub Pages. But the concept would apply equally if you were using Hugo, Hexo, Middleman, or Gatsby to generate a site or even if you were just using a static HTML page anywhere in the cloud, like on Amazon S3.

Step 1: Add Required Front-end Elements to your Website

For this example, we’re going to keep things simple. Our application requires the following three elements:

  1. A data entry form for a user to enter a URL.
  2. A button to fire off the process
  3. A location to display the thumbnail

Here is the basic html to get these three elements in place:

<html>
<body>
<form>
<input name="url" placeholder='"https://www.flex.io", etc.'>
<button type="button">Submit</button>
</form>

<img id="img_result" src="" />
</body>
</html>

NOTE: We prettied-up our live demo with a bit of CSS bling, but this will get you going.

Step 2: Build the Data Feed

A Flex.io API data feed can take data from anywhere, process it and send it anywhere. For this application, the routing is pretty straightfowrard:

  1. Receive an input (${form.url} from the data entry form)
  2. Render the url as an image
  3. Resize the image as a thumbnail
  4. Return the output and display it

The Flex.io API can be deployed in a variety of ways, including being run from GitHub, inline, in-app or as an endpoint. For simplicity, we’ll run this data feed inline. Here’s what the pipe looks like using the url parameter we are receiving from the entry form as discussed above:

var Flexio = require('flexio-sdk-js')

Flexio.setup('YOUR API KEY HERE')

Flexio.pipe()
.render('${form.url}')
.python(`
import PIL
from PIL import Image
from io import BytesIO

def flexio_handler(context):
context.output.content_type = context.input.content_type

imagedata = context.input.read()
file_imagedata = BytesIO(imagedata)
img = Image.open(file_imagedata)
imgformat = img.format

basewidth = 160
wpercent = (basewidth / float(img.size[0]))
hsize = int((float(img.size[1]) * float(wpercent)))
img = img.resize((basewidth, hsize), PIL.Image.ANTIALIAS)

file_output = BytesIO()
img.save(file_output, format = imgformat)
file_output.seek(0)
contents = file_output.getvalue()
file_output.close()

context.output.write(contents)
`)

Please note the following:

  • Swap in your own Flex.io API Key for 'YOUR API KEY HERE'. To get your free API key, sign up for a Flex.io account.
  • Without any other parameters, the .render task will render a URL to an image. Learn more about the render task.
  • For the .python task, we are using the Pillow library to write a quick script that converts the original image to a thumbnail 160 pixels wide with height proportional to the original image.

Step 3: Combine the Front-end Website Elements with the Live Data Feed

Now, we’ll combine the two elements above as follows:

<html>
<body>
<form>
<input name="url" placeholder='"https://www.flex.io", etc.'>
<button type="button">Submit</button>
</form>

<img id="img_result" src="" />

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/flexio-sdk-js@latest"></script>

<script>
Flexio.setup('YOUR API KEY HERE')

var doSubmit = function() {
Flexio.pipe()
.render('${form.url}')
.python(`
import PIL
from PIL import Image
from io import BytesIO

def flexio_handler(context):
context.output.content_type = context.input.content_type

imagedata = context.input.read()
file_imagedata = BytesIO(imagedata)
img = Image.open(file_imagedata)
imgformat = img.format

basewidth = 160
wpercent = (basewidth / float(img.size[0]))
hsize = int((float(img.size[1]) * float(wpercent)))
img = img.resize((basewidth, hsize), PIL.Image.ANTIALIAS)

file_output = BytesIO()
img.save(file_output, format = imgformat)
file_output.seek(0)
contents = file_output.getvalue()
file_output.close()

context.output.write(contents)
`)
.run({ data: $('form').serialize() })
.then(function(response) {
// response is an image blob
var url_creator = window.URL || window.webkitURL
$('#img_result').prop('src', url_creator.createObjectURL(response.blob))
})
}

$('form').on('submit', function (evt) {
evt.preventDefault()
doSubmit()
})

$('button').click(function(evt) {
doSubmit()
})
</script>
</body>
</html>

Above, we’re simply adding the extra javascript glue to take the url from the entry form and, upon click of the button, pass it to the Flex.io pipe for processing and handoff back to the site for display.

All in all, this is a very simple application, but demonstrates how you can incorporate custom server-side-like functionality, including python, to enhance your static site. To get started, you can fork the source code for this tutorial here.

Need Any Help?

We hope you found this tutorial useful. If you have any questions, shoot us a note using the chat button below. We’re happy to help and look forward to seeing what you can build!