Creating a Serverless Resume with Visitor Counter in Azure
Tags: serverless, azure, cosmosdb, cdn
Published: 2020-09-11 09:47:06

This article is part of [#ServerlessSeptember](https://aka.ms/ServerlessSeptember2020). You'll find other helpful articles, detailed tutorials, and videos in this all-things-Serverless content collection. New articles from community members and cloud advocates are published every week from Monday to Thursday through September. 
 
Find out more about how Microsoft Azure enables your Serverless functions at [https://docs.microsoft.com/azure/azure-functions/](https://docs.microsoft.com/azure/azure-functions/?WT.mc_id=servsept20-devto-cxaall).

#Introduction
The idea for this article is from the [cloud resume challenge](https://cloudresumechallenge.dev/). We need to build a serverless static resume website with a visitor counter. We need a serverless service to store the visitor’s count (Azure Cosmos DB), a serverless service to retrieve and update the visitor’s count from our store(Azure Functions), a serverless service to host our static resume website (Azure Storage) and an additional service to cache and make our static website load faster (Azure CDN). This tutorial would be divided into four parts covering each steps and services

###Building our store using Cosmos DB
Azure Cosmos DB is a fully managed NoSQL database service which is a perfect choice for our serverless store. Lets get started
#####Steps
* From azure portal, search for `azure cosmos db` and select the match
* On the cosmos db page, select `create`

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/d02qrropsqlcxmggiy8h.jpeg)

* For Project details, choose your preferred Azure subscription and resource group to group your Cosmos DB account. For instance details, enter an account name of your choice which has to be globally unique, Our API would be `Core(SQL)` as we would be using SQL syntax, Capacity mode is `serverless` and we can leave the remaining options to default and go ahead to select `review + create`

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/1mteo1kvml5accjzvkt3.png)

* Once deployment is complete, Select `Go To Resource` and choose `Data Explorer`. On data explorer page, select `New Container`.  Enter a `database id`, `container id`, and `partition key` of your choice.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/r3hju8xo3q4kz1734bar.jpeg)

* After creating DB, select your created DB from the `SQL API` list and go ahead to select `New Item`. Enter `id` as `home` or whatever you would like to call your resume home page and `count` as Zero `0`. Click `save` and our store is ready for use.

##Building our serverless function using Azure Function
Azure Function is a serverless compute service that lets you run event-triggered code without having to explicitly provision or manage infrastructure which makes it a great choice for our use case.
####Steps
* From azure portal, search for `Function App` and select the match
* On the function App Page, select `create function`

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/5a7m5uh2aqisogkhlv42.jpeg)

* For Project details, choose your preferred Azure subscription and resource group to group your Function App. For Instance Details, Enter a function App Name of your choice which is globally unique. Select `Code` as option for Publish, Select `Node.js` as Runtime stack, Leave the remaining options as default and select `Review + Create`.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/lezbecn0h1ft7q1zxih9.jpeg)

* Once deployment is complete, Select `Go to Resource` and select `functions` on the Resource page.
* Select Add, and select `HTTP trigger` from the New Function popup. Leave the details option as default and Select `Create Function`.
* We would like update the visitor count table and get the updated count all from our Function. This is possible with Integration. Select `Integration` from the function page.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/4rlio4yp7my4y0k868ba.png)

* Select `Add Input` to add an integration to get our visitors count for a specific page. Binding Type is `Azure Cosmos DB`, Database name should be the name of our CosmosDB  and Collection name should be the name of our Cosmos DB container both created earlier. Create a new Cosmos DB account connection using your created cosmos db account. Add an SQL query to get a specific page count `SELECT * FROM c WHERE c.id = {id}`. This query selects an item from our cosmos db where `item.id` is equal to our input query id. Select `Ok` to create our input integration.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ufbtinwvf18ce3hn7gxw.png)

* Select `Add Output` to add an integration to update our visitors count for a specific page. Binding Type is `Azure Cosmos DB`, Database name should be the name of our CosmosDB created earlier and Collection name should be the name of our Cosmos DB container. Select `Ok` to create our input integration.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/02ow6430flznoj0j0l8v.png)

* Select `Code + Test` and your function should look something like this:
```
module.exports = async function (context, req, data) {
  context.bindings.outputDocument = data[0];
  context.bindings.outputDocument.count += 1;
  context.res = {
     body: data[0].count
  };
}

```
The third parameter `data` in our async function returns item from our cosmos db by running the SQL Query in the input integration we created earlier. An alternative to that would be 
`data = context.bindings.inputDocument` where `inputDocument` is the name of the input integration. 
To update the visitor count in our db, we get a reference to the item we want to update using the inputDocument binding and update the count by one before returning the result. Azure function is so smart that our changes are reflected on the returned data.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ipwhw7t4zi4ydc6gfcaj.jpeg)

* Let’s test that our function works by using the `test/run` feature. We would normally make a get request to our endpoint and query parameter of `id` with a value of `home`. We used a value of home since the item we want to get from our cosmos db was saved with an `id` of `home`. You should copy your Function App API endpoint so you can call it from your resume web page.

##Hosting our static resume on Azure storage
I would assume we all can build a simple resume using html. You can build using any frontend framework but I used plain html, css and Javascript for mine. I won’t be going into the details of building the resume so feel free to clone mine [here](https://github.com/akandeBolaji/cloud-resume-frontend). The important thing you need to understand here is you would have to fetch the visitor’s count using Javascript from our Function App API endpoint and display the result on the web page. Let’s go ahead to upload our resume on Azure storage.
####Steps 
* From azure portal, search for `storage accounts` and select the match
* On the storage accounts page, Select `add`.
* For Project details, choose your preferred Azure subscription and resource group to group your Function App. For Instance Details, Enter a storage account Name of your choice which is globally unique. Leave the remaining options as default and select `Review + Create`.
* Once deployment is complete, Select `Go to Resource`.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/ykn2owslaf38qfmu78py.png)

* Select `Static website`, on static website page, select `enable` as it's disabled by default. Enter your resume website index page and error page and click `save`. You can see the url to your static website but it’s empty since we haven’t uploaded our files. Select the `$web` container to upload your files.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/k31zkiwu8i8tj3j5zblk.png)

* Upload your files and make sure your Javascript uses the Function App api gateway to retrieve the visitor’s count.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/m1dyjdkqsiql9uf5x5rr.png)

* We need to update our function App to allow request from our static website url else we wouldn’t be able to get the visitors count. go to the Function App you created and search for `CORS`. add your static website url to list of allowed origins. Make sure to enable `Access-Control-Allow-Credentials`. Everything should work fine now.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/g9lrpagpthy5c5vvbd5k.png)
 
##Using Azure CDN to cache resume and reduce load times
Azure Content Delivery Network (CDN) lets you reduce load times, save bandwidth, and speed responsiveness.
####Steps
* Go to storage accounts and select the storage for your static website.
* search for CDN and select `create new CDN endpoint`

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/x0r7322vsn2i97io9z13.png)

* Choose `create new`, enter a name for your CDN profile. Select the `Standard Microsoft` option for pricing tier. Enter a globally unique name for CDN endpoint name and select the storage account as origin name. click `create` and wait for some minutes while it deploys your content to CDN. Don't forget to add your CDN endpoint url to list of allowed origins in your Function App.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/fe9daaoko3itpmyfa9wi.jpeg)

Here's our final result.

##Conclusion
We have successfully hosted our resume on azure storage and used Azure CDN for caching, Azure Cosmos DB to store visitor's count and Function App to retrieve the count. An added functionality on your own would be to add a custom domain to our CDN integration.