Disclaimer: I am a former Microsoft employee, but I no longer own stock or options in the company and I am not receiving any promotional consideration for this blog post.

The site: BSG Industries Amalgamated
One of the main goals of building this site was to gain more experience building frontend UI. Another was to spend as little of my money as possible. I’m happy to say that I achieved both. I built not just a static presence on the web, but also a blog that serves dynamic content from a NoSQL database, and I’m hosting it using Azure’s collection of 65+ always-free services.

| Site Element | Description | Cost |
|---|---|---|
| Git repository | GitHub | $0 |
| CI/CD pipeline | GitHub | $0 |
| 1 production and 3 test sites | Azure Static Web Apps | $0 |
| SSL certificate | Azure Static Web Apps | $0 |
| Static content hosting | Azure Static Web Apps | $0 |
| Server-side rendering | Azure Function (via Azure Static Web Apps) | $0 |
| NoSQL Database | Azure Cosmos DB | $0 |
I had originally intended to build the site as a Single Page Application and host it through Azure Storage or Azure Static Web Apps. I also planned to add the ability to make backend calls to retrieve data through a serverless Azure Function App written in C# (because my background is in building backend systems in .NET). I thought that for cost reasons, storing blog posts in Azure Blob Storage would be cheapest.
But, as they say, ‘No plan survives the first encounter with the enemy.’ As I started to build and explore options, I decided to write the whole thing in Svelte TypeScript and use the svelte-adapter-azure-swa to deploy it to Azure Static Web Apps. Svelte adapters are used to generate build artifacts for various deployment and hosting scenarios. This adapter compiles code into an Azure Static Web App site complete with turning your server-side code into a managed Azure Function App along with the config files needed to deploy the compiled output to Azure. To make this solution even more compelling, Azure Static Web Apps can be configured to connect to GitHub and will generate GitHub Actions directly on your repository that will deploy pull requests to test sites for testing and review, and upon pull request closure will deploy to the main, production site.
The code is in a private repo, though at some point, I intend to open up the code to the public. For now, you’ll just have to take my word for it.
I built the site first as a plain vanilla Svelte 5 web presence using Skeleton Design System that integrates with Tailwind. I used Skeleton v4, but v5 was just released a few days ago, so upgrading is going in the backlog. There’s the main layout that contains the navigation header and footer, and all of the other routes are children to it. I used Tailwind’s theme features and Skeleton’s Theme Generator to create light and dark themes which can be toggled with a switch in the header.
Next, I built the blog functionality. For that, I used the server-side functionality in Svelte to handle the data retrieval, conversion from Markdown to HTML with mdsvex, and pass the formatted content to the Load function in the blog page.
I did have one issue with mdsvex that I had to work around. It kept including the {@html ...} in the resulting HTML. I tried a couple of different ways to put it directly into my +page.svelte but in the end just stripped it out with some RegEx.
const stripSvelteHtmlTags = (input: string): string => {
const svelteTagPattern = /([\s\S]*)/m;
return input.replace(svelteTagPattern, '$1');
};
The code is hosted in GitHub with GitHub Actions that are set up to deploy pull requests to a dynamically created test site which can be used to QA the changes and make sure no existing functionality is adversely affected. Completing the pull request merges changes to the main branch which are then deployed to the production site.
The site is hosted in Azure as a Static Web App which is configured with a managed Azure Function App that houses the server-side code. The blog data is stored in JSON in an Azure Cosmos DB which is a NoSQL document database.
The blog articles are written in Markdown and put into a JSON file that contains the article and metadata like author, publish date, and tags (the tags are currently only shown in the list of blog articles, but will eventually be leveraged for search and filtering in a future version). The process for generating the blog post JSON files is manual for now - I write the article in Markdown, use RegEx to search and replace all the line endings with \nand paste the result into the content property in the JSON file.
Using Svelte, I was able to build a site with static frontend content, dynamic server-side rendering, and modern cloud computing components with no recurring costs. While other cloud platforms offer free introductory rates, Azure has 65+ always-free services that come with caps and require you to manually select non-free tier plans or turn on auto-scaling in order to leverage paid, higher caps. So, I know that I won’t be getting any surprise hosting bills.1
1 At least that's the plan.