{
  "version": "https://jsonfeed.org/version/1.1",
  "title": "Because Developers are Awesome",
  "home_page_url": "https://blog.adrianhall.uk/",
  "feed_url": "https://blog.adrianhall.uk/feed.json",
  "description": "Musings about cloud development.",
  "authors": [
    {
      "name": "Adrian Hall"
    }
  ],
  "items": [
    {
      "id": "https://blog.adrianhall.uk/posts/2026/2026-07-01-cf-caching.html",
      "url": "https://blog.adrianhall.uk/posts/2026/2026-07-01-cf-caching.html",
      "title": "Caching options in Cloudflare Workers",
      "date_published": "2026-07-01T00:00:00.000Z",
      "tags": [
        "Cloud Development",
        "cloudflare"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2026/2026-06-07-agentic-testing.html",
      "url": "https://blog.adrianhall.uk/posts/2026/2026-06-07-agentic-testing.html",
      "title": "Testing in an agentic coding world",
      "date_published": "2026-06-07T00:00:00.000Z",
      "tags": [
        "Devtools",
        "ai"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2026/2026-05-28-cf-workflows.html",
      "url": "https://blog.adrianhall.uk/posts/2026/2026-05-28-cf-workflows.html",
      "title": "Build a video processing pipeline with Cloudflare",
      "date_published": "2026-05-28T00:00:00.000Z",
      "tags": [
        "Cloud Development",
        "cloudflare"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2026/2026-05-25-death-of-collaboration.html",
      "url": "https://blog.adrianhall.uk/posts/2026/2026-05-25-death-of-collaboration.html",
      "title": "Has AI killed collaboration?",
      "date_published": "2026-05-25T00:00:00.000Z",
      "tags": [
        "AI"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2026/2026-05-05-cf-workers-4.html",
      "url": "https://blog.adrianhall.uk/posts/2026/2026-05-05-cf-workers-4.html",
      "title": "Async APIs with Cloudflare Workers and Queues",
      "date_published": "2026-05-05T00:00:00.000Z",
      "tags": [
        "Cloud Development",
        "cloudflare"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2026/2026-05-01-cf-workers-3.html",
      "url": "https://blog.adrianhall.uk/posts/2026/2026-05-01-cf-workers-3.html",
      "title": "Maintaining state in a serverless world: Cloudflare Durable Objects",
      "date_published": "2026-05-01T00:00:00.000Z",
      "tags": [
        "Cloud Development",
        "cloudflare"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2026/2026-04-29-cf-workers-2.html",
      "url": "https://blog.adrianhall.uk/posts/2026/2026-04-29-cf-workers-2.html",
      "title": "Introduction to Cloudflare AI Gateway",
      "date_published": "2026-04-29T00:00:00.000Z",
      "tags": [
        "Cloud Development",
        "cloudflare"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2026/2026-04-26-cf-workers-1.html",
      "url": "https://blog.adrianhall.uk/posts/2026/2026-04-26-cf-workers-1.html",
      "title": "Introduction to Cloudflare Workers",
      "date_published": "2026-04-26T00:00:00.000Z",
      "tags": [
        "Cloud Development",
        "cloudflare"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2026/2026-04-21-dns-tools.html",
      "url": "https://blog.adrianhall.uk/posts/2026/2026-04-21-dns-tools.html",
      "title": "Tools for troubleshooting DNS",
      "date_published": "2026-04-21T00:00:00.000Z",
      "tags": [
        "Tools",
        "dns"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2026/2026-04-19-project-setup.html",
      "url": "https://blog.adrianhall.uk/posts/2026/2026-04-19-project-setup.html",
      "title": "Setting up a project for Agentic AI",
      "date_published": "2026-04-19T00:00:00.000Z",
      "tags": [
        "Devtools",
        "ai"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2026/2026-04-11-agentic-engineer-3.html",
      "url": "https://blog.adrianhall.uk/posts/2026/2026-04-11-agentic-engineer-3.html",
      "title": "Effective prompts for agentic engineering",
      "date_published": "2026-04-11T00:00:00.000Z",
      "tags": [
        "Devtools",
        "ai"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2026/2026-04-09-agentic-engineer-2.html",
      "url": "https://blog.adrianhall.uk/posts/2026/2026-04-09-agentic-engineer-2.html",
      "title": "Using Jobs-to-be-done to improve your agentic spec",
      "date_published": "2026-04-09T00:00:00.000Z",
      "tags": [
        "Devtools",
        "ai"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2026/2026-04-07-agentic-engineer-1.html",
      "url": "https://blog.adrianhall.uk/posts/2026/2026-04-07-agentic-engineer-1.html",
      "title": "Ten rules for spec-driven design",
      "date_published": "2026-04-07T00:00:00.000Z",
      "tags": [
        "Devtools",
        "ai"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2026/2026-04-05-ai-bubble.html",
      "url": "https://blog.adrianhall.uk/posts/2026/2026-04-05-ai-bubble.html",
      "title": "Are we in an AI bubble or an AI revolution?",
      "date_published": "2026-04-05T00:00:00.000Z",
      "tags": [
        "Devtools",
        "ai"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2026/2026-04-03-ai-discussion.html",
      "url": "https://blog.adrianhall.uk/posts/2026/2026-04-03-ai-discussion.html",
      "title": "The AI Maturity Model",
      "date_published": "2026-04-03T00:00:00.000Z",
      "tags": [
        "Devtools",
        "ai"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2025/2025-12-06-spec-kit.html",
      "url": "https://blog.adrianhall.uk/posts/2025/2025-12-06-spec-kit.html",
      "title": "Using SpecKit with multiple AI agents",
      "date_published": "2025-12-06T00:00:00.000Z",
      "tags": [
        "Devtools",
        "ai"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2025/2025-08-01-ai-editors.html",
      "url": "https://blog.adrianhall.uk/posts/2025/2025-08-01-ai-editors.html",
      "title": "AI Assisted Editors: A Comparison (Part 1)",
      "date_published": "2025-08-01T00:00:00.000Z",
      "tags": [
        "Devtools",
        "ai"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2025/2025-08-03-oss-ai-editors.html",
      "url": "https://blog.adrianhall.uk/posts/2025/2025-08-03-oss-ai-editors.html",
      "title": "AI Assisted Editors: A Comparison (Part 2)",
      "date_published": "2025-08-01T00:00:00.000Z",
      "tags": [
        "Devtools",
        "ai"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-10-04-aspire-keycloak-part3.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-10-04-aspire-keycloak-part3.html",
      "title": "Customizing Keycloak with Aspire - Part 3",
      "date_published": "2024-10-04T00:00:00.000Z",
      "tags": [
        "Web",
        "aspnetcore",
        "aspire",
        "keycloak"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-09-30-aspire-keycloak-part2.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-09-30-aspire-keycloak-part2.html",
      "title": "Customizing Keycloak with Aspire - Part 2",
      "date_published": "2024-09-30T00:00:00.000Z",
      "tags": [
        "Web",
        "aspnetcore",
        "aspire",
        "keycloak"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-09-26-aspire-keycloak-part1.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-09-26-aspire-keycloak-part1.html",
      "title": "Integrating Keycloak with Aspire - Part 1",
      "date_published": "2024-09-26T00:00:00.000Z",
      "tags": [
        "Web",
        "aspnetcore",
        "aspire",
        "keycloak"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-09-20-aspnet-identity-part6.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-09-20-aspnet-identity-part6.html",
      "title": "ASP.NET Identity deep dive - Part 6 (Social logins)",
      "date_published": "2024-09-20T00:00:00.000Z",
      "tags": [
        "Web",
        "aspnetcore",
        "aspnet_identity"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-09-18-aspnet-identity-part5.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-09-18-aspnet-identity-part5.html",
      "title": "ASP.NET Identity deep dive - Part 5 (Sending email)",
      "date_published": "2024-09-18T00:00:00.000Z",
      "tags": [
        "Web",
        "aspnetcore",
        "aspnet_identity"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-09-16-aspnet-identity-part4.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-09-16-aspnet-identity-part4.html",
      "title": "ASP.NET Identity deep dive - Part 4 (Password reset)",
      "date_published": "2024-09-16T00:00:00.000Z",
      "tags": [
        "Web",
        "aspnetcore",
        "aspnet_identity"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-09-14-aspnet-identity-part3.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-09-14-aspnet-identity-part3.html",
      "title": "ASP.NET Identity deep dive - Part 3 (Authentication)",
      "date_published": "2024-09-14T00:00:00.000Z",
      "tags": [
        "Web",
        "aspnetcore",
        "aspnet_identity"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-09-13-aspnet-identity-part2.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-09-13-aspnet-identity-part2.html",
      "title": "ASP.NET Identity deep dive - Part 2 (Registration)",
      "date_published": "2024-09-13T00:00:00.000Z",
      "tags": [
        "Web",
        "aspnetcore",
        "aspnet_identity"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-09-11-aspnet-identity-part1.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-09-11-aspnet-identity-part1.html",
      "title": "ASP.NET Identity deep dive - Part 1 (Project setup)",
      "date_published": "2024-09-11T00:00:00.000Z",
      "tags": [
        "Web",
        "aspnetcore",
        "aspnet_identity"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-09-09-aspire-config.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-09-09-aspire-config.html",
      "title": ".NET Aspire configuration patterns",
      "date_published": "2024-09-09T00:00:00.000Z",
      "tags": [
        "Cloud",
        "aspnetcore",
        "aspire",
        "azure_keyvault",
        "azure_appconfig"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-09-05-aspire-identity.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-09-05-aspire-identity.html",
      "title": "Local development for the cloud: Transitioning to .NET Aspire",
      "date_published": "2024-09-05T00:00:00.000Z",
      "tags": [
        "Cloud",
        "aspnetcore",
        "aspire"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-09-03-aspnetcore-options.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-09-03-aspnetcore-options.html",
      "title": "Making ASP.NET Core applications readable - the options patterns",
      "date_published": "2024-09-03T00:00:00.000Z",
      "tags": [
        "Web",
        "csharp",
        "aspnetcore"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-08-15-centrally-managed-dependencies.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-08-15-centrally-managed-dependencies.html",
      "title": "Centrally managing dependencies in your C# solutions",
      "date_published": "2024-08-15T00:00:00.000Z",
      "tags": [
        "Tips",
        "csharp",
        "dependencies"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-08-10-easy-exceptions.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-08-10-easy-exceptions.html",
      "title": "Better data validation exceptions with C#",
      "date_published": "2024-08-10T00:00:00.000Z",
      "tags": [
        "Tips",
        "csharp",
        "data_validation"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-08-08-bootstrap-in-aspnetcore.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-08-08-bootstrap-in-aspnetcore.html",
      "title": "Building Bootstrap apps from SASS with ASP.NET Core",
      "date_published": "2024-08-08T00:00:00.000Z",
      "tags": [
        "Web",
        "aspnetcore",
        "scss",
        "bootstrap"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-08-07-organizing-services-in-aspnetcore.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-08-07-organizing-services-in-aspnetcore.html",
      "title": "Organizing service injection in ASP.NET Core Minimal APIs",
      "date_published": "2024-08-07T00:00:00.000Z",
      "tags": [
        "Web",
        "aspnetcore",
        "minimal_apis"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-08-03-testing-js-projects.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-08-03-testing-js-projects.html",
      "title": "The State of JavaScript Testing Frameworks 2024",
      "date_published": "2024-08-03T00:00:00.000Z",
      "tags": [
        "Devtools",
        "testing",
        "typescript",
        "comparison"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-07-22-eslint-husky-prettier.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-07-22-eslint-husky-prettier.html",
      "title": "Enforcing code style with eslint, prettier, and husky",
      "date_published": "2024-07-22T00:00:00.000Z",
      "tags": [
        "Devtools",
        "typescript"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-07-11-swc-typescript.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-07-11-swc-typescript.html",
      "title": "Building TypeScript projects with the swc compiler",
      "date_published": "2024-07-11T00:00:00.000Z",
      "tags": [
        "Devtools",
        "typescript"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-07-10-esm-typescript.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-07-10-esm-typescript.html",
      "title": "TypeScript, ES Modules, and root-relative imports",
      "date_published": "2024-07-10T00:00:00.000Z",
      "tags": [
        "Devtools",
        "typescript"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-07-06-commonjs-to-esm.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-07-06-commonjs-to-esm.html",
      "title": "Converting a TypeScript project from CommonJS to ESM",
      "date_published": "2024-07-06T00:00:00.000Z",
      "tags": [
        "Web",
        "javascript",
        "typescript"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-06-27-react-ui-libraries.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-06-27-react-ui-libraries.html",
      "title": "The State of React UI libraries in 2024",
      "date_published": "2024-06-27T00:00:00.000Z",
      "tags": [
        "Web",
        "react",
        "javascript",
        "comparison"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-06-25-react-state-mgmt.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-06-25-react-state-mgmt.html",
      "title": "The State of React state management in 2024",
      "date_published": "2024-06-25T00:00:00.000Z",
      "tags": [
        "Web",
        "react",
        "javascript",
        "comparison"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-06-08-swa-production.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-06-08-swa-production.html",
      "title": "Build a Blog: Going to production with Azure Static Web Apps",
      "date_published": "2024-06-08T00:00:00.000Z",
      "tags": [
        "Cloud",
        "bicep",
        "azd",
        "azure_swa",
        "azure_dns"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-06-07-swa-dns.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-06-07-swa-dns.html",
      "title": "Build a Blog: Custom domains for Azure Static Web Apps",
      "date_published": "2024-06-07T00:00:00.000Z",
      "tags": [
        "Cloud",
        "bicep",
        "azd",
        "azure_swa",
        "azure_dns"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-06-06-azure-dns.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-06-06-azure-dns.html",
      "title": "Build a Blog: Set up DNS in Azure",
      "date_published": "2024-06-06T00:00:00.000Z",
      "tags": [
        "Cloud",
        "bicep",
        "azure_dns"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-06-05-swa-deploy.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-06-05-swa-deploy.html",
      "title": "Build a Blog: Deploy Azure Infrastructure three ways",
      "date_published": "2024-06-05T00:00:00.000Z",
      "tags": [
        "Cloud",
        "bicep",
        "azd",
        "azure_swa"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-06-04-devcontainers.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-06-04-devcontainers.html",
      "title": "Dev containers are a developers best friend",
      "date_published": "2024-06-04T00:00:00.000Z",
      "tags": [
        "Devtools",
        "containers",
        "jekyll"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2024/2024-01-19-pwsh-entra-appreg.html",
      "url": "https://blog.adrianhall.uk/posts/2024/2024-01-19-pwsh-entra-appreg.html",
      "title": "Create an App Registration for RBAC with PowerShell and Microsoft Graph.",
      "date_published": "2024-01-19T00:00:00.000Z",
      "tags": [
        "Cloud",
        "powershell",
        "msgraph",
        "azure_active_directory",
        "microsoft_entra"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2023/2023-07-12-cleanup-azure-resources.html",
      "url": "https://blog.adrianhall.uk/posts/2023/2023-07-12-cleanup-azure-resources.html",
      "title": "Deleting Azure resources the right way.",
      "date_published": "2023-07-12T00:00:00.000Z",
      "tags": [
        "Cloud",
        "azure",
        "powershell"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2023/2023-01-20-powershell-apim-rest.html",
      "url": "https://blog.adrianhall.uk/posts/2023/2023-01-20-powershell-apim-rest.html",
      "title": "Purge Azure API Management soft-deleted services with ease.",
      "date_published": "2023-01-20T00:00:00.000Z",
      "tags": [
        "Cloud",
        "azure",
        "powershell"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2022/2022-11-28-bicep-type-checking.html",
      "url": "https://blog.adrianhall.uk/posts/2022/2022-11-28-bicep-type-checking.html",
      "title": "Type-checking Bicep arrays and objects",
      "date_published": "2022-11-28T00:00:00.000Z",
      "tags": [
        "Cloud",
        "bicep"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2022/2022-11-21-bicep-loops-defaults.html",
      "url": "https://blog.adrianhall.uk/posts/2022/2022-11-21-bicep-loops-defaults.html",
      "title": "Bicep, loops, and defaults",
      "date_published": "2022-11-21T00:00:00.000Z",
      "tags": [
        "Cloud",
        "azure_apim",
        "bicep"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2022/2022-11-07-top-ten-production-graphql-tips.html",
      "url": "https://blog.adrianhall.uk/posts/2022/2022-11-07-top-ten-production-graphql-tips.html",
      "title": "Top Ten things to consider when taking your GraphQL service into production",
      "date_published": "2022-11-07T00:00:00.000Z",
      "tags": [
        "Cloud",
        "graphql"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2022/2022-10-10-apim-graphql-api.html",
      "url": "https://blog.adrianhall.uk/posts/2022/2022-10-10-apim-graphql-api.html",
      "title": "Build a GraphQL API on Azure API Management using Bicep",
      "date_published": "2022-10-10T00:00:00.000Z",
      "tags": [
        "Cloud",
        "azure_apim",
        "graphql",
        "bicep"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2022/2022-09-23-blazor-wasm-aad-signalr.html",
      "url": "https://blog.adrianhall.uk/posts/2022/2022-09-23-blazor-wasm-aad-signalr.html",
      "title": "Azure Active Directory Authentication for Blazor WASM (Part 4: SignalR)",
      "date_published": "2022-09-23T00:00:00.000Z",
      "tags": [
        "Web",
        "aspnetcore",
        "blazor",
        "azure_active_directory",
        "microsoft_entra",
        "signalr"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2022/2022-09-03-blazor-wasm-aad-auth-part-3.html",
      "url": "https://blog.adrianhall.uk/posts/2022/2022-09-03-blazor-wasm-aad-auth-part-3.html",
      "title": "Azure Active Directory Authentication for Blazor WASM (Part 3: Production)",
      "date_published": "2022-09-03T00:00:00.000Z",
      "tags": [
        "Web",
        "aspnetcore",
        "blazor",
        "azure_active_directory",
        "microsoft_entra"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2022/2022-09-02-blazor-wasm-aad-auth-part-2.html",
      "url": "https://blog.adrianhall.uk/posts/2022/2022-09-02-blazor-wasm-aad-auth-part-2.html",
      "title": "Azure Active Directory Authentication for Blazor WASM (Part 2: The Client)",
      "date_published": "2022-09-02T00:00:00.000Z",
      "tags": [
        "Web",
        "aspnetcore",
        "blazor",
        "azure_active_directory",
        "microsoft_entra"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2022/2022-09-01-blazor-wasm-aad-auth-part-1.html",
      "url": "https://blog.adrianhall.uk/posts/2022/2022-09-01-blazor-wasm-aad-auth-part-1.html",
      "title": "Azure Active Directory Authentication for Blazor WASM (Part 1: The Server)",
      "date_published": "2022-09-01T00:00:00.000Z",
      "tags": [
        "Web",
        "aspnetcore",
        "blazor",
        "azure_active_directory",
        "microsoft_entra"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2022/2022-08-26-adding-sass-to-blazor.html",
      "url": "https://blog.adrianhall.uk/posts/2022/2022-08-26-adding-sass-to-blazor.html",
      "title": "Building Stylesheets for Blazor with SASS",
      "date_published": "2022-08-26T00:00:00.000Z",
      "tags": [
        "Web",
        "aspnetcore",
        "blazor",
        "scss"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2022/2022-08-25-building-a-serverless-mud.html",
      "url": "https://blog.adrianhall.uk/posts/2022/2022-08-25-building-a-serverless-mud.html",
      "title": "Building a serverless MUD infrastructure in Azure",
      "date_published": "2022-08-25T00:00:00.000Z",
      "tags": [
        "Cloud",
        "azure"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2021/2021-11-12-zumo-irepository.html",
      "url": "https://blog.adrianhall.uk/posts/2021/2021-11-12-zumo-irepository.html",
      "title": "Building repositories for Azure Mobile Apps with ASP.NET 6",
      "date_published": "2021-11-12T00:00:00.000Z",
      "tags": [
        "Cloud",
        "aspnetcore",
        "azure_mobile_apps"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2021/2021-11-11-logging-with-zumo.html",
      "url": "https://blog.adrianhall.uk/posts/2021/2021-11-11-logging-with-zumo.html",
      "title": "Logging and Options for Azure Mobile Apps with ASP.NET 6",
      "date_published": "2021-11-11T00:00:00.000Z",
      "tags": [
        "Cloud",
        "aspnetcore",
        "azure_mobile_apps"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2021/2021-11-10-complex-zumo-auth.html",
      "url": "https://blog.adrianhall.uk/posts/2021/2021-11-10-complex-zumo-auth.html",
      "title": "Controlled access for Azure Mobile Apps for ASP.NET Core",
      "date_published": "2021-11-10T00:00:00.000Z",
      "tags": [
        "Cloud",
        "aspnetcore",
        "azure_mobile_apps"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2021/2021-11-09-adding-auth-to-zumo.html",
      "url": "https://blog.adrianhall.uk/posts/2021/2021-11-09-adding-auth-to-zumo.html",
      "title": "Add authentication to Azure Mobile Apps for ASP.NET Core",
      "date_published": "2021-11-09T00:00:00.000Z",
      "tags": [
        "Cloud",
        "aspnetcore",
        "azure_mobile_apps"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2021/2021-11-08-azure-mobile-apps-intro.html",
      "url": "https://blog.adrianhall.uk/posts/2021/2021-11-08-azure-mobile-apps-intro.html",
      "title": "Introducing Azure Mobile Apps for ASP.NET 6",
      "date_published": "2021-11-08T00:00:00.000Z",
      "tags": [
        "Cloud",
        "aspnetcore",
        "azure_mobile_apps"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2021/2021-06-29-api-keys-with-apim.html",
      "url": "https://blog.adrianhall.uk/posts/2021/2021-06-29-api-keys-with-apim.html",
      "title": "Adding an API Key to Azure Mobile Apps with API Management",
      "date_published": "2021-06-29T00:00:00.000Z",
      "tags": [
        "Cloud",
        "azure_apim",
        "azure_mobile_apps"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2021/2021-06-15-routing-based-on-request.html",
      "url": "https://blog.adrianhall.uk/posts/2021/2021-06-15-routing-based-on-request.html",
      "title": "Service Routing for Azure Mobile Apps with API Management",
      "date_published": "2021-06-15T00:00:00.000Z",
      "tags": [
        "Cloud",
        "azure_apim",
        "azure_mobile_apps"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2021/2021-06-11-adding-policies-to-apim.html",
      "url": "https://blog.adrianhall.uk/posts/2021/2021-06-11-adding-policies-to-apim.html",
      "title": "Enabling caching for Azure Mobile Apps with API Management",
      "date_published": "2021-06-11T00:00:00.000Z",
      "tags": [
        "Cloud",
        "azure_apim",
        "azure_mobile_apps"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2021/2021-06-08-using-apim-with-zumo.html",
      "url": "https://blog.adrianhall.uk/posts/2021/2021-06-08-using-apim-with-zumo.html",
      "title": "Using API Management with Azure Mobile Apps",
      "date_published": "2021-06-08T00:00:00.000Z",
      "tags": [
        "Cloud",
        "azure_apim",
        "azure_mobile_apps"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2021/2021-05-15-xamarin-forms-tabs.html",
      "url": "https://blog.adrianhall.uk/posts/2021/2021-05-15-xamarin-forms-tabs.html",
      "title": "Bottom Bar Tabs for your Xamarin Forms app",
      "date_published": "2021-05-15T00:00:00.000Z",
      "tags": [
        "Mobile",
        "xamarin",
        "xamarin_forms"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2021/2021-05-09-xamarin-forms-glyph-fonts.html",
      "url": "https://blog.adrianhall.uk/posts/2021/2021-05-09-xamarin-forms-glyph-fonts.html",
      "title": "Adding an icon font to your Xamarin Forms apps",
      "date_published": "2021-05-09T00:00:00.000Z",
      "tags": [
        "Mobile",
        "xamarin",
        "xamarin_forms"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2021/2021-03-10-hosting-static-assets-in-azure.html",
      "url": "https://blog.adrianhall.uk/posts/2021/2021-03-10-hosting-static-assets-in-azure.html",
      "title": "Choosing a hosting option for your web app in Azure",
      "date_published": "2021-03-10T00:00:00.000Z",
      "tags": [
        "Cloud",
        "comparison",
        "azure_swa",
        "azure_appservice",
        "azure_storage"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2020/2020-05-03-swiftui-masks.html",
      "url": "https://blog.adrianhall.uk/posts/2020/2020-05-03-swiftui-masks.html",
      "title": "Rounded corner panels and masks in SwiftUI",
      "date_published": "2020-05-03T00:00:00.000Z",
      "tags": [
        "Mobile",
        "swift",
        "swiftui"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2020/2020-04-04-deploy-to-azure.html",
      "url": "https://blog.adrianhall.uk/posts/2020/2020-04-04-deploy-to-azure.html",
      "title": "Deploy your React app to Azure",
      "date_published": "2020-04-04T00:00:00.000Z",
      "tags": [
        "Cloud",
        "javascript",
        "terraform",
        "azure_storage"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2020/2020-04-02-adding-unit-testing-to-template.html",
      "url": "https://blog.adrianhall.uk/posts/2020/2020-04-02-adding-unit-testing-to-template.html",
      "title": "Add unit testing to your React app",
      "date_published": "2020-04-02T00:00:00.000Z",
      "tags": [
        "Web",
        "testing",
        "javascript"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2020/2020-03-31-adding-storybook-to-template.html",
      "url": "https://blog.adrianhall.uk/posts/2020/2020-03-31-adding-storybook-to-template.html",
      "title": "Add visual testing to your React app with Storybook",
      "date_published": "2020-03-31T00:00:00.000Z",
      "tags": [
        "Web",
        "testing",
        "react",
        "javascript"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2020/2020-03-29-parcel-typescript-react.html",
      "url": "https://blog.adrianhall.uk/posts/2020/2020-03-29-parcel-typescript-react.html",
      "title": "Building a React app with Parcel, Typescript, SASS, and ESLint",
      "date_published": "2020-03-29T00:00:00.000Z",
      "tags": [
        "Web",
        "react",
        "javascript"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2020/2020-03-06-msal-react-redux.html",
      "url": "https://blog.adrianhall.uk/posts/2020/2020-03-06-msal-react-redux.html",
      "title": "Integrating Microsoft Login and MSAL with React and Redux",
      "date_published": "2020-03-06T00:00:00.000Z",
      "tags": [
        "Web",
        "react",
        "javascript",
        "azure_active_directory",
        "microsoft_entra"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2020/2020-02-20-vscode-flutter.html",
      "url": "https://blog.adrianhall.uk/posts/2020/2020-02-20-vscode-flutter.html",
      "title": "Pre-build steps for Flutter using Visual Studio Code",
      "date_published": "2020-02-20T00:00:00.000Z",
      "tags": [
        "Mobile",
        "flutter",
        "vscode"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2020/2020-01-20-build-gradle-files.html",
      "url": "https://blog.adrianhall.uk/posts/2020/2020-01-20-build-gradle-files.html",
      "title": "Adding a pre-build step to Android Studio builds",
      "date_published": "2020-01-20T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2020/2020-01-12-fixing-functions-deployment.html",
      "url": "https://blog.adrianhall.uk/posts/2020/2020-01-12-fixing-functions-deployment.html",
      "title": "Reducing the deployment size of your JavaScript Azure Functions",
      "date_published": "2020-01-12T00:00:00.000Z",
      "tags": [
        "Cloud",
        "azure_functions"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2020/2020-01-03-mockito-mocking-resources.html",
      "url": "https://blog.adrianhall.uk/posts/2020/2020-01-03-mockito-mocking-resources.html",
      "title": "Mocking Android resources with Mockito and Kotlin",
      "date_published": "2020-01-03T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android",
        "kotlin"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2020/2020-01-01-unit-testing-service-methods.html",
      "url": "https://blog.adrianhall.uk/posts/2020/2020-01-01-unit-testing-service-methods.html",
      "title": "Unit testing asynchronous Android network libraries",
      "date_published": "2020-01-01T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android",
        "kotlin"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2019/2019-12-24-unit-testing-android-libraries.html",
      "url": "https://blog.adrianhall.uk/posts/2019/2019-12-24-unit-testing-android-libraries.html",
      "title": "Two tips for unit testing Android libraries",
      "date_published": "2019-12-24T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android",
        "kotlin"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2019/2019-12-13-android-recyclerview-adapter.html",
      "url": "https://blog.adrianhall.uk/posts/2019/2019-12-13-android-recyclerview-adapter.html",
      "title": "Build a better RecyclerView Adapter",
      "date_published": "2019-12-13T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android",
        "kotlin"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2019/2019-11-05-swiftui-location.html",
      "url": "https://blog.adrianhall.uk/posts/2019/2019-11-05-swiftui-location.html",
      "title": "Handle location and geocoding with SwiftUI",
      "date_published": "2019-11-05T00:00:00.000Z",
      "tags": [
        "Mobile",
        "swift",
        "swiftui"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2019/2019-11-02-swiftui-bubble-background.html",
      "url": "https://blog.adrianhall.uk/posts/2019/2019-11-02-swiftui-bubble-background.html",
      "title": "Create a bubble background in SwiftUI",
      "date_published": "2019-11-02T00:00:00.000Z",
      "tags": [
        "Mobile",
        "swift",
        "swiftui"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2019/2019-10-31-swiftui-intro.html",
      "url": "https://blog.adrianhall.uk/posts/2019/2019-10-31-swiftui-intro.html",
      "title": "Why SwiftUI might just convert me to an iOS developer",
      "date_published": "2019-10-31T00:00:00.000Z",
      "tags": [
        "Mobile",
        "swift",
        "swiftui"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2019/2019-10-23-terraform-functions.html",
      "url": "https://blog.adrianhall.uk/posts/2019/2019-10-23-terraform-functions.html",
      "title": "Deploying an Azure Function App with Terraform",
      "date_published": "2019-10-23T00:00:00.000Z",
      "tags": [
        "Cloud",
        "azure_functions",
        "terraform"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2019/2019-10-07-validating-permissions.html",
      "url": "https://blog.adrianhall.uk/posts/2019/2019-10-07-validating-permissions.html",
      "title": "Validating permissions on Android with Kotlin",
      "date_published": "2019-10-07T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android",
        "kotlin"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2019/2019-09-22-azure-app-config.html",
      "url": "https://blog.adrianhall.uk/posts/2019/2019-09-22-azure-app-config.html",
      "title": "Using Azure App Configuration for Remote Config with Android",
      "date_published": "2019-09-22T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android",
        "kotlin",
        "azure_appconfig"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2019/2019-06-30-building-an-efficient-logger-in-typescript.html",
      "url": "https://blog.adrianhall.uk/posts/2019/2019-06-30-building-an-efficient-logger-in-typescript.html",
      "title": "Building an efficient Logger in TypeScript",
      "date_published": "2019-06-30T00:00:00.000Z",
      "tags": [
        "Cloud",
        "typescript"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2019/2019-02-12-documenting-opensource-projects.html",
      "url": "https://blog.adrianhall.uk/posts/2019/2019-02-12-documenting-opensource-projects.html",
      "title": "Documenting open-source projects",
      "date_published": "2019-02-12T00:00:00.000Z",
      "tags": [
        "Tips",
        "documentation"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2019/2019-02-06-where-do-you-start-with-graphql.html",
      "url": "https://blog.adrianhall.uk/posts/2019/2019-02-06-where-do-you-start-with-graphql.html",
      "title": "Where do you start with GraphQL? I asked four engineers",
      "date_published": "2019-02-06T00:00:00.000Z",
      "tags": [
        "Cloud",
        "graphql"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2019/2019-01-31-which-aws-service-for-hosting.html",
      "url": "https://blog.adrianhall.uk/posts/2019/2019-01-31-which-aws-service-for-hosting.html",
      "title": "What AWS service should you use to publish a web site?",
      "date_published": "2019-01-31T00:00:00.000Z",
      "tags": [
        "Cloud",
        "aws_amplify",
        "comparison"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2019/2019-01-15-three-ways-graphql-react-awsappsync.html",
      "url": "https://blog.adrianhall.uk/posts/2019/2019-01-15-three-ways-graphql-react-awsappsync.html",
      "title": "The three ways to execute a GraphQL query from React with AWS AppSync (and how to choose)",
      "date_published": "2019-01-15T00:00:00.000Z",
      "tags": [
        "Cloud",
        "aws_appsync",
        "graphql"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2019/2019-01-03-early-return-from-graphql-resolvers.html",
      "url": "https://blog.adrianhall.uk/posts/2019/2019-01-03-early-return-from-graphql-resolvers.html",
      "title": "Early return from GraphQL Resolvers with AWS AppSync",
      "date_published": "2019-01-03T00:00:00.000Z",
      "tags": [
        "Cloud",
        "aws_appsync",
        "graphql"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-12-18-handling-file-uploads-with-aws-appsync.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-12-18-handling-file-uploads-with-aws-appsync.html",
      "title": "Handling File Uploads with AWS AppSync",
      "date_published": "2018-12-18T00:00:00.000Z",
      "tags": [
        "Cloud",
        "aws_appsync",
        "graphql"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-12-10-bootstrapping-a-react-native-app.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-12-10-bootstrapping-a-react-native-app.html",
      "title": "Bootstrapping a React Native App: A Comparison",
      "date_published": "2018-12-10T00:00:00.000Z",
      "tags": [
        "Mobile",
        "react_native",
        "comparison"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-11-05-auth-with-aws-amplify-8.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-11-05-auth-with-aws-amplify-8.html",
      "title": "Authentication with AWS Amplify and Android: Fraud Protection and Analytics",
      "date_published": "2018-11-05T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android",
        "kotlin",
        "aws_amplify"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-10-29-auth-with-aws-amplify-7.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-10-29-auth-with-aws-amplify-7.html",
      "title": "Authentication with AWS Amplify and Android: Integrating Biometrics",
      "date_published": "2018-10-29T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android",
        "kotlin",
        "aws_amplify"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-10-26-backend-graphql-trigger-appsync.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-10-26-backend-graphql-trigger-appsync.html",
      "title": "Backend GraphQL: How to trigger an AWS AppSync mutation from AWS Lambda",
      "date_published": "2018-10-26T00:00:00.000Z",
      "tags": [
        "Cloud",
        "aws_appsync",
        "graphql"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-10-22-auth-with-aws-amplify-6.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-10-22-auth-with-aws-amplify-6.html",
      "title": "Authentication with AWS Amplify and Android: Integrating TOTP",
      "date_published": "2018-10-22T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android",
        "kotlin",
        "aws_amplify"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-10-15-auth-with-aws-amplify-5.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-10-15-auth-with-aws-amplify-5.html",
      "title": "Authentication with AWS Amplify and Android: 3rd Party OIDC Providers",
      "date_published": "2018-10-15T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android",
        "kotlin",
        "aws_amplify"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-10-08-auth-with-aws-amplify-4.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-10-08-auth-with-aws-amplify-4.html",
      "title": "Authentication with AWS Amplify and Android: Google Login",
      "date_published": "2018-10-08T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android",
        "kotlin",
        "aws_amplify"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-10-02-learn-to-build-modern-apps-with-aws-amplify-and-serverless.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-10-02-learn-to-build-modern-apps-with-aws-amplify-and-serverless.html",
      "title": "Learn to build mobile and web apps with AWS Amplify and Serverless Framework",
      "date_published": "2018-10-02T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android",
        "kotlin",
        "aws_amplify",
        "serverless"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-10-01-auth-with-aws-amplify-3.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-10-01-auth-with-aws-amplify-3.html",
      "title": "Authentication with AWS Amplify and Android: Facebook Login",
      "date_published": "2018-10-01T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android",
        "kotlin",
        "aws_amplify"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-09-23-auth-with-aws-amplify-2.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-09-23-auth-with-aws-amplify-2.html",
      "title": "Authentication with AWS Amplify and Android: Customizing the UI",
      "date_published": "2018-09-23T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android",
        "kotlin",
        "aws_amplify"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-09-18-auth-with-aws-amplify-1.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-09-18-auth-with-aws-amplify-1.html",
      "title": "Authentication with AWS Amplify and Android: The Basics",
      "date_published": "2018-09-18T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android",
        "kotlin",
        "aws_amplify"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-09-11-endpoint-profiles-with-aws-amplify.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-09-11-endpoint-profiles-with-aws-amplify.html",
      "title": "Let your analytics drive engagement: Endpoint profiles with AWS Amplify and Android",
      "date_published": "2018-09-11T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android",
        "kotlin",
        "aws_amplify"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-09-04-integrate-analytics-with-aws-amplify.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-09-04-integrate-analytics-with-aws-amplify.html",
      "title": "Integrate Analytics into your Android applications with AWS Amplify",
      "date_published": "2018-09-04T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android",
        "kotlin",
        "aws_amplify"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-08-29-build-a-graphql-service-the-easy-way.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-08-29-build-a-graphql-service-the-easy-way.html",
      "title": "Build a GraphQL Service the easy way with AWS Amplify Model Transforms",
      "date_published": "2018-08-29T00:00:00.000Z",
      "tags": [
        "Cloud",
        "aws_appsync",
        "graphql"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-08-27-native-development-with-aws-amplify.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-08-27-native-development-with-aws-amplify.html",
      "title": "Native Android Development with AWS Amplify",
      "date_published": "2018-08-27T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-08-14-how-to-deploy-graphql-api-serverless-framework.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-08-14-how-to-deploy-graphql-api-serverless-framework.html",
      "title": "How to deploy a GraphQL API on AWS with the Serverless Framework",
      "date_published": "2018-08-14T00:00:00.000Z",
      "tags": [
        "Cloud",
        "aws_appsync",
        "graphql",
        "serverless"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-08-08-converting-types-with-room-and-kotlin.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-08-08-converting-types-with-room-and-kotlin.html",
      "title": "Converting types with Room and Kotlin",
      "date_published": "2018-08-08T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android",
        "kotlin"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-07-20-build-a-graphql-weather-api-with-openweathermap-and-aws-appsync.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-07-20-build-a-graphql-weather-api-with-openweathermap-and-aws-appsync.html",
      "title": "Build a GraphQL Weather API with OpenWeatherMap and AWS AppSync",
      "date_published": "2018-07-20T00:00:00.000Z",
      "tags": [
        "Cloud",
        "aws_appsync",
        "graphql"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-07-04-run-typescript-mocha-tests-in-vscode.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-07-04-run-typescript-mocha-tests-in-vscode.html",
      "title": "Run TypeScript Mocha Tests in Visual Studio Code",
      "date_published": "2018-07-04T00:00:00.000Z",
      "tags": [
        "Web",
        "testing",
        "typescript"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-06-20-implementing-search-on-type-in-android-with-rxjava.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-06-20-implementing-search-on-type-in-android-with-rxjava.html",
      "title": "Implement Search-on-type in Android with RxJava",
      "date_published": "2018-06-20T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android",
        "kotlin"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-06-19-build-a-universal-search-api-with-graphql.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-06-19-build-a-universal-search-api-with-graphql.html",
      "title": "Build a Universal Search API with GraphQL and AWS AppSync",
      "date_published": "2018-06-19T00:00:00.000Z",
      "tags": [
        "Cloud",
        "aws_appsync",
        "graphql"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-06-01-how-developers-can-auth-with-aws-appsync.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-06-01-how-developers-can-auth-with-aws-appsync.html",
      "title": "How developers can authenticate and authorize users with AWS AppSync",
      "date_published": "2018-06-01T00:00:00.000Z",
      "tags": [
        "Cloud",
        "aws_appsync",
        "graphql"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-05-12-unit-testing-with-kotlin.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-05-12-unit-testing-with-kotlin.html",
      "title": "Unit Testing in Android Studio with Kotlin",
      "date_published": "2018-05-12T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android",
        "kotlin",
        "testing"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-04-11-easy-edittext-content-validation-with-kotlin.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-04-11-easy-edittext-content-validation-with-kotlin.html",
      "title": "Easy EditText content validation with Kotlin",
      "date_published": "2018-04-11T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android",
        "kotlin"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-04-06-using-dependency-injection-with-koin.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-04-06-using-dependency-injection-with-koin.html",
      "title": "Using dependency injection with Kotlin",
      "date_published": "2018-04-06T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android",
        "kotlin"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-04-01-lessons-in-kotlin-the-toolbar-icons-reflection.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-04-01-lessons-in-kotlin-the-toolbar-icons-reflection.html",
      "title": "Lessons in Kotlin: Toolbar Icons and Reflection",
      "date_published": "2018-04-01T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android",
        "kotlin"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-03-29-lessons-in-kotlin-animated-splash-screen.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-03-29-lessons-in-kotlin-animated-splash-screen.html",
      "title": "Lessons in Kotlin Threading: An Animated Splash Screen",
      "date_published": "2018-03-29T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android",
        "kotlin"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-03-23-the-react-toolbox-2018-edition.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-03-23-the-react-toolbox-2018-edition.html",
      "title": "The React Toolbox - 2018 Edition",
      "date_published": "2018-03-23T00:00:00.000Z",
      "tags": [
        "Web",
        "react",
        "javascript"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-03-21-why-im-refactoring-to-kotlin.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-03-21-why-im-refactoring-to-kotlin.html",
      "title": "Why I'm refactoring to Kotlin",
      "date_published": "2018-03-21T00:00:00.000Z",
      "tags": [
        "Mobile",
        "android",
        "kotlin"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-03-11-testing-mobile-apps-a-primer.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-03-11-testing-mobile-apps-a-primer.html",
      "title": "Testing Mobile Apps: A Primer",
      "date_published": "2018-03-11T00:00:00.000Z",
      "tags": [
        "Mobile",
        "testing"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-03-10-the-six-mobile-apps-you-should-write.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-03-10-the-six-mobile-apps-you-should-write.html",
      "title": "The Six Mobile Apps You Should Write",
      "date_published": "2018-03-10T00:00:00.000Z",
      "tags": [
        "Mobile"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2018/2018-01-19-creating-a-react-native-bridge-library.html",
      "url": "https://blog.adrianhall.uk/posts/2018/2018-01-19-creating-a-react-native-bridge-library.html",
      "title": "Creating a React Native bridge library",
      "date_published": "2018-01-19T00:00:00.000Z",
      "tags": [
        "Mobile",
        "react_native"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2017/2017-08-21-asyncstorage-typescript-and-async-await-in-react-native.html",
      "url": "https://blog.adrianhall.uk/posts/2017/2017-08-21-asyncstorage-typescript-and-async-await-in-react-native.html",
      "title": "AsyncStorage, TypeScript, and Async/await in React Native",
      "date_published": "2017-08-21T00:00:00.000Z",
      "tags": [
        "Mobile",
        "react_native",
        "async_programming",
        "typescript"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2017/2017-08-16-building-a-master-detail-pattern-in-react-native.html",
      "url": "https://blog.adrianhall.uk/posts/2017/2017-08-16-building-a-master-detail-pattern-in-react-native.html",
      "title": "Building a Master-Detail Pattern in React Native",
      "date_published": "2017-08-16T00:00:00.000Z",
      "tags": [
        "Mobile",
        "react_native",
        "typescript"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2017/2017-08-14-universal-ios-apps-with-react-native.html",
      "url": "https://blog.adrianhall.uk/posts/2017/2017-08-14-universal-ios-apps-with-react-native.html",
      "title": "Universal iOS Apps with React Native",
      "date_published": "2017-08-14T00:00:00.000Z",
      "tags": [
        "Mobile",
        "react_native"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2017/2017-08-11-integrating-react-native-typescript-mobx.html",
      "url": "https://blog.adrianhall.uk/posts/2017/2017-08-11-integrating-react-native-typescript-mobx.html",
      "title": "Integrating React Native, TypeScript, and MobX",
      "date_published": "2017-08-11T00:00:00.000Z",
      "tags": [
        "Mobile",
        "react_native",
        "typescript"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2017/2017-08-09-debugging-react-native-with-typescript-and-vscode.html",
      "url": "https://blog.adrianhall.uk/posts/2017/2017-08-09-debugging-react-native-with-typescript-and-vscode.html",
      "title": "Debugging React Native with TypeScript and Visual Studio Code",
      "date_published": "2017-08-09T00:00:00.000Z",
      "tags": [
        "Mobile",
        "react_native",
        "debugging",
        "typescript"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2017/2017-08-07-implementing-swipe-right-on-a-react-native-flatlist.html",
      "url": "https://blog.adrianhall.uk/posts/2017/2017-08-07-implementing-swipe-right-on-a-react-native-flatlist.html",
      "title": "Implementing swipe-right on a React Native FlatList",
      "date_published": "2017-08-07T00:00:00.000Z",
      "tags": [
        "Mobile",
        "react_native"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2017/2017-07-26-handling-orientation-changes-in-react-native.html",
      "url": "https://blog.adrianhall.uk/posts/2017/2017-07-26-handling-orientation-changes-in-react-native.html",
      "title": "Handling orientation changes in React Native",
      "date_published": "2017-07-26T00:00:00.000Z",
      "tags": [
        "Mobile",
        "react_native"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2017/2017-06-19-the-things-i-like-about-swift.html",
      "url": "https://blog.adrianhall.uk/posts/2017/2017-06-19-the-things-i-like-about-swift.html",
      "title": "The things I like (and don't like) about Swift?",
      "date_published": "2017-06-19T00:00:00.000Z",
      "tags": [
        "Mobile",
        "swift"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2017/2017-05-25-reactnative-vs-xamarinforms.html",
      "url": "https://blog.adrianhall.uk/posts/2017/2017-05-25-reactnative-vs-xamarinforms.html",
      "title": "Which is better - React Native or Xamarin Forms?",
      "date_published": "2017-05-25T00:00:00.000Z",
      "tags": [
        "Mobile",
        "react_native",
        "xamarin",
        "comparisons"
      ]
    },
    {
      "id": "https://blog.adrianhall.uk/posts/2017/2017-05-08-building-a-service-in-the-cloud.html",
      "url": "https://blog.adrianhall.uk/posts/2017/2017-05-08-building-a-service-in-the-cloud.html",
      "title": "Building a service in the Cloud",
      "date_published": "2017-05-08T00:00:00.000Z",
      "tags": [
        "Cloud",
        "serverless"
      ]
    }
  ]
}