Skip to main content

· 7 min read
John Reilly

I love the Material-UI (MUI) library for React. Hand on heart, I'm not very good at making UIs that are attractive. So I always grab for something to paper over the cracks. MUI is awesome for that.

One of the components that I use frequently is the tabs component. However, I've found that it can be a little tricky to use in a "text-first" way, that also remains strongly typed. This post documents how to do just that!

title image reading "Text-first MUI Tabs" with the MUI logo

· 2 min read
John Reilly

Generating a Word document in the context of an ASP.NET controller is quite simple to do. However, it took me a little experimentation to work out just what was required. This post documents (pun very much intended) what we need to do.

title image reading "Generate a Word document in ASP.NET" with the Word and ASP.NET logos

· 5 min read
John Reilly

Imagine you're deploying a solution to Azure. It'll feature some resources like a database or a storage account. How do can you configure your application with access to these resources? One approach would be using Managed Identity. Another approach is configuring the connection strings and access keys in our application's configuration store as the Bicep templates are deployed. This is a common approach when working with Azure Functions, Azure Static Web Apps, Azure Container Apps and similar.

title image reading "Configure Azure connection strings and keys in Azure Bicep" with the Bicep and Azure logos

A wonderful aspect of this approach is that no human need ever get to see the connection strings / access keys. They'll be discovered and consumed by Azure during a deployment, and known to your application at runtime, but untrustworthy humans need never get to see them. This is secure, and therefore good.

· One min read
John Reilly

I love using .env files to configure my applications. They're a great way to keep configuration in one place and to keep it out of the codebase. They're also a great way to keep secrets out of the codebase.

But what if you need to use a multiline string in a .env file? How do you do that? You just do it:

SINGLE_LINE="you know what..."
MULTI_LINE="you know what you did
LAST SUMMER"

That's right, you just use a newline character. It's that simple. Oddly, searching for that on the internet didn't yield the answer I was looking for. So I'm writing it down here for posterity.

With your .env file in place, you can then consume it in your application using a package like dotenv. Or if you'd like to use a bash script to consume the .env file, you can do it like this:

#!/usr/bin/env bash
set -a
source test.env
set +a

npm run start # or whatever you need to do

· 6 min read
John Reilly

I'm a longtime user of TypeScripts noUnusedLocals and noUnusedParameters settings. I like to avoid leaving unused variables in my code; these compiler options help me do that.

I use ESLint alongside TypeScript. The no-unused-vars rule provides similar functionality to TypeScripts noUnusedLocals and noUnusedParameters settings, but has more power and more flexibility. For instance, no-unused-vars can catch unused error variables; TypeScript's noUnusedLocals and noUnusedParameters cannot.

One thing that I missed when switching to the ESLint option is that, with noUnusedLocals and noUnusedParameters, you can simply ignore unused variables by prefixing a variable with the _ character. That's right, sometimes I want to declare a variable that I know I'm not going to use, and I want to do that without getting shouted at by the linter.

It turns out you can get ESLint to respect the TypeScript default of ignoring variables prefixed with _; it's just not the default configuration for no-unused-vars. But with a little configuration we can have it. This post is a quick guide to how to implement that configuration.

title image reading "From TypeScript noUnusedLocals and noUnusedParameters to ESLint no-unused-vars (with _ prefix)" with the ESLint and TypeScript logo

· 2 min read
John Reilly

I'm a keen user of Bun. Bun is a fast TypeScript / JavaScript runtime which can be used to speed up the TypeScript / JavaScript you have. It's a drop-in replacement for Node.js, and it's compatible with the vast majority of the Node.js ecosystem. (There are still rough edges that have issues.) In this post we'll look at how to use it in Azure Pipelines.

title image reading "Using Bun in Azure Pipelines" with the Bun and Azure Pipelines logos

· 10 min read
John Reilly

Bicep has had linting since version 0.4.1. It's a great way to ensure that your bicep files conform to best practices. Interestingly, when the linting feature first shipped, there wasn't an explicit lint command as part of the CLI. Instead, you had to run bicep build and it would run the linter as part of the build process. This was a little confusing as it was not obvious that the linter was running.

As of version 0.21.1 there is a dedicated bicep lint command. This is a nice step forwards; it allows you to explicitly lint your your code, rather than have it happen as a side effect of build. And it is useful if you want to run the linter as part of a CI/CD pipeline. What's more the bicep lint command is now available in the Azure CLI as well. You can run az bicep lint to lint your bicep files.

In this post we'll look at how to run lint Bicep in Azure Pipelines and GitHub Actions, and surface the output in the UI.

title image reading "Bicep lint with Azure Pipelines and GitHub Actions" with the Bicep logo

· 7 min read
John Reilly

Of late, I've found myself getting more and more into structured data. Structured data is a way of adding machine-readable information to web pages. To entertain myself, I liken it to static typing for websites. I've written about structured data before, but in this post I want to focus on how to validate structured data.

Specifically, how can we validate structured data in the context of a GitHub workflow? I've created a GitHub Action called Schemar that facilitates just that. In this post we'll see how to use it.

title image reading "Schemar: a GitHub Action to validate structured data" with the GitHub Action logo

· 8 min read
John Reilly

Writing tests is important. The easier it is to write tests, the more likely they'll be written. I've long loved snapshot testing for this reason. Snapshot testing takes away the need to manually write verification code in your tests. Instead, you write tests that compare the output of a call to your method with JSON serialised output you've generated on a previous occasion. This approach takes less time to write, less time to maintain, and the solid readability of JSON makes it more likely you'll pick up on bugs. It's so much easier to scan JSON than it is a list of assertions.

Loving snapshot testing as I do, I want to show you how to write high quality and low effort log assertions using snapshot testing. The behaviour of logging code is really important; it's this that we tend to rely upon when debugging production issues. But how do you test logging code? Well, you could write a bunch of assertions that check how your logger is used. But that's a lot of work, it's not super readable and it's not fun. (Always remember: if it's not fun, you're doing it wrong.)

Instead, we'll achieve this using snapshot testing.

title image reading "Snapshot log tests in .NET" with the .NET logo

· 14 min read
John Reilly
Megan Lee

Like Node.js and Deno, Bun is a JavaScript runtime that provides a faster development experience while you’re building frontend applications. It’s gaining ground as a competitor to these widely used runtime environments — and for good reason.

In this evaluation guide, we’ll explore the features that make Bun an excellent choice for developing fast, performant, error-free frontend apps. By the end of this article, you’ll have a clear understanding of when and why you should use Bun in your projects.

title image reading "Bun overview: whats cooking" with the Bun logo

· 33 min read
John Reilly
Growtika

We might also call this:

I ruined my SEO and a stranger from Hacker News help me fix it

This is a follow up to my "How I ruined my SEO" post. That was about how my site stopped ranking in Google's search results around October 2022. This post is about how Growtika and I worked together to fix it.

As we'll see, the art of SEO (Search Engine Optimisation) is a mysterious one. We made a number of changes that we believe helped. All told, my site spent about a year out in the cold - barely surfacing in search results. But in October 2023 it started ranking again. And it's been ranking ever since.

I put that down to the assistance rendered by Growtika. What was the nature of that assistance? I'll tell you. This post is a biggie; so buckle up!

title image reading "How we fixed my SEO" with images of graphs trending upwards in the background

· 8 min read
John Reilly

The Graph API is a great way to get information about users in Azure Active Directory. I recently needed to get the names and ids of the Active Directory groups that a user was a member of. Here's how to do it with the C# SDK.

I'm writing this post as, whilst it ends up being a relatively small amount of code and configuration required, if you don't know what that is, you can end up somewhat stuck. This should hopefully unstick you.

title image reading "Graph API: getting users AD group names and ids with the C# SDK" with the Azure Graph and C# logos

· 9 min read
John Reilly

There's a new programming model available for Node.js Azure Functions known as v4. There's documentation out there for how to migrate JavaScript Azure Functions from v3 to v4, but at the time of writing, TypeScript wasn't covered.

This post fills in the gaps for a TypeScript Azure Function. It's probably worth mentioning that my blog is an Azure Static Web App with a TypeScript Node.js Azure Functions back end. So, this post is based on my experience migrating my blog to v4.

title image reading "Link Azure Application Insights to Static Web Apps with Bicep" with the Bicep and Azure Static Web App logos

· 3 min read
John Reilly

If you're looking into a Production issue with your Azure Static Web App, you'll want to be able to get to your logs as fast as possible. You can do this by linking your Static Web App to an Azure Application Insights instance. If you've used the Azure Portal to create your Static Web App, the setup phase will likely have done this for you already. But if you're using Bicep to create your Static Web App, you'll need to do this yourself.

This post will show you how to do that using Bicep.

title image reading "Link Azure Application Insights to Static Web Apps with Bicep" with the Bicep and Azure Static Web App logos

· 13 min read
John Reilly

Docusaurus v3 is on the way. One of the big changes that is coming with Docusaurus 3 is MDX 3. My blog has been built with Docusaurus 2 and I have a number of rehype plugins that I use to improve the experience of the blog. These include:

I wanted to migrate these plugins to Docusaurus 3. This post is about how I did that - and if you've got a rehype plugin it could probably provide some guidance on the changes you'd need to make.

title image reading "Migrating rehype plugins to Docusaurus 3" with the Docusaurus logos

· 10 min read
John Reilly

This post grew out of my desire to improve the metadata for my blog posts. I have been blogging for more than ten years, and the majority of my posts lack descriptions. A description is meta tag that sits in a page and describes the contents of the page. This is what this posts description meta tag looks like in HTML:

<meta
name="description"
content="Use the TypeScript Azure Open AI SDK to generate article metadata."
/>

Descriptions are important for search engine optimisation (SEO) and for accessibility. You can read up more on the topic here. I wanted to have descriptions for all my blog posts. But writing around 230 descriptions for my existing posts was not something I wanted to do manually. I wanted to automate it.

title image reading &quot;Azure Open AI: generate article metadata with TypeScript&quot; with the Azure Open AI / TypeScript logos

· One min read
John Reilly

I am excited to announce that a documentary has been made about TypeScript! It premiered on YouTube at 5pm British Summertime September 21st 2023.

I had the good fortune to be involved in the making of the documentary. In part this was thanks to my work on Definitely Typed. Another reason was my work on recording the history of DefinitelyTyped.

You can see it on YouTube here or hit play on the embedded video above. Thanks to the Keyboard Stories team for making this happen!

· 4 min read
John Reilly

We're currently in the gold rush period of AI. The world cannot get enough. A consequence of this, is that rationing is in force. It's like the end of the second world war, but with GPUs. This is a good thing, because it means that we can't just spin up as many resources as we like. It's a bad thing, for the exact same reason.

If you're making use of Azure's Open AI resources for your AI needs, you'll be aware that there are limits known as "quotas" in place. If you're looking to control how many resources you're using, you'll want to be able to control the capacity of your deployments. This is possible with Bicep.

This post grew out of a GitHub issue around the topic where people were bumping on the message the capacity should be null for standard deployment as they attempted to deploy. At the time that issue was raised, there was very little documentation on how to handle this. Since then, things have improved, but I thought it would be useful to have a post on the topic.

title image reading &quot;Azure Open AI: handling capacity and quota limits with Bicep&quot; with the Azure Open AI / Bicep logos

· 3 min read
John Reilly

This post explains how to integrate the tremendous test runner Vitest with the continuous integration platform Azure Pipelines. If you read the post on integrating with Jest, you'll recognise a lot of common ground with this. Once again we want:

  1. Tests run as part of our pipeline
  2. A failing test fails the build
  3. Test results reported in Azure Pipelines UI

title image reading &quot;Azure Pipelines meet Vitest&quot; with the Pipelines and Vitest logos

· 4 min read
John Reilly

Azure Container Apps supports custom domains via certificates. If you're looking to make use of the managed certificates in Azure Container Apps using Bicep, then you might want to take a look at this post on the topic.

This post will instead look at how we can use the "bring your own certificates" approach in Azure Container Apps using Bicep. Well, as much as that is possible; there appear to be limitations in what can be achieved with Bicep at the time of writing.

title image reading &quot;Azure Container Apps, Bicep, bring your own certificates and custom domains&quot; with the Azure Container App logos