Making a wishlist for Santa with Azure Static Web Apps - Festive Tech Calendar
As part of the Festive Tech Calendar 2020, I’m joining about 77 (!) very talented people in submitting a festive topic. In this blogpost I will talk about what exactly Azure Static Web Apps are and how we can use them to develop something for this holiday season! Be sure to check out the many other sessions, livestreams and blogs over at the Festive Tech Calendar!
TL;DR: Made a wish list for Santa using Azure Static Web Apps with source code on GitHub.
My wish list for Santa!
I’d like to think I’ve been good this year so let’s draw up a wish list for Santa. We could use Word and OneNote or we could build something cool using Microsoft Azure. A more traditional way of doing is that you take <generic scripting language #33> and combine it with <database technique #2> powered by <your favourite webserver software> but that’s no fun and not very festive! So let’s go do something cool and perhaps learn new thing or two along the way. You don’t need to be a developer but you do need some basic knowledge of Git(Hub) repositories.
Static Web Apps
Static web apps is a method of developing/hosting websites that in nature don’t change very often. Think about your typical website. How often does the data change and does it really need to be interactive? Do we really need big fat chunky servers with soon-out-of-date scripting software eating up precious CPU cycles just to render your washing machine manual? For far too long we’ve relied on CGI-BIN, ASP.NET or PHP to power our favorite CMS or blogging software like WordPress. Defaced or hacked WordPress sites are practically a cliché by now.
What we’re going to do in this post is embrace a new view on website development. What if the website server didn’t have to do anything to serve the content to the user? What if we could send our framework to the client and have the browser do most of the heavy lifting (if needed at all). Let’s adopt Static Web Apps. Using static content and the new Azure Static Web Apps service, we can create lean apps that are super responsive.
Static? That doesn’t sound very festive to me!
Hold on, we’re getting there. Just because the content on the webserver is static doesn’t mean your website will be boring. You’d be surprised how much you can do with just basic HTML and a dash of JavaScript (you know, like we did in the 90s and early 2000s?). Also, often only a small part of the website actually needs to be dynamic in order for it to be interactive. So what if we write a static website that does dynamic calls to cloud APIs? If all we want to do is show the weather, why not host a small page with most of the graphics/framework and load in the last bit of information using a API call?
Azure Static Web Apps
Introduced at Microsoft Build this year and still in preview, Azure Static Web Apps is a Platform-as-a-Service offering in Azure specialized in hosting static sites (with optionally co-hosting of serverless APIs). It differs from Web Apps in that it has very limited server-side processing making it really fast in serving unchanged content. You can do some basic things like defining routes and ask for authentication (with support for Microsoft accounts, GitHub, Twitter et cetera built-in) but it’s mostly focused on serving your static front-end that will use client-side scripting for added functionality. For some websites even just the static front-end is more than enough. Think about your average company website or this blog for instance. Yes, this post is served by an Azure Static Web App.
Deploying to Azure Static Web Apps is kinda different compared to traditional websites / Azure Web Apps and that’s, in a number of ways, a good thing. You don’t upload to a FTP host or upload a ZIP directly. Instead, you configure your Azure Static Web App to use a source code repository hosted on GitHub. These can be public (free, unlimited) or private repos so you don’t have to worry about your content being abused or someone sneaking around in your code. Azure will auto-provision a connection between the Static Web App and the GitHub repo and create a GitHub Action. In a nutshell, GitHub Actions is a Continuous Integration/Continuous Deployment platform that can automagically transform your repo code into something useful. In this case, Azure will create a YAML file in your source code that will be triggered whenever you push code to GitHub. The YAML file uses the Azure/static-web-apps-deploy provider to push your code to the Azure Static Web App.
So the workflow is as follows:
- You define your code in whatever language or static framework you want.
- You upload the code to your GitHub repo.
- GitHub Actions will automatically push your code to Azure.
- Azure will host your code for you.
The most basic test is creating an index.html page within a GitHub repo and enable that for Azure Static Web Apps. After the GitHub Action is triggered, you should be able to see the website live at whatever weird URL Azure gives your Static Web App by default. Microsoft has a demo repo.
Making it dynamic
If this sounds a bit 1990s meets 2010s to you, you’re right. Writing pure HTML code isn’t real fun anymore and most people resort to frameworks to do most of the heavy lifting for them. For instance, you can use Hugo to write your website in Markdown code (you know, the syntax used by GitHub repo’s readme.md) and transform that to usable HTML. That’s how I’m writing this post right now. Great fun!
Azure Static Web Apps not only can deploy your code to a “dumb web server” but it can also auto-create the back-end resources you’ll be using via your Javascript API calls. By defining an API folder in your repo, you can create Azure Functions that can respond interactively with server-side processing on-demand. By definition, Azure Functions is a serverless service that only gets processing power/time whenever it’s needed. No hits to the API, no big servers doing nothing.
I promised a bit more for our Christmas wish list so let’s not just host an static HTML website with some pictures. To keep things easy to follow along, we’ll base our demo on the following API example by Microsoft. This quickstart shows us how we can add a simple API to our website and deploy them simultaneous to Azure.
Following this link, we can generate a new GitHub repo based on the Microsoft example. Let’s take a look at what’s already there. It shows a simple index.html and styles.css that do little but serve a little webpage to the user, with some styling and some embedded JavaScript:
(async function () {
let response = await fetch(`api/message`);
let message = await response.json();
document.querySelector("#message").innerHTML = message.text
})();
When the browser is loading this page, it’ll to an asynchronous call to the relative “api/message” URL. By defining that the api folder is the dynamic folder in our Static Web App, Azure will know to compile code in this folder and make it available to the public under the /api url. If this sounds familiar, you’re right, that sounds a lot like CGI-BIN like the good-ol’ days of Perl. So the browser is polling the URL https://ashy-hill-05011fd03.azurestaticapps.net/api/message in order to get the extra content and place it in the proper placeholder.
So let’s take this simple demo and modify it for our holiday season wish list. We’ll keep things simple by just calling an API that retrieves dummy data. We could expand this by actually going to a Azure Storage Account with Tables in it or by querying an actual database but for now we keep things simple by retrieving a static list of possible gifts. We could also later add functionality to add and remove gift from our list by expanding the API calls. You should now have a personal GitHub repo with the example code above.
Santa wish list
Using the above example, we’re expanding the demo with a new API folder. Copy the api/GetMessage folder and call it api/GetGifts. You’ll only the need the function.json and index.js. Function.json contains meta-data for the new Function, open it and change line 11 to route: gifts. index.js will be replaced with the following code (which just returns a not-so-dynamic JSON string):
module.exports = async function (context, req) {
context.res = {
// status: 200, /* Defaults to 200 */
// Don't mind this crappy code, you should imagine some fancy database calling code here and format objects to JSON. You get the idea.
body: { text: '{ "gifts": { "Xbox": { "Name": "Xbox", "Notes": "The new one with the X!", "Store": "Microsoft Store" }, "OLED": { "Name": "LG OLED UHD", "Notes": "65 inch monster!", "Store": "Big TV store" }, "Ori": { "Name": "Ori and the Will of the Wisps", "Notes": "Best platformer on Xbox!", "Store": "Video game store" } } } ' },
};
};
That’s the back-end/API taken care of, now let’s work on the new front end. Copy index.html to list.html and add the following code snippets. Add the first in the tags of the HTML and replace the JavaScript near the bottom with the 2nd snippet.
<table id="tableofgifts" class="gifttable">
<tr><td colspan="3" class="center"><i>Loading giftlist...</i></td></tr>
</table>
(async function () {
let response = await fetch(`api/gifts`);
let giftJSON = await response.json();
var giftlist = JSON.parse(giftJSON.text);
var innerHTML = '<tr><td class="toprow">Name</td><td class="toprow">Notes</td><td class="toprow">Store</td></tr>';
document.querySelector("#tableofgifts").innerHTML = innerHTML
for (const gift in giftlist.gifts) {
document.querySelector("#tableofgifts").innerHTML += `<tr><td>${giftlist.gifts[gift].Name}</td><td>${giftlist.gifts[gift].Notes}</td><td>${giftlist.gifts[gift].Store}</td></tr>`
}
})();
I also added some cosmetics via CSS, don’t worry, I’ll share the source code to a complete demo down below.
Creating the Azure Static Web App
In Azure ($200 in Free Azure credits here), create a new Resource Group. In this new RG, click Add in the top bar and search for Static Web App. For now the service is still in preview, unsupported in production and is free. Confirm your subscription and resource group and give your new App a new. Don’t worry, this name is for your eyes only; the temp URL given to your app is quite random and you can always assign a custom URL to it later. Select your region (this is limited for preview services, more will come) and click the blue Sign In with GitHub button. A popup with confirm your selection and you’re given the option to select your GitHub org, repo and branch of choice. Under Build presets, you can select Custom for now but note that Azure already has preset for a lot of static frameworks. For now the defaults are fine. Tag resources if needed and hit Create. You’re done!
Azure will now look into your repo and create two things:
- New folders with .github/workflows structure with the GitHub Actions yaml file (For me azure-static-web-apps-ashy-hill-05011fd03.yml). In this file, it tells GitHub what to do with the code. Don’t worry, this file won’t contain any secrets, instead it references GitHub secrets tied to your repo (not visible to public).
- A new GitHub secret with an Azure API token. This is used by GitHub to actually push the resulting code to Azure.
Although the GitHub Actions pipeline is in place and connected to Azure, it won’t actually run until you push a git commit to the repo. Easiest way of making it run is to simply make a little change to the code and push that commit into the repo. Open the Actions tab on your GitHub repo and watch it deploy your new website. Make sure it successfully finishes the GitHub Action pipeline.
The end result
Go back to the Azure Portal and look at your Static Web App object. Near the top right, you should see the URL (like https://ashy-hill-05011fd03.azurestaticapps.net/, add list.html). Open this in a new browser and you should see your new Static Web App. So again, the static website with all it’s HTML, JavaScript and images is served and loaded by the browser, the browser will get the data from the Azure Function API and present it to you. I added some more windowdressing for the season and the following is presented:
The demo site in this screenshot is live and I’ll try to keep it online for a while after this post.
If you’re an experienced coder, you really shouldn’t be looking at my source code but I hope it inspires beginning developers to think outside of the dynamic box. Want to do and learn more? Try expanding my demo by actually storing the sample gift list as object in the Azure Functions code (api/GetGifts/index.js) and/or storing the in a database/storage account. Ah shoot, you could even store it in SharePoint or something and use one of their fancy APIs to deliver it to Santa. And if you’re really feeling adventurous, try adding Add/Update/Remove controls to your gift. Be sure to program the front-end in basic HTML/JavaScript and make it dynamic using the Azure Functions API. Hit me up on Twitter @MartijnBrant if you need help or pointers on anything in this demo.
I hope you have a great festive ending to this year.. I know that 2020 isn’t what everyone expected it to be but for now, let us focus on building beautiful things and celebrating the holiday season with those close to you. From the bottom of my heart I want to thank all my friends and family that have been so supportive this year and a big shout out to Pixel Robots (Richard Hooper) and Gregor Suttie for selecting my submission into the Festive Calendar to end this year. I wish everyone great health, joy and success for 2021 and hope to talk to everyone a little bit closer next year!
Thank you for reading this post. Please head over to the Festive Tech Calendar for even more great content!