Hugo and server side compute on Azure Static Web Apps

This site was made to Play with Azure Static Websites and Hugo. I intend to Add some Azure Functions and see how much I can get out of the Technology

Azure Function Example Code :

Please Enter your Name :

Building the above

The form’s functionality is powered by a two-pronged architecture:

  1. Client-side rendering: Utilizes Hugo Shortcode, a lightweight templating system, for efficient on-demand content generation, minimizing server load.

  2. Serverless logic: Leverages Azure Functions, integrated within Azure Static Web Apps, for dynamic processing and execution of business logic at scale. This cost-effective approach capitalizes on the built-in hosting capabilities of Static Web Apps, avoiding dedicated server infrastructure expenses.

Client Side

The Hugo Shortcode is a simple HTML form with a single function that Handles the XHR request to the server, given that these are on the same FQDN (Fully Qualified Domain Name) there is no need to worry about CORS (Cross-Origin Resource Sharing)

<div>
    Please Enter your Name : <br/>
    <Input id="helloName" title="Enter Name Here" /> 
    <button onclick="UpdateHelloWorld()" >Submit</button> <br/>
    <label id="helloWorld"></label>    
</div>
<script>
    const helloWorldLabel = document.getElementById('helloWorld')
    const helloWorldInput = document.getElementById('helloName')
    function UpdateHelloWorld() {
        var guestName = helloWorldInput.value;
        const xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
                console.log("Response - " + xhttp.responseText)
                helloWorldLabel.innerText = this.responseText;
            }
        };

        xhttp.open("POST", "/api/HelloWorld", true);
        xhttp.send('{"Name":"' + guestName + '"}');
    }
</script>

Server Side

For this example all that is required is a simple REST endpoint

Program.cs

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Linq;

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices(s =>
    {
        s.Configure<LoggerFilterOptions>(options =>
        {
            LoggerFilterRule toRemove = options.Rules.FirstOrDefault(rule => rule.ProviderName
                == "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider");

            if (toRemove is not null)
            {
                options.Rules.Remove(toRemove);
            }
        });
    })
    .Build();

await host.RunAsync();

HelloWorldRequest.cs

This is a simple Request model

namespace api.Requests;
public record HelloWorldRequest(string Name);

HelloWorldFunction.cs

Simple example HTTP function that takes a request body and returns an output

using System.IO;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using api.Requests;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using System.Text.Json;
using System.Net;

namespace api;
public class HelloWorldFunction(ILoggerFactory loggerFactory)
{
    private readonly ILogger _logger = loggerFactory.CreateLogger<HelloWorldFunction>(); 

    [Function("HelloWorld")]
    public async Task<HttpResponseData> Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequestData req)
    {
        string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
        var data = JsonSerializer.Deserialize<HelloWorldRequest>(requestBody);

        string responseMessage = string.IsNullOrEmpty(data.Name)
            ? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
            : $"Hello, {data.Name}. This HTTP triggered function executed successfully.";

        _logger.LogInformation(responseMessage);

        var response = req.CreateResponse(HttpStatusCode.OK);
        response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
        response.WriteString(responseMessage);

        return response;
    }
}