Wilson Mar bio photo

Wilson Mar


Calendar YouTube Github


Version controlled simplicity using Jekyll and GitHub Pages compared with AWS S3 and CloudFront.

US (English)   Norsk (Norwegian)   Español (Spanish)   Français (French)   Deutsch (German)   Italiano   Português   Estonian   اَلْعَرَبِيَّةُ (Egypt Arabic)   Napali   中文 (简体) Chinese (Simplified)   日本語 Japanese   한국어 Korean


Static is Cool Now

Here is why building a static site is “cool” (popular, interesting, etc.).

When someone types in a URL on a web browser and lands on a website built using WordPress, Drupal, or other CMS (Content Management System), that user waits while the web server make calls to a database and builds the HTML to send back.

Static sites are faster for several reasons.

  1. There is no time lost generating HTML dynamically. There is no time lost calling a database. The web page sent to a visitor is direct response to the URL requested.

    Personalization is done by JavaScript running on the user’s machine, calling web services APIs (Application Programming Interfaces).

  2. The HTML file can be spread out around the world in a CDN (Content Distribution Network) such as Amazon S3. This reduces network latency.

    Reduction in cost of CDNs via Amazon S3, CloudFlair, Fastly, etc. vs. the enterprise Akamai makes this possible.

    Due to less processing, the website is also more scalable, able to handle a much larger number of visitors.

Having static files in an environment which serves many other sites provides the site resilience to DoS (Denial of Service) attacks which aim to overwhelm a service.

Fraction of a Second to First Byte

Techniques described on this website achieve the fastest possible loading speed, world-wide:

(Click here for new window containing higher resolution image)

“JAM” Stack

Static sites are called “JAM stack” for

  • JavaScript,
  • API calls (to various 3rd party sites rather than local databases), and
  • Markup text stored in GitHub then built into HTML and stored in CDN.

Video: The JAM Stack 16 April 2016 by Mathias Billmann (@Billmann at Netlify.com)

  • https://www.smashingmagazine.com/2015/11/modern-static-website-generators-next-big-thing/

jamstack.org comments on the drivers for the JAM stack:

“Today browsers are the operating system of the web, and are able to run complex applications completely client side. They are capable of consuming and interacting with an ever growing amount of APIs and services across domains and infrastructures. CDNs (Content Delivery Networks) have gone from being a luxury only large corporations could afford, to being the natural way to cut down the time to first byte for sites and apps of all sizes. Deployment models have shifted from cumbersome manual uploads to automated processes triggered by ever-present version control systems.”

API Calls

The rise of APIs has removed many of the limitations of static HTML:

  • Discourse for visitor comments
  • Lunr.js for search
  • Stripe for e-commerce

The downside

  1. Some feel git version control is a hassle to use.

  2. Some prefer the WSIWYG editors like Microsoft Word over text editors and writing markdown code.

    However, CloudCannon.com enables users to create a Jekyll site that presents Visual Editor forms for editing text in context of background graphics.

  3. Since Jekyll and other static platforms are newer than WordPress, Drupal, etc. there are not as much of a diversity in themes and plug-ins available.

Tools to generate static websites

I’ve configured a few, but most recently:

  • Jekyll is the most popular among static website generation tools largely because GitHub.io websites are hosted automatically, and free, from repositories in GitHub.com.

Much like what wordpress.org provides, but with the git version control added – a crucial feature.

Surveys are:

Sites using this approach

React-driven generation of SPA pages

https://phenomic.io, generates html from .md files containing yaml like Jekyll, but instead of template code, it processes standard templating in React.js with Webpack does the generation.

Coding JavaScript in ES6 is possible because Babel or PostCSS or CSSNext enables can translate the ES6 code back to ES5 so that current websites work.

  • ESLint for JavaScript and
  • Stylelint for CSS

Phenomic_app is rather young. Its @Phenomic_app on Twitter had 130 followers as of July 6, 2016.

Its advantage is that it generates SPA (Singe Page App) JavaScript which initially loads just enough to display on the page (so it’s faster than loading the whole HTML file). More importantly, additional pages are downloaded as needed in response to user action such as scrolling.

When a link or a button is clicked by a visitor, JavaScript running on the page updates the address bar, but the whole web page is not refreshed. Management of the address bar is done by the router JavaScript library.

Use of React means changes to markup is instantly reflected on the web page display.

See video: “A static website with React? Really?” on 25 May 2016 by Maxime Thirouin

There are several router libraries in the React ecosystem. The most popular router is react-router.


  • @MoOx (from France) is its creator.


  • https://github.com/petehunt/react-webpack-template
  • https://github.com/petehunt/webpack-howto

  • https://webpack.github.io/docs/list-of-plugins.html#dllplugin
  • https://gist.github.com/robertknight/058a194f45e77ff95fcd
  • https://github.com/mxstbr/react-boilerplate/pull/495/files
  • https://github.com/FrendEr/webpack-optimize-example/tree/master/dll-bundles

Most people (including Facebook) are using React.createClass() rather than JSX.

  1. Use npm to download phenomic into present working directory:

    npm i phenomic

    This takes several minutes to download from

  2. Install phenomic using npm:

    ./node_modules/.bin/phenomic setup

    Note: All values can be adjusted later.
    ? Dashed name of your project (eg: my-project) 
  3. Type “phenomic” and press Enter for:

    ? Website url (eg: http://abc.xyz/) 
  4. Type URL for:

    ? Repository url (eg: https://github.com/MoOx/phenomic.git, optional) 
    ? Twitter nickname (eg: MoOx, optional) 
    ? Do you want a CNAME file (eg: for GitHub Pages)? No
    Generated package.json file
    Copied boilerplate
    Setup done. Now run "npm install" to get started

    These can be changed later by editing the package.json file.

  5. Install npm

    npm i && npm start

  6. Start npm:

    npm start –devPort=3001

    Without the extra parameter, this starts a web page on port 3000 by default. The response:

  7. Edit the configuration file (subsituting vim with atom, subl, or other text editor):

    vim package.json

    “stage-1” refers to ES7.

    See https://phenomic.io/docs/usage/configuration/

  8. Run tests:

    npm test

Edit this site

The built site has a Edit this link to the GitHub repo file.

  • https://github.com/MoOx/phenomic/edit/master/docs/content/showcase.md

  • https://github.com/petehunt/react-howto

AWS S3 and CloudFront

This is based on video React App on AWS S3 with Static Hosting + Cloudfront | Practical AWS Projects #1 by Be a Better Dev.

Here we see how many steps it takes to host a static website in an AWS S3 bucket and AWS CloudFront CDN.

a. Using Console GUI b. Using CloudFormation c. Using Terraform

  1. The website can be a simple HTML file or a set of HTML, CSS, Js, png images built using React.js and Webpack.

  2. Package up the website into a zip file:

    npm run build

    VIDEO: Create S3 bucket with globally unique Bucket Name that’s without spaces and uppercase letters.

  3. In S3


  4. Click Create bucket.

  5. For Bucket name, type a unique DNS-compliant name for your new bucket. For Bucket name, type example-bucket-name. For Region, choose US East (N. Virginia).

  6. Determine what region (geographic location) to use. The default is US East (N. Virginia).

    REMEMBER: The region can’t be changed after the bucket is created.


    REMEMBER: The bucket name cannot be changed after the bucket is created.


  7. Skip “Choose bucket”.
  8. Leave ACLs disabled in play/test. In production, enable ACLs so Objects in this bucket can be owned by other AWS accounts. Access to this bucket and its objects can be specified using ACLs.
  9. Uncheck “Block all public access”.
  10. Check “I acknowledge that the current settings might result in this bucket and the objects within becoming public.”
  11. Bucket Versioning: leave disable.
  12. Pass on Tags.
  13. Default encryption: Select SSE-KMS for play/test use.
  14. Choose from your AWS KMS keys. Create a KMS key for https://us-east-1.console.aws.amazon.com/kms/home?region=us-east-1#/kms/keys/create
    • Key type: Symmetric (single key, not Asymmetric)
    • Key usage: Encrypt and decrypt (not Generate and verify MAC).
    • Advanced options:
    • KMS
    • Regionality: Single-Region key
    • Next
    • Alias: use the bucket name from above (3329v32).
  15. Bucket Key: disable
  16. Advanced setting:
  17. Object lock: Disable (only works in versioned buckets.

  18. Go to the S3 buckets page, and click your bucket’s name.

  19. Choose the “Properties” tab.

  20. Scroll down to the “Static website hosting” section at the bottom of the page, and click the “Edit” button.

  21. On the “Edit static website hosting” page, choose “Enable” under the “Static website hosting” section. It’ll open up additional properties.

  22. Keep the hosting type “Host a static website” selected.

  23. In the “Index document” text field, give the file name you want to configure as a default file. When someone accesses your bucket website endpoint, this file will load (we will add this file later on). Write index.html in the text field, and remember that the file name is case-sensitive.

  24. Click the “Save changes” button.

  25. In the “Properties” tab, go to the “Static website hosting” section.

  26. Find a bucket website endpoint. Try to open it in the new tab of the browser, we’ll get a 403 Forbidden page because our bucket is not publically accessible for now.

    Upload site contents (HTML, CSS, etc.)

  27. In the S3 buckets page, open your bucket.

  28. Currently, the bucket is empty. Click the orange button named “Upload”, which takes you to the “Upload” page.

  29. In the “Files and folders” section, click the “Add files” button, and select the index.html file from your system.

  30. Click the “Upload” button at the end of the page. It shows the “Upload: status” page. Once the file is uploaded, click the “Close” button to return to the bucket.

    Set Error Document and Public Access

  31. Replace “Bucket-Name” with your bucket name:

    "Version": "2012-10-17",
    "Statement": [
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
            "Resource": [

    Create a CloudFront Distribution

    Define CloudFront Error Page and Cache Invalidation

  32. Open the bucket created for CloudFront.

  33. On the “Objects” page, click the “Create folder” button.

  34. Write errors in the “Folder name” field and click the “Create folder” button.

  35. Upload the error.html file to the errors folder.

  36. Once uploaded, go to the “Properties” of the error.html file.

  37. Copy the value of “Key” under the “Object overview” section. It should be errors/error.html.

  38. open the CloudFront distribution.

  39. Click the “Error pages” tab and the “Create custom error response” button.

  40. On the next page, choose “403: Forbidden” from the drop-down of the “HTTP error code” field.

  41. For the “Error caching minimum TTL” field, keep the default value (10) unchanged. This value defines the minimum time to live for the cached error on the edge node. After this, CloudFront will reaccess the origin to check if the issue has been resolved and the requested object is available.

  42. Choose “Yes” for the “Customize error response” option. It’ll expand further fields.

  43. In the text field of the “Response page path,” enter / and paste the value of the “Key” copied from the properties of the error.html object. The value should look like /errors/error.html.

  44. Click “Create custom error response”.

  45. Wait for 4–5 minutes for a successful deployment. After that, try to access the wrong object with your domain name Your-CloudFront-domain-name/sample, and it’ll show the content of the error.html page.

    Cache invalidation

    This feature allows us to tell CloudFront which files not to cache at the edge locations. Whenever an object specified in this configuration is accessed, CloudFront fetches the fresh copy from the origin. To create an invalidation, perform the following steps:

  46. Go to the “Invalidations” tab of your distribution.

  47. Click the “Create invalidation” button.

  48. On the next page, give the path of the object you want to invalidate cache behavior. One path should be defined per line.

  49. Give the object’s path carefully. Invalidation can not be canceled once it is started.

    Clean Up

    Delete all the resources no longer used: buckets, CloudFront OAC, and a distribution.

  50. Navigate to the CloudFront distributions, select your distribution, and click the “Disable” button.

  51. Click the “Disable” button in the pop-up box.

  52. Once the timestamp is updated in the “Last modified” column, select the distribution again and click the “Delete” button.

  53. Click the “Delete” button in the pop-up box.

  54. Select “Origin access” from the left panel once the distribution is deleted.

  55. Select the relevant OAC, click the “Delete” button, and click the “Delete” button in the pop-up box.

  56. Navigate to the S3 “Buckets” page, select the first bucket from the list, and click the “Empty” button.

  57. On the next page, type “permanently delete” in the text field, and click the “Empty” button. This process may take time, depending on the size of your bucket.

  58. Once the bucket is empty, select it again and click the “Delete” button. Type your bucket name in the text field on the “Delete bucket” page.

  59. Click the “Delete bucket” button to delete the bucket.

  60. Repeat these steps for the second bucket.


People who have commented on this include:


Static Site Generator Build Better Blog Pluralsight video course.

Automate static website deployment from Github to S3 using AWS CodePipeline

More on front-end styling

This is one of several topics:

  1. UI Design Systems
  2. Text Editors
  3. Markdown text for GitHub from HTML
  4. 508 Accessibility

  5. gRPC (g___ Remote Procedure Call)
  6. HTTP/2 Transition Project Plan

  7. Front-end UI creation options
  8. Docusaurus static website generator
  9. Static websites
  10. JAM Stack Website Project Plan
  11. Jekyll Site Development
  12. Gatsby app generator

  13. Website styles
  14. Website Styling
  15. VueJs front-end framework

  16. Protractor to automate testing of Angular and other web pages

  17. Email from website
  18. Search within Hyde format Jekyll websites
  19. Windows Tile Pin Picture to Website Feed

  20. Data Visualization using Tableau