Static Site Website Generators have been getting increasingly popular within the last 2 years. Much has been written (like this and this) and there have been many great open source projects and even funded companies launched to help you get up and running.
What if I told you that you could build a Static Site Generator with your own custom CMS without the need for a database? Not just that, but we can get to Hello World! in under 100 lines of JavaScript.
Article Series:
Build a Custom CMS for a Serverless Static Site Generator (You are here!) + Repo
Build a Custom Serverless CMS: Part 2 + Repo
The historic problem with static site generators is that they typically require content to be authored in markdown. This works great for developers but not as well for clients who are used to working in a CMS authoring environment. Creating such an environment has traditionally meant the need to create a database to manage authentication, save content and upload media.
Thanks to the rise of so-called serverless architectures (aka Backend as a Service), this is no longer the case.
In this demo, we will create the bare bones of a static site generator with content authored by an admin user via a standard web form (no database necessary).
To accomplish this, we will use:
A serverless web application architecture (AWS SDK for JavaScript, Amazon Cognito, IAM and S3)
A front end template engine (JSRender).
View the completed files for this proof-of-concept demo project on GitHub.
Set Up a Static Website on Amazon S3
First, sign up for an account with Amazon Web Services (AWS) if you have not already. Once you have an AWS account it is easy to set up a static site hosted on AWS Simple Storage Service (S3).
First, create a bucket and then under Static Website Hosting in Properties, select Enable website hosting and set the Index Document to point to the homepage of the site (`index.html`).
Next, create a bucket policy to make your site publicly readable. For information on setting up bucket permissions, refer to the AWS S3 documentation. Additionally, we need a policy that will allow an admin to save content edits.



*
POST
GET
PUT
DELETE
HEAD
*


For more detailed information on how to host a static site on S3, including on one of your own domains, refer to Hosting a Static Website on Amazon Web Services.
Create Static Site Files
Create a new directory for your project. Construct a simple project page or pick a simple example from your front end framework of choice. In our demo, we use the Jumbotron example from Bootstrap.
Upload the files to the S3 bucket you created. Once the upload is complete, select the S3 bucket and view Properties. Click on the endpoint link and you will be able to view your site.
Create Admin Login
Amazon Cognito provides a simple way to add an authentication flow to a website.
The first step in this process is to create a UserPool. In the AWS Console, navigate to Amazon Cognito and create a user pool with the default settings. Read more about User Pools in the AWS Documentation.
Once your User Pool is created, you need to add an app with access to the pool. Select your User Pool to edit it, then select the Apps tab. Click the Add an app button and give your app a name. When adding an app, it is very important to uncheck the Generate client secret checkbox because the JavaScript in the Browser SDK does not support apps with a client secret.
data-recalc-dims=1
We will directly create our admin users in the AWS Console, then provide them with credentials they can use to log in. Only these users will be able to get authenticated to have access to generate the static content for our site.
Go into the User Pool and select Users and Groups. Fill in your own information so you can be the first admin user. Select the option to send an invitation to the user via email.
data-recalc-dims=1
Now we need to create a login page for our admins. Make a new admin directory in the project with an index.html with a login form inside it. In our demo, we use the Bootstrap Sign In Page.
To connect our form with Cognito, we will need to use the Amazon Cognito Identity SDK for JavaScript. Follow the installation instructions on the project page to add the scripts to our login page.
Next, use the Amazon Cognito Identity service to authenticate and establish a session for our admin user with the temporary password received via email.
Add a submit event listener to our login form that calls a login function based on the authentication example from the Amazon Cognito Identity SDK for JavaScript Project Page.
$(.form-signin).on(submit, function(e) {
e.preventDefault();
var authenticationData = {
Username : $(#inputUsername).val(),
Password : $(#inputPassword).val()
};
var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);
var poolData = {
UserPoolId : …, // your user pool id here
ClientId : … // your client id here
};
var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
var userData = {
Username : $(#inputUsername).val(),
Pool : userPool
};
cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
cognitoUser.authenticateUser(authenticationDetails, {
newPasswordRequired: function(userAttributes, requiredAttributes) {
$(#form-password).removeAttr(hidden);
$(#form-login).css(display, none);
if ($(#inputNewPassword).val() !== ) {
cognitoUser.completeNewPasswordChallenge($(#inputNewPassword).val(), [], this);
}
},
onSuccess: function (result) {
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId : us-east-1:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX,
Logins : {
cognito-idp.us-east-1.amazonaws.com/us-east-1_XXXXXXXXX : result.getIdToken().getJwtToken()
}
});
$.getJSON(index.json, function(data) {
$(.container).html($(#adminForm).render(data));
}).fail(function() {
$(.container).html($(#adminForm).render({}));
});
AWS.config.update({
region: us-east-1,
credentials: new AWS.CognitoIdentityCredentials({
IdentityPoolId: us-east-1:XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX,
Logins: {
cognito-idp.us-east-1.amazonaws.com/us-east-1_XXXXXXXXX : result.getIdToken().getJwtToken()
}
})
});
s3 = new AWS.S3({
apiVersion: 2006-03-01,
params: {
Bucket: YOUR_BUCKET_NAME
}
)};
},
onFailure: function(err) {
alert(err);
}
});
});
We need to create an additional form to allow the admin to create a password. Admin will sign in with their temporary password then set a new password to complete authentication.
For more information on working with Amazon Cognito and User Pools, refer to these articles:
Amazon Cognito Developer Guide
Accessing Your User Pools using the Amazon Cognito Identity SDK for JavaScript
Customizing Amazon Cognito User Pool Authentication Flow
Create CMS Admin
With login complete, we want to allow our admin to edit content on the site. In this demo, we will edit the top jumbotron callout. After admin is authenticated, we display a form with inputs for site info, the callout headline, and text content.
data-recalc-dims=1
When the form is submitted, we combine the data from the form with a template to generate static HTML. In this demo, we JSRender as our templating engine.
Create the template for our Jumbotron page by copying the HTML and embed it on our admin page as a JSX template. Replace the content with template tags mapped to the names of the admin edit form fields.