Blog
All the posts I ever wrote!
2024
- January 2 - Schemar: a GitHub Action to validate structured data
- January 30 - Bicep lint with Azure Pipelines and GitHub Actions
- February 4 - Using Bun in Azure Pipelines
- February 18 - ESLint no-unused-vars: _ ignore prefix
- March 9 - Multiline strings in .env files
- March 10 - Configure Azure connection strings and keys in Azure Bicep
- March 19 - Generate a Word document in ASP.NET
- March 20 - Text-first MUI Tabs
- April 1 - Azure Cosmos DB: container items and generics
- April 6 - Overview of webpack, a JavaScript bundler
- April 21 - Using Kernel Memory to Chunk Documents into Azure AI Search
- May 3 - Large Language Models, Open API, View Models and the Backend for Frontend Pattern
- May 12 - Serialising ASP.NET method calls for later execution
- May 25 - MUI React Tree View: check children, uncheck parents
- June 15 - Dual Publishing ESM and CJS Modules with tsup and Are the Types Wrong?
- June 18 - Static Web Apps CLI: improve performance with Vite server proxy
- June 23 - Web Workers, Comlink, Vite and TanStack Query
- July 1 - MUI React Tree View: pass data to TreeItem
- July 15 - Using AZD for faster incremental Azure Container App deployments in Azure DevOps
- August 27 - Using AZD for faster incremental Azure Static Web App deployments in GitHub Actions
- September 2 - typescript-eslint with JSDoc JavaScript
- October 7 - Static Typing for MUI React Data Grid Columns
2023
- January 1 - Using Application Insights with Bicep to monitor Azure Static Web Apps and Azure Functions
- January 5 - Azure Pipelines - Node.js 16 and custom pipelines task extensions
- January 15 - How I ruined my SEO
- January 18 - Docusaurus: improving Core Web Vitals with fetchpriority
- January 22 - Image Optimisation with the TinyPNG API
- January 28 - Docusaurus blogs: using the createFeedItems API with git commit date
- February 1 - Migrating from GitHub Pages to Azure Static Web Apps
- February 5 - Docusaurus blogs: adding breadcrumb structured data
- February 11 - In defence of pull requests
- March 9 - Node.js 18, Axios and unsafe legacy renegotiation disabled
- March 18 - Migrating from ts-node to Bun
- March 20 - Playwright, GitHub Actions and Azure Static Web Apps staging environments
- April 5 - Bicep user defined types and Bash single item arrays
- April 8 - Docusaurus: Structured Data FAQs with MDX
- May 4 - Teams Direct Message API with Power Automate
- May 8 - Migrating Azure Functions from JSDoc JavaScript to TypeScript
- May 9 - TypeScript 5: importsNotUsedAsValues replaced by ESLint consistent-type-imports
- May 20 - Static Web Apps CLI and Node.js 18: could not connect to API
- June 2 - Private Bicep registry authentication with AzureResourceManagerTemplateDeployment@3
- June 11 - Azure Container Apps, Easy Auth and .NET authentication
- June 18 - Azure Container Apps, Bicep, managed certificates and custom domains
- July 9 - TypeScript 5.1: declaring JSX element types
- July 20 - Azure Container Apps, Bicep, bring your own certificates and custom domains
- August 5 - Azure Pipelines meet Vitest
- August 17 - Azure Open AI: handling capacity and quota limits with Bicep
- September 20 - TypeScript: The Movie
- September 25 - Azure Open AI: generate article metadata with TypeScript
- October 9 - Docusaurus 3: how to migrate rehype plugins
- October 18 - Bicep: Link Azure Application Insights to Static Web Apps
- October 24 - Migrating to v4 Azure Functions Node.js with TypeScript
- November 23 - Graph API: getting users Active Directory group names and ids with the C# SDK
- November 28 - How we fixed my SEO
- December 15 - Overview of Bun, a JavaScript runtime
- December 20 - Snapshot log tests in .NET
2022
- January 22 - Azure Container Apps: dapr, devcontainer, debug and deploy
- February 2 - Lazy loading images with Docusaurus
- February 8 - Azure Static Web Apps - a Netlify alternative
- March 6 - Swashbuckle & inheritance: Give. Me. The. Types
- March 20 - Lighthouse meet GitHub Actions
- March 30 - Azure DevOps: consume a private artifact feed
- April 6 - ESLint your C# in VS Code with Roslyn Analyzers
- April 16 - Type annotations: strong types, weakly held
- May 1 - Upgrading to React 18 with TypeScript
- May 7 - Azure Static Web Apps: named preview environments with Azure DevOps
- May 28 - Azure Static Web Apps: Node.js 16 / 18 and Oryx
- June 7 - TypeScript 4.7 and ECMAScript Module Support
- June 21 - Azure Container Apps: dapr pubsub
- July 7 - Azure Static Web Apps: Failed to deploy the Azure Functions
- July 10 - Get Build Validations with the Azure DevOps API
- July 23 - Terry Pratchett and the Azure Static Web Apps
- August 31 - Swashbuckle and schemaId is already used
- September 3 - Reverse engineering the Azure Application Insights Transactions URL
- September 20 - React: storing state in URL with URLSearchParams
- September 29 - Faster Docusaurus builds with swc-loader
- October 1 - TypeScript Unit Tests with Debug Support
- October 14 - Bicep: Static Web Apps and Linked Backends
- October 20 - Getting started with the Web Monetization API
- November 11 - Debugging Azure Functions in VS Code on Mac OS
- November 17 - Azure AD Claims with Static Web Apps and Azure Functions
- November 22 - XML: read and write with Node.js
- November 25 - Adding lastmod to sitemap based on git commits
- December 1 - Docusaurus: Using fontaine to reduce custom font cumulative layout shift
- December 4 - Deep linking with Azure Static Web Apps and Easy Auth
- December 11 - Publishing Docusaurus to dev.to with the dev.to API
- December 18 - Azure Static Web Apps: build app externally
- December 22 - Azure Static Web Apps: dynamic redirects with Azure Functions
- December 26 - Serving Docusaurus images with Cloudinary
2021
- January 2 - Create React App with ts-loader and CRACO
- January 3 - react-query: strongly typing useQueries
- January 14 - Azure App Service, Easy Auth and Roles with .NET
- January 17 - Azure App Service, Easy Auth and Roles with .NET and Microsoft.Identity.Web
- January 29 - Azure Pipelines Build Info in an ASP.NET React app
- January 30 - ASP.NET, Serilog and Application Insights
- February 8 - Azure RBAC: role assignments and ARM templates
- February 11 - Azure App Service, Health checks and zero downtime deployments
- February 16 - Making Easy Auth tokens survive releases on Linux Azure App Service
- February 27 - Goodbye Client Affinity, Hello Data Protection with Azure
- March 6 - NSwag: TypeScript and CSharp client generation based on an API
- March 10 - Managed Identity, Azure SQL and Entity Framework
- March 15 - The definitive guide to migrating from Blogger to Docusaurus
- March 17 - RSS update; we moved to Docusaurus
- March 20 - Bicep meet Azure Pipelines
- March 23 - Bicep meet Azure Pipelines 2
- April 10 - Hello World Bicep
- April 20 - ts-loader goes webpack 5
- April 24 - The Service Now API and TypeScript Conditional Types
- May 1 - Blog Archive for Docusaurus
- May 8 - Create a Pipeline with the Azure DevOps API
- May 15 - Azurite and Table Storage in a dev container
- June 11 - Azure Functions and .NET 5: Query params, Dependency Injection, Bicep & Build
- June 30 - React 18 and TypeScript
- July 1 - C# 9 in-process Azure Functions
- July 7 - Output connection strings and keys from Azure Bicep
- July 11 - webpack? esbuild? Why not both?
- July 14 - Directory.Build.props: C# 9 for all your projects
- August 1 - TypeScript, abstract classes, and constructors
- August 14 - TypeScript 4.4 and more readable code
- August 15 - Publish Azure Static Web Apps with Bicep and Azure DevOps
- August 19 - Bicep: syntax highlighting with PrismJS (and Docusaurus)
- September 10 - Google APIs: authentication with TypeScript
- September 12 - Permissioning Azure Pipelines with Bicep and Azure RBAC Role Assignments
- October 15 - Structured data, SEO and React
- October 18 - Docusaurus, meta tags and Google Discover
- October 31 - NSwag generated C# client: Open API property name clashes and decimal types rather than double
- November 18 - Azure standard availability tests with Bicep
- November 22 - TypeScript vs JSDoc JavaScript
- December 5 - Azure Static Web App Deploy Previews with Azure DevOps
- December 12 - Open Graph: a guide to sharable social media previews
- December 19 - Azure Container Apps, Bicep and GitHub Actions
- December 27 - Azure Container Apps: build and deploy with Bicep and GitHub Actions
- December 28 - Query deployment outputs with the Azure CLI
- December 29 - Preload fonts with Docusaurus (updated 03/11/2022)
2020
- January 2 - EF Core 3.1 breaks left join with no navigation property
- January 21 - LICENSE to kill your PWA
- January 31 - From create-react-app to PWA
- February 21 - Web Workers, comlink, TypeScript and React
- March 22 - Dual boot authentication with ASP.NET
- March 29 - Offline storage in a PWA
- April 4 - Up to the clouds!
- May 10 - From react-window to react-virtual
- May 21 - Autofac, WebApplicationFactory and integration tests
- June 21 - Task.WhenAll / Select is a footgun 👟🔫
- July 11 - Devcontainers and SSL interception
- August 9 - Devcontainers AKA performance in a secure sandbox
- September 4 - Why your team needs a newsfeed
- October 2 - Autofac 6, integration tests and .NET generic hosting
- October 19 - Safari: The Mysterious Case of the Empty Download
- October 31 - Azure DevOps Client for Node.js - GitApi / WikiApi limitations
- November 10 - Throttling data requests with React Hooks
- November 14 - Bulletproof uniq with TypeScript generics (yay code reviews!)
- November 28 - Visual Studio Marketplace: images in Markdown!
- December 9 - azure-pipelines-task-lib and isOutput setVariable
- December 20 - Nullable reference types; CSharp's very own strictNullChecks
- December 21 - Make Microsoft.Identity.Web respond with 403 forbidden instead of a 302 redirect
- December 22 - dotnet-format: Prettier your C# with lint-staged & husky
- December 30 - Azure Pipelines meet Jest
2019
- January 5 - GitHub Actions and Yarn
- January 13 - TypeScript and webpack: Watch It
- February 22 - ASP.NET Core: Proxying HTTP Requests with an AllowList
- March 6 - fork-ts-checker-webpack-plugin v1.0
- March 22 - Google Analytics API and ASP.Net Core
- March 24 - Template Tricks for a Dainty DOM
- April 27 - react-select with less typing lag
- May 23 - TypeScript and high CPU usage - watch don't stare!
- June 7 - TypeScript / webpack - you down with PnP? Yarn, you know me!
- July 13 - Using TypeScript and ESLint with webpack (fork-ts-checker-webpack-plugin new feature!)
- August 2 - ASP.NET Core authentication: hard-coding a claim in development
- August 17 - Symbiotic Definitely Typed
- September 14 - Coming Soon: Definitely Typed
- September 30 - Start Me Up: ts-loader meet .tsbuildinfo
- October 8 - Definitely Typed: The Movie
- December 18 - Teams notification webhooks
2018
- January 14 - Auth0, TypeScript and ASP.NET Core
- January 28 - webpack 4 - ts-loader / fork-ts-checker-webpack-plugin betas
- January 29 - Finding webpack 4 (use a Map)
- February 25 - ts-loader 4 / fork-ts-checker-webpack-plugin 0.4
- March 7 - It's Not Dead: webpack and dead code elimination limitations
- March 25 - Uploading Images to Cloudinary with the Fetch API
- March 26 - It's Not Dead 2: mobx-react-devtools and the undead
- April 28 - Using Reflection to Identify Unwanted Dependencies
- May 13 - Compromising: A Guide for Developers
- June 16 - VSTS... YAML up!
- June 24 - VSTS and EF Core Migrations
- July 9 - Cypress and Auth0
- July 28 - Azure App Service: nested configuration for ASP.NET running in Web App for Containers using Application Settings
- August 21 - Using TypeScript and webpack alias: goodbye relative paths
- September 15 - Semantic Versioning and Definitely Typed
- September 23 - ts-loader Project References: First Blood
- October 7 - Brand New Fonting Awesomeness
- October 27 - Making a Programmer
- November 17 - Snapshot Testing for C#
- December 10 - IMemoryCache and GetOrCreateForTimeSpanAsync
- December 22 - You Might Not Need thread-loader
2017
- January 1 - webpack: configuring a loader with query / options
- January 6 - webpack: resolveLoader / alias with query / options
- February 1 - Hands-free HTTPS
- February 14 - @types is rogue
- February 23 - Under the Duck: An Afternoon in Open Source
- March 28 - Debugging ASP.Net Core in VS or Code
- March 30 - I'm looking for work!
- April 25 - Setting Build Version Using AppVeyor and ASP.Net Core
- May 20 - TypeScript: Spare the Rod, Spoil the Code
- June 11 - Windows Defender Step Away From npm
- July 2 - Dynamic import: I've been awaiting you...
- July 29 - A Haiku on the Problem with SemVer: Us
- August 27 - Karma: From PhantomJS to Headless Chrome
- August 30 - Oh the Glamour of Open Source
- September 7 - TypeScript + webpack: Super Pursuit Mode
- September 12 - fork-ts-checker-webpack-plugin code clickability
- October 19 - Working with Extrahop on webpack and ts-loader
- October 20 - TypeScript Definitions, webpack and Module Types
- November 19 - The TypeScript webpack PWA
- December 24 - ts-loader 2017 retrospective
2016
- January 1 - UseStaticFiles for ASP.Net Framework
- January 14 - Coded UI and the Curse of the Docking Station
- February 1 - TFS 2012, .NET 4.5 and C# 6
- February 19 - Visual Studio, tsconfig.json and external TypeScript compilation
- February 29 - Creating Angular UI Routes in the Controller
- March 4 - TFS 2012 meet PowerShell, Karma and BuildNumber
- March 17 - Atom - Recovering from Corrupted Packages
- March 22 - Concatting IEnumerables in C#
- April 25 - Instant Stubs with JSON.Net (just add hot water)
- May 13 - Inlining Angular Templates with WebPack and TypeScript
- May 24 - The Mysterious Case of webpack, AngularJS and jQuery
- June 2 - Creating an ES2015 Map from an Array in TypeScript
- July 23 - Understanding webpack's DefinePlugin (and using with TypeScript)
- August 19 - The Ternary Operator <3 Destructuring
- September 12 - Integration Tests with SQL Server Database Snapshots
- September 22 - TypeScript 2.0, ES2016 and Babel
- October 5 - React Component Curry
- November 1 - But you can't die... I love you!
- November 12 - My Subconscious is a Better Developer Than I Am
- December 11 - webpack: syncing the enhanced-resolve
- December 19 - Using ts-loader with webpack 2
2015
- January 7 - Deploying from ASP.Net MVC to GitHub Pages using AppVeyor part 2
- January 20 - TypeScript: In Praise of Union Types
- February 11 - The Convent with Continuous Delivery
- February 17 - Using Gulp to inject scripts and styles tags directly into your HTML
- February 27 - Hey tsconfig.json, where have you been all my life?
- March 20 - PartialView.ToString()
- April 17 - How to activate your emoji keyboard on Android 5.0 (Lollipop)
- April 24 - Tonight I'll Start an Open Source Project...
- May 5 - A tale of Angular, html5mode, ASP.Net MVC and ASP.Net Web API
- May 11 - NgValidationFor Baby Steps
- May 23 - Angular UI Bootstrap Datepicker Weirdness
- June 19 - Back to the Future with Code First Migrations
- June 29 - npm please stop hurting Visual Studio
- July 30 - Upgrading to Globalize 1.x for Dummies
- August 13 - (Top One, Nice One) Get Sorted
- September 10 - Things Done Changed
- September 23 - Definitely Typed Shouldn't Exist
- October 5 - jQuery Validation Globalize hits 1.0
- October 23 - The Names Have Been Changed...
- November 30 - IQueryable... IEnumerable... Hmmm...
- December 16 - ES6 + TypeScript + Babel + React + Flux + Karma: The Secret Recipe
- December 20 - Live Reload Considered Harmful
2014
- January 9 - Upgrading to TypeScript 0.9.5 - A Personal Memoir
- January 24 - Integration Testing with Entity Framework and Snapshot Backups
- February 12 - WPF and Mystic Meg or Playing Futurologist
- February 27 - TypeScript and RequireJS (Keep It Simple)
- March 5 - Caching and cache-busting with RequireJS
- March 11 - Knockout + Globalize = valueNumber Binding Handler
- March 17 - The Surprisingly Happy Tale of Visual Studio Online, Continous Integration and Chutzpah
- April 1 - TypeScript this is what I want! (the unfortunate neglect of Instance Methods / callback functions)
- May 5 - TypeScript, JSDoc and Intellisense
- May 15 - Team Foundation Server, Continuous Integration and separate projects for JavaScript unit tests
- June 1 - Migrating from AngularJS to AngularTS - a walkthrough
- June 20 - A folk story wherein we shall find dates, DataAnnotations & data impedance mismatch
- July 3 - HotTowel-Angular meet TypeScript
- August 1 - AngularJS meet ASP.Net Server Validation
- August 8 - Getting more RESTful with Web API and IHttpActionResult
- August 12 - My Unrequited Love for Isolate Scope
- September 6 - Running JavaScript Unit Tests in AppVeyor
- September 10 - Unit Testing an Angular Controller with Jasmine
- September 13 - Journalling the Migration of Jasmine Tests to TypeScript
- October 3 - He tasks me; he heaps me.... I will wreak that MOQ upon him.
- October 6 - Caching and Cache-Busting in AngularJS with HTTP interceptors
- November 4 - Using Gulp in Visual Studio instead of Web Optimization
- November 26 - Pretending to be someone you're not and the dark pit of despair
- December 5 - What's in a (Domain) Name?
- December 12 - Gulp, npm, long paths and Visual Studio.... Fight!
- December 29 - Deploying from ASP.Net MVC to GitHub Pages using AppVeyor part 1
2013
- January 3 - HTML to PDF using a WCF Service
- January 9 - Twitter.Bootstrap.MVC4 meet Bootstrap Datepicker
- January 14 - Twitter.Bootstrap.MVC4 meet Bootstrap Datepicker *and* get your Internationalization on...
- February 13 - Using Expressions with Constructors
- February 18 - Unit testing MVC controllers / Mocking UrlHelper
- March 3 - Unit testing ModelState
- March 11 - DecimalModelBinder for nullable Decimals
- April 1 - Death to compatibility mode
- April 9 - Making IE 10's clear field (X) button and jQuery UI autocomplete play nice
- April 17 - IE 10 Install Torches JavaScript Debugging in Visual Studio 2012 Through Auto Update (Probably)
- April 26 - A navigation animation (for your users delectation)
- May 4 - How I'm Using Cassette part 1:Getting Up and Running
- June 6 - How I'm Using Cassette part 2:Get Cassette to Serve Scripts in Dependency Order
- June 26 - jQuery Validation - Native Unobtrusive Validation Support!
- July 6 - How I'm Using Cassette part 3:Cassette and TypeScript Integration
- August 8 - Announcing jQuery Validation Unobtrusive Native...
- August 17 - Using Bootstrap Tooltips to display jQuery Validation error messages
- October 4 - Migrating from jquery.validate.unobtrusive.js to jQuery.Validation.Unobtrusive.Native
- October 30 - Getting TypeScript Compile-on-Save and Continuous Integration to play nice
- November 4 - TypeScript: Don't forget Build Action for Implicit Referencing...
- November 26 - Rolling your own confirm mechanism using Promises and jQuery UI
- December 4 - Simple fading in and out using CSS transitions and classes
- December 13 - NuGet and WebMatrix: How to install a specific version of a package
2012
- January 7 - Standing on the Shoulders of Giants...
- January 14 - jqGrid - it's just a far better grid
- January 24 - What on earth is jQuery? And why should I care?
- January 30 - JavaScript - getting to know the beast...
- February 5 - A Potted History of using Ajax (on the Microsoft Stack of Love)
- February 15 - WCF Transport Windows authentication using NetTcpBinding in an Intranet environment
- February 23 - The Joy of JSON
- March 3 - jQuery Unobtrusive Remote Validation
- March 12 - Striving for (JavaScript) Convention
- March 17 - Using the PubSub / Observer pattern to emulate constructor chaining without cluttering up global scope
- March 22 - WCF - moving from Config to Code, a simple WCF service harness (plus implementing your own Authorization)
- April 5 - Making PDFs from HTML in C# using WKHTMLtoPDF
- April 16 - A Simple Technique for Initialising Properties with Internal Setters for Unit Testing
- April 23 - JSHint - Customising your hurt feelings
- April 28 - Beg, Steal or Borrow a Decent JavaScript DateTime Converter
- May 7 - Globalize.js - number and date localisation made easy
- May 30 - Dad Didn't Buy Any Games
- June 4 - Reasons to be Cheerful (why now is a good time to be a dev)
- July 1 - Optimally Serving Up JavaScript
- July 16 - Rendering Partial View to a String
- August 6 - jQuery Unobtrusive Validation (+ associated gotchas)
- August 16 - ClosedXML - the real SDK for Excel
- August 24 - How to attribute encode a PartialView in MVC (Razor)
- September 6 - Globalize and jQuery Validation
- September 24 - Giving OData to CRM 4.0
- October 3 - Unit Testing and Entity Framework: The Filth and the Fury
- October 5 - Using Web Optimization with MVC 3
- October 22 - MVC 3 meet Dictionary
- November 2 - XSD/XML Schema Generator + Xsd.exe:Taking the pain out of manual XML
- November 13 - Getting up to speed with Bloomberg's Open API...