Building a JAMstack site with Hugo and Azure Functions
Modern web development architecture:
Static site generators + JavaScript + Serverless = JAMstack
This blog post covers:
Hugo + jQuery + Azure Functions = JAMstack
This blog post is part of a series:
- Building a JAMstack site with Hugo and Azure Functions (this post)
- Managing content for a JAMstack site with Netlify CMS
The example used in this blog post is a site for jam recipes.
Example code:
Example site:
JAMstack
Modern web development architecture based on client-side JavaScript, reusable APIs, and prebuilt Markup.
Read all about it over at: https://jamstack.org
Three things are needed:
- JavaScript
- APIs
- Markup
In this blog post the JavaScript is written with jQuery, the APIs implemented with Azure Functions and the markup generated with Hugo.
Why?
- Better Performance
- Higher Security
- Cheaper, Easier Scaling
- Better Developer Experience
Static site generators is The Next Big Thing and it is used At Scale.
Hugo
A fast and modern static website engine
Hugo is a static site generator.
It’s the second most popular according to https://www.staticgen.com
Why Hugo?
- Extremely fast build times
- Runs on Windows and is easy to install
Scaffold a Hugo site:
hugo new site .
Add content:
hugo new recipe/apple-jam.md
Code
The code for the site:
Configuration for the Hugo site is done in config.toml
:
- Uses the TOML format, located in the root folder
- The
baseURL
points to where the site is hosted on GitHub Pages
Data:
- Uses the TOML format, located in the
data
folder - This example is for the API URLs invoked by the JavaScript
The HTML template for the header:
- HTML file located in the
layouts\partials
folder - This example uses Bootstrap template with the Narrow jumbotron
- Custom CSS in
app.css
, Bootstrap stylesheets from CDN - The
body
tag gets anid
with the current page template, will be used in the JavaScript - The navigation is populated by pages configured with
navigation = true
in the front matter
The HTML template for the header:
- HTML file located in the
layouts\partials
folder - Custom JS in
app.js
, third-party scripts from CDN
Content:
- Uses the Markdown format with Front Matter
- This example is for the Apple Jam page
- The image and ingredients are stored as variables, available in templates via the Param method
Page Templates:
- HTML file located in a
layouts
subfolder - Reference the header and footer partials
- This example is for the recipe pages
- Data for the JavaScript is stored as attributes in a dedicated element
- The image and ingredients are accessed via the Param method
- The page markdown content is accessed with the
.Content
variable
JavaScript:
- Located in the
static
folder - This example uses jQuery
- The recipe page will
GET
ingredients from a Azure Function - The submit page will
POST
recipes to a Azure Function
Hugo has a theming system, so you don’t have to implement all templates yourself.
Hugo Themes:
Run and Build
Hugo provides its own webserver which builds and serves the site:
hugo server
- In this example you can then browse
http://localhost:1313/jamstack/
Build the Hugo site:
hugo --destination ../../docs
- In this example the site is hosted by GitHub Pages from the
docs
folder in the git repo.
Troubleshoot the site generation with:
hugo --verbose
GitHub Pages
Get the site hosted on GitHub Pages by:
- Pushing the code to GitHub
- Configuring a publishing source for GitHub Pages
In this example the docs
folder is used as publishing source:
Azure Functions
Azure Functions Core Tools is a command line tool for Azure Functions
The Azure Functions Core Tools provide a local development experience for creating, developing, testing, running, and debugging Azure Functions.
Create a function app:
func init
Create a function:
func function create
If you don’t like the terminal, take a look at Visual Studio 2017 Tools for Azure Functions
Code
The code for the API:
Configuration for a function is done in function.json
:
- The
authLevel
can be set toanonymous
in this example - The
route
andmethods
are important to know when invoking the function from the JavaScript
The actual function is implemented in run.csx
:
- Uses the scriptcs format
- This example will return hard coded ingredients for the given recipe
Run
Run the functions locally:
func host start
When running the Hugo site against local functions, specify CORS origins:
func host start --cors http://localhost:1313
Deployment
Get the functions hosted on Azure by:
- Pushing the code to GitHub, Bitbucket or Visual Studio Team Services
- Log in to the Azure portal
- Create a function app
- Set up continuous deployment
In this example the Azure Functions code is located in the \src\api\
folder in the git repo.
Therefor deploying with custom script is needed:
.deployment
:
- Run
deploy.cmd
during deployment
deploy.cmd
:
- Copy files from the
\src\api
folder to the repository root
During deployment the logs look like this:
Configuration
Before the Hugo site and the JavaScript can invoke the Azure Functions, Cross-Origin Resource Sharing (CORS) needs to be configured.
In this example these origins are allowed:
https://hlaueriksson.github.io
http://localhost:1313
Now the Hugo site can be configured to use these URLs:
https://jamstack.azurewebsites.net/api/Ingredients/{recipe}
https://jamstack.azurewebsites.net/api/Recipe
Conclusion
- JAMstack is the modern web development architecture
- Static site generators is a big thing right now
- Hugo is fast and awesome
- jQuery is still useful
- Serverless is the next big thing
- Azure Functions is awesome