<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Harsh Gupta</title>
    <description>The latest articles on DEV Community by Harsh Gupta (@harshgupta71).</description>
    <link>https://dev.to/harshgupta71</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3214964%2Ff4e79036-4c0a-457a-8b86-b82b14a88f99.jpg</url>
      <title>DEV Community: Harsh Gupta</title>
      <link>https://dev.to/harshgupta71</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/harshgupta71"/>
    <language>en</language>
    <item>
      <title>How to Configure keyVaultReferenceIdentity in Azure App Service?</title>
      <dc:creator>Harsh Gupta</dc:creator>
      <pubDate>Sat, 25 Jul 2026 00:00:47 +0000</pubDate>
      <link>https://dev.to/harshgupta71/how-to-configure-keyvaultreferenceidentity-in-azure-app-service-3d8c</link>
      <guid>https://dev.to/harshgupta71/how-to-configure-keyvaultreferenceidentity-in-azure-app-service-3d8c</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;This guide shows you how to fix a critical Azure App Service configuration issue where the &lt;code&gt;keyVaultReferenceIdentity&lt;/code&gt; property is hidden from the Azure Portal but required for accessing Key Vault secrets.&lt;/p&gt;

&lt;h2&gt;
  
  
  Symptoms
&lt;/h2&gt;

&lt;p&gt;Developers encountering this issue typically observe:&lt;/p&gt;

&lt;p&gt;Key Vault references returning empty values instead of secret content&lt;br&gt;
Configuration entries showing "Not Resolved" error messages&lt;br&gt;
Application settings failing to fetch secret values from Key Vault&lt;br&gt;
Authentication errors when attempting to access protected secrets&lt;br&gt;
401/403 errors from App Service attempting to validate Key Vault access&lt;/p&gt;
&lt;h2&gt;
  
  
  Why This Happens
&lt;/h2&gt;

&lt;p&gt;Azure App Service uses Managed Identity authentication to access Key Vault secrets, but the &lt;code&gt;keyVaultReferenceIdentity&lt;/code&gt; property is deliberately hidden from standard Azure Portal interfaces. This property only exists at the Azure Resource Manager (ARM) level, making it invisible through the typical Azure management UI.&lt;/p&gt;
&lt;h3&gt;
  
  
  Technical Architecture
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;App Service → Managed Identity → Azure AD → Key Vault Access Policy → Secret Store

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;App Service attempts to authenticate using its assigned Managed Identity&lt;br&gt;
Azure needs explicit permission through the &lt;code&gt;keyVaultReferenceIdentity&lt;/code&gt; property&lt;br&gt;
This permission exists only in the underlying ARM configuration&lt;br&gt;
Without this configuration, the authentication chain breaks&lt;br&gt;
Key Vault references resolve to empty values or error messages&lt;/p&gt;
&lt;h3&gt;
  
  
  Why Portal Visibility is Limited
&lt;/h3&gt;

&lt;p&gt;Microsoft implements this design choice for several reasons:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security&lt;/strong&gt;: Keeps identity-to-Key Vault mappings out of standard management interfaces&lt;br&gt;
&lt;strong&gt;Simplicity&lt;/strong&gt;: Prevents accidental misconfigurations that could cause security issues&lt;br&gt;
&lt;strong&gt;Audit Trail&lt;/strong&gt;: Ensures all identity configurations go through proper change management&lt;br&gt;
&lt;strong&gt;Resource Provider&lt;/strong&gt;: Some properties require ARM-level configuration for consistency&lt;/p&gt;
&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Required Azure Resources
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Azure Subscription&lt;/strong&gt;: Active subscription with appropriate permissions&lt;br&gt;
&lt;strong&gt;Azure App Service&lt;/strong&gt;: Existing Linux or Windows App Service&lt;br&gt;
&lt;strong&gt;User-Assigned Managed Identity&lt;/strong&gt;: Pre-created Managed Identity for the App Service&lt;br&gt;
&lt;strong&gt;Azure Key Vault&lt;/strong&gt;: Key Vault with access policies configured for the Managed Identity&lt;/p&gt;
&lt;h3&gt;
  
  
  Required Tools and Permissions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Azure CLI&lt;/strong&gt;: Version 2.0+ installed locally&lt;br&gt;
&lt;strong&gt;PowerShell&lt;/strong&gt;: Azure Az module installed&lt;br&gt;
&lt;strong&gt;RBAC Permissions&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Contributor&lt;/code&gt; or &lt;code&gt;Owner&lt;/code&gt; role on App Service resource&lt;br&gt;
&lt;code&gt;Reader&lt;/code&gt; role minimum for resource listing&lt;br&gt;
Key Vault access policies granting &lt;code&gt;Get Secret&lt;/code&gt; permissions&lt;/p&gt;
&lt;h3&gt;
  
  
  Environment Setup
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install required Azure CLI extensions&lt;/span&gt;
az extension add &lt;span class="nt"&gt;--name&lt;/span&gt; keyvault

&lt;span class="c"&gt;# Verify Azure CLI installation&lt;/span&gt;
az &lt;span class="nt"&gt;--version&lt;/span&gt;

&lt;span class="c"&gt;# Login to Azure (if not already authenticated)&lt;/span&gt;
az login

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Step-by-Step Solution Guide
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Step 1: Prepare Your PowerShell Environment
&lt;/h3&gt;

&lt;p&gt;Initialize your PowerShell session and clear any cached authentication tokens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Connect to Azure (if not already connected)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Connect-AzAccount&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Clear any cached authentication tokens&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Clear-AzTokenCache&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Verify current authentication status&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Get-AzContext&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Target the Correct Azure Subscription
&lt;/h3&gt;

&lt;p&gt;Set the correct subscription context for your infrastructure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# List all accessible subscriptions&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Get-AzSubscription&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;State&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Set your target subscription&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Set-AzContext&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-SubscriptionId&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"YOUR-SUBSCRIPTION-ID"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Execute the ARM Fix Script
&lt;/h3&gt;

&lt;p&gt;Apply the required KeyVault Reference Identity configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# =========================================================================&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# FIX: App Service KeyVault Reference Identity Configuration Script&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# =========================================================================&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# 1. Configure your deployment variables&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$subscriptionId&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"YOUR-SUBSCRIPTION-ID"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$resourceGroup&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-resource-group-name"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$identityName&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-managed-identity-name"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$appName&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-app-service-name"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# 2. Construct the User-Assigned Identity Resource URL&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$identityUrl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/subscriptions/&lt;/span&gt;&lt;span class="nv"&gt;$subscriptionId&lt;/span&gt;&lt;span class="s2"&gt;/resourceGroups/&lt;/span&gt;&lt;span class="nv"&gt;$resourceGroup&lt;/span&gt;&lt;span class="s2"&gt;/providers/Microsoft.ManagedIdentity/userAssignedIdentities/&lt;/span&gt;&lt;span class="nv"&gt;$identityName&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# 3. Retrieve the App Service's resource ID&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$appUrl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Get-AzWebApp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ResourceGroupName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$resourceGroup&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$appName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ExpandProperty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Id&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# 4. Prepare the ARM PATCH request payload&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$uriPath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"{0}?api-version=2021-01-01"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-f&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$appUrl&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$payload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nx"&gt;properties&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nx"&gt;keyVaultReferenceIdentity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$identityUrl&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ConvertTo-Json&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Depth&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;3&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# 5. Execute the API update request&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Invoke-AzRestMethod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Method&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;PATCH&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$uriPath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Payload&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$payload&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# 6. Verify successful execution&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Content&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ConvertFrom-Json&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Complete Verification Process
&lt;/h3&gt;

&lt;p&gt;After script execution, complete these validation steps:&lt;/p&gt;

&lt;h4&gt;
  
  
  Restart App Service
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Azure Portal&lt;/strong&gt;: Navigate to App Service → Overview → Restart button&lt;br&gt;
&lt;strong&gt;PowerShell&lt;/strong&gt;: &lt;code&gt;Restart-AzWebApp -ResourceGroupName $resourceGroup -Name $appName&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: Force reload of new identity configuration&lt;/p&gt;

&lt;h4&gt;
  
  
  Validate Application Settings
&lt;/h4&gt;

&lt;p&gt;Access your App Service in Azure Portal&lt;br&gt;
Navigate to Settings → Configuration → Application Settings&lt;br&gt;
Locate Key Vault reference entries&lt;br&gt;
Confirm green checkmarks (✅) indicate successful resolution&lt;br&gt;
Verify secrets display values like &lt;code&gt;@Microsoft.KeyVault(VaultName={your-key-vault-name},SecretName={your-secret-name})&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Test Secret Access
&lt;/h4&gt;

&lt;p&gt;Check application logs for resolution status&lt;br&gt;
Verify actual secret values are accessible&lt;br&gt;
Confirm application functionality with Key Vault integration&lt;/p&gt;

&lt;h4&gt;
  
  
  Success Checklist
&lt;/h4&gt;

&lt;p&gt;User-Assigned Managed Identity assigned to App Service&lt;br&gt;
 PowerShell script executed without errors&lt;br&gt;
 App Service restarted successfully&lt;br&gt;
 Green checkmarks visible in Application Settings&lt;br&gt;
 Secret values properly resolved&lt;br&gt;
 Application functions normally&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Issues and Troubleshooting
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Issue: "Not Resolved" Errors Persist
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Root Cause&lt;/strong&gt;: User-Assigned Managed Identity not attached to App Service&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Verify identity assignment in Azure Portal:&lt;/p&gt;

&lt;p&gt;Open your App Service in Azure Portal&lt;br&gt;
Navigate to Identity → User assigned → Assigned identities&lt;br&gt;
Confirm your Managed Identity is listed and enabled&lt;/p&gt;

&lt;h3&gt;
  
  
  Issue: Permission Denied
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Root Cause&lt;/strong&gt;: Insufficient RBAC permissions&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Grant required permissions:&lt;/p&gt;

&lt;p&gt;Navigate to your App Service → Access control (IAM)&lt;br&gt;
Add Contributor role for comprehensive permissions&lt;br&gt;
Alternative: Grant specific &lt;code&gt;Microsoft.Web/sites/write&lt;/code&gt; permission&lt;/p&gt;

&lt;h3&gt;
  
  
  Issue: Cross-Subscription Access
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Root Cause&lt;/strong&gt;: Key Vault, Managed Identity, and App Service in different subscriptions&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Ensure all resources in same subscription:&lt;/p&gt;

&lt;p&gt;Deploy all resources to identical subscription&lt;br&gt;
Verify Key Vault access policies allow Managed Identity from current subscription&lt;br&gt;
Use cross-tenant access if working across subscriptions&lt;/p&gt;

&lt;h2&gt;
  
  
  Security Considerations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Required RBAC Permissions
&lt;/h3&gt;

&lt;p&gt;The script requires these specific Azure permissions:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Permission&lt;/th&gt;
&lt;th&gt;Required For&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft.Web/sites/read&lt;/td&gt;
&lt;td&gt;Get-AzWebApp&lt;/td&gt;
&lt;td&gt;Read App Service properties&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft.Web/sites/write&lt;/td&gt;
&lt;td&gt;PATCH operation&lt;/td&gt;
&lt;td&gt;Update App Service configuration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft.ManagedIdentity/userAssignedIdentities/read&lt;/td&gt;
&lt;td&gt;Identity reference&lt;/td&gt;
&lt;td&gt;Read Managed Identity details&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Security Best Practices
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Principle of Least Privilege&lt;/strong&gt;: Use Contributor role instead of Owner when possible&lt;br&gt;
&lt;strong&gt;Identity Lifecycle Management&lt;/strong&gt;: Regularly review and rotate Managed Identity access&lt;br&gt;
&lt;strong&gt;Audit Compliance&lt;/strong&gt;: Enable diagnostic settings for tracking configuration changes&lt;br&gt;
&lt;strong&gt;Access Policy Configuration&lt;/strong&gt;: Configure Key Vault access policies with specific permissions&lt;br&gt;
&lt;strong&gt;Secret Rotation&lt;/strong&gt;: Implement automated Key Vault secret rotation policies&lt;/p&gt;

&lt;h2&gt;
  
  
  Alternative Implementation Methods
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Azure CLI Solution
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az webapp update &lt;span class="nt"&gt;--resource-group&lt;/span&gt; your-resource-group &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; your-app-name &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--set&lt;/span&gt; properties.keyVaultReferenceIdentity&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/subscriptions/YOUR-SUBSCRIPTION-ID/resourceGroups/your-resource-group/providers/Microsoft.ManagedIdentity/userAssignedIdentities/your-identity-name"&lt;/span&gt;

&lt;span class="c"&gt;# Verify the update&lt;/span&gt;
az webapp show &lt;span class="nt"&gt;--resource-group&lt;/span&gt; your-resource-group &lt;span class="nt"&gt;--name&lt;/span&gt; your-app-name &lt;span class="nt"&gt;--query&lt;/span&gt; properties.keyVaultReferenceIdentity

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Infrastructure as Code (Bicep)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;@description('App&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Service&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;name')&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;param&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;appServiceName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;string&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;@description('Resource&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;group&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;name')&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;param&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;resourceGroupName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;string&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;@description('Location&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;all&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;resources')&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;param&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;location&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;string&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;@description('User-Assigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Managed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Identity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ID')&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;param&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;keyVaultReferenceIdentityId&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;string&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;resource&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;appService&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'Microsoft.Web/sites@&lt;/span&gt;&lt;span class="mi"&gt;2021-01-01&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;name:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;appServiceName&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;location:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;location&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;resourceGroupName:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;resourceGroupName&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;kind:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'linux'&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;properties:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;serverFarmId:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;appServicePlanId&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;keyVaultReferenceIdentity:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;keyVaultReferenceIdentityId&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Infrastructure as Code (Terraform)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight terraform"&gt;&lt;code&gt;&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"azurerm_app_service"&lt;/span&gt; &lt;span class="s2"&gt;"example"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"your-app-name"&lt;/span&gt;
  &lt;span class="nx"&gt;location&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;
  &lt;span class="nx"&gt;resource_group_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
  &lt;span class="nx"&gt;app_service_plan_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;azurerm_app_service_plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;
  &lt;span class="nx"&gt;kind&lt;/span&gt;                &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"linux"&lt;/span&gt;

  &lt;span class="nx"&gt;site_config&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;min_tls_version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"1.2"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;identity&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;type&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"UserAssigned"&lt;/span&gt;
    &lt;span class="nx"&gt;identity_ids&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;azurerm_user_assigned_identity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;lifecycle&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;ignore_changes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"azurerm_key_vault"&lt;/span&gt; &lt;span class="s2"&gt;"example"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;                     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"your-keyvault-name"&lt;/span&gt;
  &lt;span class="nx"&gt;location&lt;/span&gt;                 &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;
  &lt;span class="nx"&gt;resource_group_name&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;azurerm_resource_group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;
  &lt;span class="nx"&gt;tenant_id&lt;/span&gt;               &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;azurerm_client_config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tenant_id&lt;/span&gt;
  &lt;span class="nx"&gt;sku_name&lt;/span&gt;                 &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"standard"&lt;/span&gt;
  &lt;span class="nx"&gt;enabled_for_template_deployment&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

  &lt;span class="nx"&gt;access_policy&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;tenant_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;azurerm_app_service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tenant_id&lt;/span&gt;
    &lt;span class="nx"&gt;object_id&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;azurerm_app_service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;identity&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;principal_id&lt;/span&gt;
    &lt;span class="nx"&gt;secret_permissions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"get"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"list"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Technical Limitations and Considerations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Current Limitations
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Portal Invisibility&lt;/strong&gt;: The &lt;code&gt;keyVaultReferenceIdentity&lt;/code&gt; property cannot be managed through Azure Portal&lt;br&gt;
&lt;strong&gt;API Version Dependency&lt;/strong&gt;: Uses ARM API version 2021-01-01&lt;br&gt;
&lt;strong&gt;Resource Provider Constraints&lt;/strong&gt;: Requires &lt;code&gt;Microsoft.Web/sites&lt;/code&gt; resource provider availability&lt;br&gt;
&lt;strong&gt;Manual Configuration&lt;/strong&gt;: Requires PowerShell or CLI interaction for setup&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance Impact
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;App Service Restart&lt;/strong&gt;: Required for configuration changes to take effect&lt;br&gt;
&lt;strong&gt;Authentication Overhead&lt;/strong&gt;: Additional identity validation adds minimal latency&lt;br&gt;
&lt;strong&gt;Resource Consumption&lt;/strong&gt;: No significant performance impact on secret retrieval&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Implementation Mistakes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Mistake 1: Premature Script Execution
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Running configuration script before identity assignment&lt;br&gt;
&lt;strong&gt;Solution&lt;/strong&gt;: Always assign Managed Identity first, then execute PowerShell script&lt;/p&gt;

&lt;h3&gt;
  
  
  Mistake 2: Incorrect Subscription Context
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Script running in wrong Azure subscription&lt;br&gt;
&lt;strong&gt;Solution&lt;/strong&gt;: Verify subscription context with &lt;code&gt;Get-AzContext&lt;/code&gt; before running&lt;/p&gt;

&lt;h3&gt;
  
  
  Mistake 3: Incomplete Identity URLs
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Problem&lt;/strong&gt;: Missing subscription ID or resource group in identity URL&lt;br&gt;
&lt;strong&gt;Solution&lt;/strong&gt;: Ensure complete resource URL construction in script&lt;/p&gt;

&lt;h2&gt;
  
  
  SEO Optimization Keywords
&lt;/h2&gt;

&lt;p&gt;Azure App Service KeyVault Reference Identity&lt;br&gt;
Azure Key Vault access with App Service&lt;br&gt;
Azure Managed Identity for App Service&lt;br&gt;
Azure Key Vault references configuration&lt;br&gt;
Azure App Service secret management&lt;br&gt;
Azure KeyVault integration with App Service&lt;br&gt;
Azure Resource Manager ARM configuration&lt;br&gt;
Azure App Service Key Vault fix&lt;br&gt;
Azure Web Apps KeyVault identity&lt;br&gt;
Azure App Service Managed Identity configuration&lt;/p&gt;

&lt;h2&gt;
  
  
  Related Documentation
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/app-service/app-service-key-vault-references?tabs=azure-cli" rel="noopener noreferrer"&gt;Use Key Vault references as app settings in Azure App Service&lt;/a&gt;&lt;br&gt;
&lt;a href="https://learn.microsoft.com/en-us/dotnet/api/microsoft.azure.powershell.cmdlets.functions.models.site.keyvaultreferenceidentity?view=az-ps-latest" rel="noopener noreferrer"&gt;Site.KeyVaultReferenceIdentity Property&lt;/a&gt;&lt;br&gt;
&lt;a href="https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview" rel="noopener noreferrer"&gt;User-Assigned Managed Identity Overview&lt;/a&gt;&lt;br&gt;
&lt;a href="https://stackoverflow.com/questions/77941574/bicep-keyvaultreferenceidentity-in-function-app" rel="noopener noreferrer"&gt;Bicep KeyVaultReferenceIdentity in Function App&lt;/a&gt;&lt;br&gt;
&lt;a href="https://learn.microsoft.com/en-us/answers/questions/2281797/azure-app-service-key-vault-reference-user-assigne" rel="noopener noreferrer"&gt;Azure App Service Key Vault Reference: User Assigned Managed Identity&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Reference Commands
&lt;/h2&gt;

&lt;h3&gt;
  
  
  PowerShell Commands
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check current subscription context&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Get-AzContext&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# List all available subscriptions&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Get-AzSubscription&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;State&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Set subscription context&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Set-AzContext&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-SubscriptionId&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-subscription-id"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Retrieve App Service information&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Get-AzWebApp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ResourceGroupName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-rg"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-app-name"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Restart App Service to apply changes&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Restart-AzWebApp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ResourceGroupName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-rg"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-app-name"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Get diagnostic logs&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Get-AzWebAppLog&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ResourceGroupName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-rg"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-app-name"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Verification Commands
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Verify KeyVaultReferenceIdentity configuration&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Get-AzWebApp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ResourceGroupName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-rg"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-app-name"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ExpandProperty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;KeyVaultReferenceIdentity&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Check App Service identity status&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Get-AzWebApp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ResourceGroupName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-rg"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-app-name"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Select-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ExpandProperty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Identity&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Success Metrics
&lt;/h2&gt;

&lt;p&gt;Track these indicators to confirm successful implementation:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configuration Status&lt;/strong&gt;: Green checkmarks in Application Settings&lt;br&gt;
&lt;strong&gt;Secret Resolution&lt;/strong&gt;: Keys display &lt;code&gt;@Microsoft.KeyVault(...)&lt;/code&gt; format&lt;br&gt;
&lt;strong&gt;Authentication Success&lt;/strong&gt;: Application logs show successful secret retrieval&lt;br&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: No increased latency in secret access operations&lt;br&gt;
&lt;strong&gt;Security&lt;/strong&gt;: Proper RBAC permissions and access policies in place&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This comprehensive guide resolves Azure App Service KeyVault Reference Identity configuration issues by addressing the hidden &lt;code&gt;keyVaultReferenceIdentity&lt;/code&gt; property problem. The solution enables proper authentication between Azure App Service and Azure Key Vault through Managed Identity integration.&lt;/p&gt;

&lt;p&gt;By following this step-by-step approach, developers can successfully:&lt;/p&gt;

&lt;p&gt;Configure KeyVault Reference Identity using PowerShell&lt;br&gt;
Verify secret resolution in application settings&lt;br&gt;
Implement proper security and RBAC permissions&lt;br&gt;
Use alternative methods like Azure CLI or infrastructure as code&lt;/p&gt;

&lt;p&gt;The hidden property may be invisible in the Azure Portal, but with this technical approach, developers can overcome this architectural limitation and maintain secure, compliant secret management for their Azure applications.&lt;/p&gt;

&lt;p&gt;For ongoing maintenance, remember to review identity assignments quarterly, monitor configuration changes, and implement automated secret rotation policies to ensure continued security and compliance.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This article covers advanced Azure administration concepts. Ensure you have proper permissions and understand the implications before making changes to production environments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>dotnet</category>
      <category>productivity</category>
      <category>vineforce</category>
    </item>
    <item>
      <title>Astro + Cloudflare Pages vs WordPress - A Technical Comparison for Modern Static Sites</title>
      <dc:creator>Harsh Gupta</dc:creator>
      <pubDate>Fri, 17 Jul 2026 00:00:55 +0000</pubDate>
      <link>https://dev.to/harshgupta71/astro-cloudflare-pages-vs-wordpress-a-technical-comparison-for-modern-static-sites-2b4d</link>
      <guid>https://dev.to/harshgupta71/astro-cloudflare-pages-vs-wordpress-a-technical-comparison-for-modern-static-sites-2b4d</guid>
      <description>&lt;h2&gt;
  
  
  1. Introduction
&lt;/h2&gt;

&lt;p&gt;In 2026, many teams still default to WordPress when building blogs or marketing sites, often without fully considering the architectural alternatives. The classic WordPress setup PHP on shared hosting or managed WordPress platforms, coupled with a MySQL database and a plugin ecosystem works reliably but comes with inherent performance trade-offs.&lt;/p&gt;

&lt;p&gt;Modern visitors now expect lightning-fast page loads and perfect Core Web Vitals a bar that traditional WordPress setups struggle to meet without extensive optimization and caching strategies.&lt;/p&gt;

&lt;p&gt;This article examines why, for many developer-managed websites, &lt;strong&gt;Astro + Cloudflare Pages delivers superior results&lt;/strong&gt; in performance, SEO, security, and maintainability compared to traditional WordPress deployments. We'll explore the technical trade-offs and help you make an informed decision for your next blog or business website.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. What is Astro + Cloudflare Pages?
&lt;/h2&gt;

&lt;p&gt;Astro is a modern web framework that prioritizes delivering fast, lightweight content by default. Instead of running client-side JavaScript on every page load, Astro generates complete HTML during build time. Only interactive elements—dubbed "islands of interactivity"—run JavaScript, and only when needed.&lt;/p&gt;

&lt;p&gt;Cloudflare Pages is a globally distributed static hosting platform that leverages Cloudflare's edge network for content delivery. Think of it as Git combined with Cloudflare's CDN and security stack with integrated CI/CD, zero-downtime deployments, and automatic edge caching.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How they work together:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You write your content and components&lt;/strong&gt; using Astro's Markdown, MDX, or frameworks&lt;br&gt;
&lt;strong&gt;Astro builds your site&lt;/strong&gt; to static HTML during your CI/CD pipeline&lt;br&gt;
&lt;strong&gt;Cloudflare Pages takes the built static assets&lt;/strong&gt; and deploys them to edge locations worldwide&lt;br&gt;
&lt;strong&gt;Every request hits the nearest edge location&lt;/strong&gt;, serving cache-optimized HTML directly&lt;/p&gt;

&lt;p&gt;This contrasts sharply with WordPress, which typically involves:&lt;/p&gt;

&lt;p&gt;PHP processing on every request&lt;br&gt;
Database queries to fetch content&lt;br&gt;
Server-side template rendering&lt;br&gt;
Dynamic page generation per visitor&lt;/p&gt;

&lt;p&gt;The result: &lt;strong&gt;WordPress delivers pages via server-side rendering, while Astro + Cloudflare Pages delivers pages via edge-based static serving.&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Performance and Core Web Vitals: Astro vs WordPress
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Why Astro Sites Are Typically Faster
&lt;/h3&gt;

&lt;p&gt;Astro sites start with a clean slate: &lt;strong&gt;static HTML by default&lt;/strong&gt;. This means:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Zero JavaScript by default&lt;/strong&gt; – Pages load instantly with just HTML&lt;br&gt;
&lt;strong&gt;Minimal HTTP requests&lt;/strong&gt; – Bundles are eliminated from the initial response&lt;br&gt;
&lt;strong&gt;Small page weight&lt;/strong&gt; – Often under 50KB for content pages&lt;br&gt;
&lt;strong&gt;Instant first paint&lt;/strong&gt; – No rendering blockers&lt;/p&gt;

&lt;p&gt;Real-world tests and case studies consistently show Astro sites achieving near-perfect Lighthouse performance scores. The initial page load times typically range from &lt;strong&gt;0.5s to 1.5s&lt;/strong&gt; for content-heavy sites, compared to &lt;strong&gt;2s to 5s&lt;/strong&gt; for typical WordPress installations.&lt;/p&gt;
&lt;h3&gt;
  
  
  WordPress Performance Challenges
&lt;/h3&gt;

&lt;p&gt;WordPress usually involves several performance bottlenecks:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PHP rendering on every request&lt;/strong&gt; – Server-side template processing delays first byte&lt;br&gt;
&lt;strong&gt;Database queries&lt;/strong&gt; – MySQL lookups add tens to hundreds of milliseconds&lt;br&gt;
&lt;strong&gt;Plugin overhead&lt;/strong&gt; – Even maintenance plugins add significant JavaScript and processing&lt;br&gt;
&lt;strong&gt;Theme scripts&lt;/strong&gt; – Most themes include jQuery and other bloat by default&lt;/p&gt;
&lt;h3&gt;
  
  
  Core Web Vitals Impact
&lt;/h3&gt;

&lt;p&gt;These differences translate directly into Core Web Vitals:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LCP (Largest Contentful Paint)&lt;/strong&gt; – Astro typically achieves &lt;strong&gt;under 1.5s&lt;/strong&gt;, while WordPress often lands between &lt;strong&gt;2-3s&lt;/strong&gt; without extensive caching&lt;br&gt;
&lt;strong&gt;CLS (Cumulative Layout Shift)&lt;/strong&gt; – Astro's static nature means predictable layouts. WordPress experiences frequent layout shifts during dynamic content loading&lt;br&gt;
&lt;strong&gt;FID (First Input Delay)&lt;/strong&gt; – Lower JavaScript payloads in Astro mean better interactivity&lt;br&gt;
&lt;strong&gt;FCP (First Contentful Paint)&lt;/strong&gt; – Static HTML delivers content instantly, while WordPress waits for PHP to parse and render&lt;/p&gt;

&lt;p&gt;The performance gap becomes more pronounced on mobile networks and in regions far from hosting servers. Since Cloudflare Pages serves content from their global edge network, the geographic distance factor disappears entirely.&lt;/p&gt;
&lt;h2&gt;
  
  
  4. SEO Benefits of Astro + Cloudflare Pages
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Static HTML vs Dynamic Rendering
&lt;/h3&gt;

&lt;p&gt;Static HTML serves SEO exceptionally well because:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fast pages are prioritized by Google&lt;/strong&gt; – Poor Core Web Vitals directly impact rankings&lt;br&gt;
&lt;strong&gt;Simple, crawlable markup&lt;/strong&gt; – Search engines can parse clean HTML instantly without JavaScript&lt;br&gt;
&lt;strong&gt;Predictable content delivery&lt;/strong&gt; – Same markup for all visitors regardless of device or traffic source&lt;/p&gt;

&lt;p&gt;WordPress's JavaScript-heavy pages force Googlebot to execute JavaScript a process that's become more sophisticated but still less reliable than serving static HTML.&lt;/p&gt;
&lt;h3&gt;
  
  
  Astro's SEO Capabilities
&lt;/h3&gt;

&lt;p&gt;Astro offers granular control over SEO elements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Your&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Page&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Title"&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Page&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;SEO"&lt;/span&gt;
&lt;span class="na"&gt;keywords&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;keyword1"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;keyword2"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="s"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="s"&gt;&amp;lt;meta property="og:title" content="Social Share Title" /&amp;gt;&lt;/span&gt;
  &lt;span class="s"&gt;&amp;lt;meta property="og:description" content="Social description" /&amp;gt;&lt;/span&gt;
  &lt;span class="s"&gt;&amp;lt;meta property="og:image" content="/social-image.png" /&amp;gt;&lt;/span&gt;
  &lt;span class="s"&gt;&amp;lt;link rel="canonical" href="https://your-site.com/page-url" /&amp;gt;&lt;/span&gt;
&lt;span class="s"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Content collections and frontmatter provide structured data management:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/content/articles/&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ArticleSchema&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;publishDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;excerpt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;
  &lt;span class="nl"&gt;image&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Astro integrates seamlessly with popular SEO tooling:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Robots.txt generation&lt;/strong&gt; via Astro's &lt;code&gt;sitemap&lt;/code&gt; integration&lt;br&gt;
&lt;strong&gt;Structured data&lt;/strong&gt; through &lt;code&gt;@astrojs/sitemap&lt;/code&gt; and JSON-LD&lt;br&gt;
&lt;strong&gt;Meta tags&lt;/strong&gt; automatically generated from frontmatter&lt;br&gt;
&lt;strong&gt;Image optimization&lt;/strong&gt; via &lt;code&gt;@astrojs/image&lt;/code&gt;, supporting WebP, lazy loading, and responsive sizes&lt;/p&gt;
&lt;h3&gt;
  
  
  Cloudflare's SEO Advantages
&lt;/h3&gt;

&lt;p&gt;Cloudflare Pages provides several SEO-specific benefits:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Global CDN distribution&lt;/strong&gt; – Pages serve from 280+ edge locations&lt;br&gt;
&lt;strong&gt;Zero-Time to First Byte (TTFB)&lt;/strong&gt; – Edge caching eliminates server latency&lt;br&gt;
&lt;strong&gt;Built-in SSL/HTTPS&lt;/strong&gt; – No mixed content warnings&lt;br&gt;
&lt;strong&gt;Automatic performance optimization&lt;/strong&gt; – Image compression, HTML minification&lt;/p&gt;

&lt;p&gt;These factors combine to create a superior SEO foundation where pages load in &lt;strong&gt;under 500ms&lt;/strong&gt; with &lt;strong&gt;perfect Core Web Vitals&lt;/strong&gt;, immediately signaling relevance to search engines.&lt;/p&gt;
&lt;h3&gt;
  
  
  Real SEO Impact
&lt;/h3&gt;

&lt;p&gt;The combination of fast performance, clean HTML, and reliable crawling translates to:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Faster indexing&lt;/strong&gt; – Pages crawled and ranked immediately&lt;br&gt;
&lt;strong&gt;Higher visibility&lt;/strong&gt; – Better Core Web Vitals improve rankings&lt;br&gt;
&lt;strong&gt;Better user engagement&lt;/strong&gt; – Faster pages reduce bounce rates and increase dwell time&lt;br&gt;
&lt;strong&gt;Improved Zero-Click Searches&lt;/strong&gt; – Perfect page structure for featured snippets and search features&lt;/p&gt;
&lt;h2&gt;
  
  
  5. Developer Experience and Workflow
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Astro + Cloudflare Pages Developer Experience
&lt;/h3&gt;

&lt;p&gt;Modern developer workflows prioritize speed and reliability:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# .github/workflows/deploy.yml&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy to Cloudflare Pages&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v3&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;20'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm install&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run build&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish to Cloudflare Pages&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cloudflare/pages-action@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;apiToken&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.CF_PAGES_API_TOKEN }}&lt;/span&gt;
          &lt;span class="na"&gt;accountId&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.CF_ACCOUNT_ID }}&lt;/span&gt;
          &lt;span class="na"&gt;project&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-blog&lt;/span&gt;
          &lt;span class="na"&gt;directory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./dist&lt;/span&gt;
          &lt;span class="na"&gt;gitHubToken&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key benefits include:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Commit → Deploy&lt;/strong&gt; – Automatic deployments directly from git branches&lt;br&gt;
&lt;strong&gt;Zero infrastructure management&lt;/strong&gt; – No cPanel, FTP, or server administration&lt;br&gt;
&lt;strong&gt;Consistent environments&lt;/strong&gt; – Same code runs identically across dev, staging, and prod&lt;br&gt;
&lt;strong&gt;Version control for content&lt;/strong&gt; – Content is text files, fully version-controlled&lt;/p&gt;
&lt;h3&gt;
  
  
  WordPress Workflow Comparison
&lt;/h3&gt;

&lt;p&gt;Traditional WordPress workflows involve:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Content management through admin dashboard&lt;/strong&gt; – HTML editors, plugin dependencies&lt;br&gt;
&lt;strong&gt;Theme and plugin management&lt;/strong&gt; – Version control challenges for non-developers&lt;br&gt;
&lt;strong&gt;Performance tuning&lt;/strong&gt; – Caching plugins, database optimization, CDN integration&lt;br&gt;
&lt;strong&gt;Security maintenance&lt;/strong&gt; – Regular updates, vulnerability patches, backup systems&lt;/p&gt;

&lt;p&gt;The WordPress approach demands significant operational overhead to achieve acceptable performance, while Astro + Cloudflare Pages delivers optimal performance by design.&lt;/p&gt;
&lt;h2&gt;
  
  
  6. A Side-by-Side Comparison
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Quick Reference Table
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Astro + Cloudflare Pages&lt;/th&gt;
&lt;th&gt;WordPress&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Performance&lt;/td&gt;
&lt;td&gt;Static HTML by design, edge delivery&lt;/td&gt;
&lt;td&gt;Dynamic PHP rendering, database queries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Core Web Vitals&lt;/td&gt;
&lt;td&gt;Excellent LCP (under 1.5s), CLS, FID by default&lt;/td&gt;
&lt;td&gt;2-3s LCP, frequent CLS without tuning&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Learning Curve&lt;/td&gt;
&lt;td&gt;Moderate (JavaScript/TypeScript)&lt;/td&gt;
&lt;td&gt;Low (PHP/WordPress admin)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Content Management&lt;/td&gt;
&lt;td&gt;File-based (Markdown/MDX) or Git-based&lt;/td&gt;
&lt;td&gt;Visual editor (Gutenberg)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Out-of-the-Box Features&lt;/td&gt;
&lt;td&gt;Limited (static sites)&lt;/td&gt;
&lt;td&gt;Extensive (plugins for everything)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Customization&lt;/td&gt;
&lt;td&gt;Framework-based (Astro, React, Vue)&lt;/td&gt;
&lt;td&gt;Theme/plugin ecosystem&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scalability&lt;/td&gt;
&lt;td&gt;Automatic (CDN, edge caching)&lt;/td&gt;
&lt;td&gt;Manual (server, caching setup)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security&lt;/td&gt;
&lt;td&gt;Strong (no runtime, Cloudflare WAF)&lt;/td&gt;
&lt;td&gt;Moderate (plugins, PHP vulnerabilities)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maintenance&lt;/td&gt;
&lt;td&gt;Low (CI/CD pipelines, static assets)&lt;/td&gt;
&lt;td&gt;High (updates, backups, plugins)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SEO&lt;/td&gt;
&lt;td&gt;Excellent (fast, clean HTML)&lt;/td&gt;
&lt;td&gt;Good (with optimizations)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Price Comparison
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;Astro + Cloudflare Pages&lt;/th&gt;
&lt;th&gt;WordPress&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Hosting&lt;/td&gt;
&lt;td&gt;Free tier available, Pay-as-you-go ($5-20/month)&lt;/td&gt;
&lt;td&gt;Shared hosting ($10-50/month) or Managed ($25-100/month)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Development Tools&lt;/td&gt;
&lt;td&gt;Free (Astro, Node.js, Git)&lt;/td&gt;
&lt;td&gt;Free (WordPress core)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Premium Extensions&lt;/td&gt;
&lt;td&gt;Limited (Astro integrations)&lt;/td&gt;
&lt;td&gt;Many ($30-200+/year for premium plugins)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Design Themes&lt;/td&gt;
&lt;td&gt;Open source, paid ($20-100)&lt;/td&gt;
&lt;td&gt;Thousands free, premium ($50-500+)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Support&lt;/td&gt;
&lt;td&gt;Community, Cloudflare docs&lt;/td&gt;
&lt;td&gt;Extensive docs, commercial support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total Monthly Cost&lt;/td&gt;
&lt;td&gt;$5-30 (estimated)&lt;/td&gt;
&lt;td&gt;$60-180 (estimated)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Cost Breakdown:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Astro + Cloudflare Pages&lt;/strong&gt;: Only pay for Cloudflare usage ($5-20/month for hobby plan, $20-100+ for pro tier)&lt;br&gt;
&lt;strong&gt;WordPress&lt;/strong&gt;: Hosting ($10-50/month) + Premium plugins/themes ($20-100+/year) + Maintenance costs&lt;/p&gt;
&lt;h3&gt;
  
  
  When to Choose Each Platform
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Decision Factor&lt;/th&gt;
&lt;th&gt;Choose Astro + Cloudflare Pages&lt;/th&gt;
&lt;th&gt;Choose WordPress&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Performance Priority&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Developer Team&lt;/td&gt;
&lt;td&gt;✅ Yes (dev-first approach)&lt;/td&gt;
&lt;td&gt;✅ Yes (content-first approach)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Non-Technical Users&lt;/td&gt;
&lt;td&gt;❌ No (requires development)&lt;/td&gt;
&lt;td&gt;✅ Yes (visual editor)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Complex Features&lt;/td&gt;
&lt;td&gt;❌ Limited (static nature)&lt;/td&gt;
&lt;td&gt;✅ Extensive (plugin ecosystem)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Budget Constraints&lt;/td&gt;
&lt;td&gt;✅ Lower monthly costs&lt;/td&gt;
&lt;td&gt;❌ Higher monthly costs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Technical Team&lt;/td&gt;
&lt;td&gt;✅ Developer expertise available&lt;/td&gt;
&lt;td&gt;✅ Available (WordPress skills)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Growth Plans&lt;/td&gt;
&lt;td&gt;✅ Automatic scalability&lt;/td&gt;
&lt;td&gt;❌ Manual scaling required&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Decision Tree Summary
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Performance is critical?&lt;/strong&gt; → &lt;strong&gt;Astro + Cloudflare Pages&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Non-technical content creators needed?&lt;/strong&gt; → &lt;strong&gt;WordPress&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Complex dynamic features required?&lt;/strong&gt; → &lt;strong&gt;WordPress&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Budget is a primary concern?&lt;/strong&gt; → &lt;strong&gt;Astro + Cloudflare Pages&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Developer-first approach preferred?&lt;/strong&gt; → &lt;strong&gt;Astro + Cloudflare Pages&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Existing WordPress investment?&lt;/strong&gt; → &lt;strong&gt;Consider WordPress&lt;/strong&gt; (but evaluate migration ROI)&lt;/p&gt;
&lt;h3&gt;
  
  
  Bottom Line Recommendation
&lt;/h3&gt;

&lt;p&gt;**For most modern developer-managed projects, especially blogs, documentation sites, and marketing pages:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Total Cost&lt;/strong&gt;: ~60-70% less with Astro + Cloudflare Pages&lt;br&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: Significantly better (0.5s vs 2-5s load times)&lt;br&gt;
&lt;strong&gt;Maintainability&lt;/strong&gt;: Much easier (CI/CD vs ongoing administration)&lt;br&gt;
&lt;strong&gt;Security&lt;/strong&gt;: Stronger (no database, fewer attack vectors)&lt;br&gt;
&lt;strong&gt;Developer Experience&lt;/strong&gt;: Superior (modern toolchain vs legacy admin)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose WordPress when you need:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Visual content editing without code&lt;br&gt;
Complex plugin ecosystems (e-commerce, memberships)&lt;br&gt;
Existing WordPress team skills&lt;br&gt;
Rapid feature deployment without developer involvement&lt;/p&gt;

&lt;p&gt;This comparison should make it crystal clear which platform serves your specific needs best, with the financial implications being a major deciding factor in 2026's cost-conscious environment.&lt;/p&gt;
&lt;h2&gt;
  
  
  7. Practical Comparison Scenarios
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Scenario 1: SaaS Marketing Site
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;WordPress approach:&lt;/strong&gt; Typical SaaS marketing site would require multiple plugins for lead generation, analytics, and contact forms. Performance optimization needs caching plugins, CDN integration, and database cleanup. Security requires Wordfence or similar WAF.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Astro + Cloudflare Pages approach:&lt;/strong&gt; Lead form implemented via Astro's forms API or a lightweight service like Netlify Forms. Analytics with Astro integrations. Simple, fast pages that convert better due to performance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Astro wins:&lt;/strong&gt; Marketing sites benefit immediately from faster loads and better SEO. The lightweight approach reduces maintenance overhead and improves conversion rates.&lt;/p&gt;
&lt;h3&gt;
  
  
  Scenario 2: Developer Technical Blog
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;WordPress approach:&lt;/strong&gt; Technical blog with code blocks. Requires syntax highlighting plugins, potentially heavy. Each post loads JavaScript for commenting, related posts, and social sharing. Database queries slow down the blog index page.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Astro + Cloudflare Pages approach:&lt;/strong&gt; Syntax highlighting built into Astro syntax highlighting. Comments via third-party services (Disqus, Utterances). Static generation means instant page loads even with hundreds of posts.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Astro wins:&lt;/strong&gt; Developer audiences expect fast loading, especially for code-heavy content. Static generation eliminates database overhead and delivers instant page loads.&lt;/p&gt;
&lt;h3&gt;
  
  
  WordPress remains viable for:
&lt;/h3&gt;

&lt;p&gt;News sites with tight publishing deadlines&lt;br&gt;
Sites requiring complex dynamic features (membership, e-commerce)&lt;br&gt;
Organizations with non-technical content teams&lt;br&gt;
Existing WordPress investments with extensive custom development&lt;/p&gt;
&lt;h2&gt;
  
  
  8. Migration Considerations
&lt;/h2&gt;

&lt;p&gt;Moving from WordPress to Astro requires careful planning:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;URL Preservation:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use redirects to maintain SEO equity&lt;br&gt;
Implement 301 redirects for changed URLs&lt;br&gt;
Consider using tools like &lt;code&gt;next-redirect&lt;/code&gt; or Cloudflare's redirect rules&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SEO Transition:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;&amp;lt;!--&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Preserve&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;schema.org&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;markup&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;--&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;script&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;type=&lt;/span&gt;&lt;span class="s2"&gt;"application/ld+json"&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://schema.org"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"BlogPosting"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"headline"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Article Title"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"datePublished"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-06-24"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Person"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Author Name"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Content Migration Strategy:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Map old URLs to new structure&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;page &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;mysql &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"SELECT post_name FROM wp_posts WHERE post_type='post'"&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;&lt;span class="nv"&gt;old_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/&lt;/span&gt;&lt;span class="nv"&gt;$page&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nv"&gt;new_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/blog/&lt;/span&gt;&lt;span class="nv"&gt;$page&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$old_url&lt;/span&gt;&lt;span class="s2"&gt; 301  &lt;/span&gt;&lt;span class="nv"&gt;$new_url&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; redirects.txt
 &lt;span class="k"&gt;done&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Search Console Updates:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Submit updated sitemap.xml&lt;br&gt;
Monitor crawl rate changes&lt;br&gt;
Verify canonical tags are set correctly&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Conclusion
&lt;/h2&gt;

&lt;p&gt;The choice between WordPress and Astro + Cloudflare Pages depends heavily on your specific use case, team expertise, and long-term goals. However, for most modern blogs, documentation sites, and business websites, &lt;strong&gt;Astro + Cloudflare Pages provides the superior foundation&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  When to Choose Astro + Cloudflare Pages:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;You need performance first&lt;/strong&gt; – When Core Web Vitals and user experience are priorities&lt;br&gt;
&lt;strong&gt;You have developer expertise&lt;/strong&gt; – When your team can manage content through code and version control&lt;br&gt;
&lt;strong&gt;You want low maintenance&lt;/strong&gt; – When you prefer simplicity over extensive plugin ecosystems&lt;br&gt;
&lt;strong&gt;You need global reach&lt;/strong&gt; – When serving users worldwide with consistent performance&lt;br&gt;
&lt;strong&gt;You prioritize SEO&lt;/strong&gt; – When search rankings and visibility are critical&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Advantages Recap:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Zero-compromise performance&lt;/strong&gt; – Static HTML serves instantly from edge locations&lt;br&gt;
&lt;strong&gt;Developer-friendly workflows&lt;/strong&gt; – Git-based deployment and modern CI/CD&lt;br&gt;
&lt;strong&gt;Strong security posture&lt;/strong&gt; – No database, less attack surface, Cloudflare protection&lt;br&gt;
&lt;strong&gt;SEO-ready by design&lt;/strong&gt; – Fast pages, clean markup, global distribution&lt;br&gt;
&lt;strong&gt;Scalable architecture&lt;/strong&gt; – Handles growth without performance degradation&lt;/p&gt;

&lt;p&gt;WordPress still holds value in specific scenarios, but for performance-critical, developer-managed sites in 2026, &lt;strong&gt;Astro on Cloudflare Pages represents the modern standard for web development&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Ready to prototype your next blog or marketing site using this approach? Start with Astro's starter templates and Cloudflare Pages' Git integration then measure your performance gains and SEO improvements against your current WordPress installation. The difference in user experience and search rankings will speak for itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Official Astro documentation&lt;/strong&gt; – &lt;a href="https://astro.build/" rel="noopener noreferrer"&gt;https://astro.build&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Cloudflare Pages documentation&lt;/strong&gt; – &lt;a href="https://developers.cloudflare.com/pages/" rel="noopener noreferrer"&gt;https://developers.cloudflare.com/pages/&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Astro vs WordPress performance comparison&lt;/strong&gt; – &lt;a href="https://www.netlify.com/blog/2021/01/14/how-astro-is-better-than-wordpress/" rel="noopener noreferrer"&gt;https://www.netlify.com/blog/2021/01/14/how-astro-is-better-than-wordpress/&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Cloudflare + Astro SEO guide&lt;/strong&gt; – &lt;a href="https://developers.cloudflare.com/blogs/2023/08/astro-seo/" rel="noopener noreferrer"&gt;https://developers.cloudflare.com/blogs/2023/08/astro-seo/&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Static vs dynamic: When to choose each&lt;/strong&gt; – &lt;a href="https://web.dev/static-vs-dynamic-rendering/" rel="noopener noreferrer"&gt;https://web.dev/static-vs-dynamic-rendering/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>productivity</category>
      <category>vineforce</category>
    </item>
    <item>
      <title>Why Use Repository Pattern in Angular Applications - Best Practices</title>
      <dc:creator>Harsh Gupta</dc:creator>
      <pubDate>Sun, 14 Jun 2026 07:21:11 +0000</pubDate>
      <link>https://dev.to/harshgupta71/why-use-repository-pattern-in-angular-applications-best-practices-1dji</link>
      <guid>https://dev.to/harshgupta71/why-use-repository-pattern-in-angular-applications-best-practices-1dji</guid>
      <description>&lt;p&gt;In modern Angular applications, managing data efficiently is crucial for performance and maintainability. The Repository Pattern provides a clean abstraction layer between your components and data sources, offering significant benefits for enterprise applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is the Repository Pattern?
&lt;/h2&gt;

&lt;p&gt;The Repository Pattern is an architectural approach that acts as a mediator between the data source (database, API, etc.) and the business logic layers of an application. Rather than making direct API calls from components, you use repository services that:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Centralize data access logic&lt;/strong&gt; in one place&lt;br&gt;
&lt;strong&gt;Provide caching mechanisms&lt;/strong&gt; to reduce redundant network requests&lt;br&gt;
&lt;strong&gt;Offer reactive observables&lt;/strong&gt; for data changes&lt;br&gt;
&lt;strong&gt;Handle data loading and initialization&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Why Vineforce Teams Uses This Pattern
&lt;/h2&gt;

&lt;p&gt;At Vineforce, we've adopted the Repository Pattern for several key reasons:&lt;/p&gt;
&lt;h3&gt;
  
  
  Performance Optimization
&lt;/h3&gt;

&lt;p&gt;Reduces redundant API calls through intelligent caching&lt;br&gt;
Minimizes network overhead by storing frequently accessed data&lt;br&gt;
Enables optimistic UI updates for better user experience&lt;/p&gt;
&lt;h3&gt;
  
  
  Code Maintainability
&lt;/h3&gt;

&lt;p&gt;Centralizes data access logic in one place&lt;br&gt;
Promotes separation of concerns&lt;br&gt;
Makes components cleaner and more testable&lt;br&gt;
Simplifies debugging and troubleshooting&lt;/p&gt;
&lt;h3&gt;
  
  
  Developer Productivity
&lt;/h3&gt;

&lt;p&gt;Provides consistent API across different data types&lt;br&gt;
Enables reactive programming patterns&lt;br&gt;
Reduces boilerplate code in components&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementation in Vineforce Teams
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Base Repository Class
&lt;/h3&gt;

&lt;p&gt;Our implementation starts with an abstract &lt;code&gt;Repository&lt;/code&gt; class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Repository&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="na"&gt;dic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[];&lt;/span&gt;

    &lt;span class="cm"&gt;/** Provides an observable that will emit a new list every time a change occurs */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cm"&gt;/** Returns the item having that ID, only if already loaded in the repository */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cm"&gt;/** Returns the item if present in the repository, otherwise loads it */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;getOrLoad&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cm"&gt;/** Adds a range of items to the repository */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;addRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="cm"&gt;/** Removes a range of items from the repository */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;removeRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;ts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[]):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="nf"&gt;loadAll&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Concrete Implementation Example
&lt;/h3&gt;

&lt;p&gt;Here's how we extend the base class for team member data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;providedIn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TeamMemberNamesRepositoryService&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Repository&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TeamMemberNameDto&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="na"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserServiceProxy&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initialLoad&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Pre-load data when service is instantiated&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nf"&gt;loadAll&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TeamMemberNameDto&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTeamMembersByCurrentUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;members&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;members&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;}))))&lt;/span&gt;
            &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toPromise&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;TeamMemberNameDto&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Benefits for Vineforce Teams Developers
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Reduced API Calls
&lt;/h3&gt;

&lt;p&gt;With caching built into repositories, common data is only fetched once and reused across components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Multiple components can access the same data without additional API calls&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;teamMembers$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;teamMemberRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Consistent Data State
&lt;/h3&gt;

&lt;p&gt;All components using the same repository share the same data state, ensuring consistency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// When data updates in one place, all components automatically reflect changes&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;teamMemberRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entityChanged&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;updateEntity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updatedMember&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Simplified Component Logic
&lt;/h3&gt;

&lt;p&gt;Components focus on presentation logic rather than data management:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app-team-selector&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
    &amp;lt;select [(ngModel)]="selectedTeamMember"&amp;gt;
      &amp;lt;option *ngFor="let member of teamMembers$ | async" [value]="member.id"&amp;gt;
        {{ member.name }}
      &amp;lt;/option&amp;gt;
    &amp;lt;/select&amp;gt;
  `&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TeamSelectorComponent&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;OnInit&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;teamMembers$&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;teamMemberRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;teamMemberRepository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;TeamMemberNamesRepositoryService&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="nf"&gt;ngOnInit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Repository handles loading automatically&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Best Practices for Repository Implementation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Initialize Early
&lt;/h3&gt;

&lt;p&gt;Load frequently used data early in the application lifecycle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;userService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserServiceProxy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initialLoad&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Load data when service is created&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Handle Loading States
&lt;/h3&gt;

&lt;p&gt;Repositories provide built-in mechanisms for handling loading states:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Check if repository is ready&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isReady&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Repository has loaded data&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isReady&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Process loaded items&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Update Repository on Data Changes
&lt;/h3&gt;

&lt;p&gt;Keep repositories synchronized with backend changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// When an item is created/updated/deleted&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entityChanged&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;insertEntity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newItem&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entityChanged&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;updateEntity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;updatedItem&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entityChanged&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;deletedEntity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;removedItem&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  When to Use Repository Pattern
&lt;/h2&gt;

&lt;p&gt;The Repository Pattern is particularly beneficial when:&lt;/p&gt;

&lt;p&gt;You have data that is used across multiple components&lt;br&gt;
You need to minimize network requests&lt;br&gt;
You want to implement caching strategies&lt;br&gt;
You need to maintain consistent data state across your application&lt;br&gt;
You're building enterprise applications with complex data relationships&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The Repository Pattern provides a robust and scalable approach to data management in Angular applications. By centralizing data access and implementing intelligent caching, repositories significantly improve both application performance and developer productivity.&lt;/p&gt;

&lt;p&gt;Key advantages of this pattern include:&lt;/p&gt;

&lt;p&gt;Reduced API calls through caching&lt;br&gt;
Cleaner component code&lt;br&gt;
Consistent data access patterns&lt;br&gt;
Built-in reactive programming support&lt;br&gt;
Easy synchronization with backend changes&lt;/p&gt;

&lt;p&gt;This pattern is especially valuable in enterprise applications like Vineforce Teams where multiple components need access to the same data sets, ensuring optimal performance and maintainability.&lt;/p&gt;

&lt;p&gt;For developers working with Vineforce Teams, understanding and utilizing the Repository Pattern will lead to more efficient, maintainable, and performant applications.&lt;/p&gt;

</description>
      <category>angular</category>
      <category>dotnet</category>
      <category>productivity</category>
      <category>vineforce</category>
    </item>
    <item>
      <title>DefaultAzureCredential vs Client ID &amp; Client Secret for Azure Key Vault Authentication</title>
      <dc:creator>Harsh Gupta</dc:creator>
      <pubDate>Sun, 14 Jun 2026 07:20:28 +0000</pubDate>
      <link>https://dev.to/harshgupta71/defaultazurecredential-vs-client-id-client-secret-for-azure-key-vault-authentication-5ee4</link>
      <guid>https://dev.to/harshgupta71/defaultazurecredential-vs-client-id-client-secret-for-azure-key-vault-authentication-5ee4</guid>
      <description>&lt;p&gt;Securely accessing &lt;strong&gt;Azure Key Vault&lt;/strong&gt; is essential for modern cloud applications. This guide compares the &lt;strong&gt;&lt;code&gt;DefaultAzureCredential&lt;/code&gt;&lt;/strong&gt; (recommended) and the classic &lt;strong&gt;Client ID &amp;amp; Client Secret&lt;/strong&gt; authentication methods for Azure Key Vault, providing best‑practice recommendations, security considerations, and ready‑to‑use C# code samples.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Two Approaches
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. DefaultAzureCredential
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;DefaultAzureCredential&lt;/code&gt; is a &lt;strong&gt;composite credential&lt;/strong&gt; that sequentially attempts a set of credential sources (environment variables, managed identity, Visual Studio, Azure CLI, etc.) until one succeeds. It is designed to work &lt;strong&gt;out‑of‑the‑box&lt;/strong&gt; in local development, CI pipelines, and production environments. &lt;em&gt;&lt;a href="https://learn.microsoft.com/azure/developer/dotnet/azure-sdk-authentication" rel="noopener noreferrer"&gt;Azure SDK authentication overview (Azure Identity)&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Client ID &amp;amp; Client Secret
&lt;/h3&gt;

&lt;p&gt;The &lt;strong&gt;Client ID &amp;amp; Client Secret&lt;/strong&gt; method uses an Azure AD &lt;strong&gt;App Registration&lt;/strong&gt;. You explicitly provide the &lt;code&gt;tenantId&lt;/code&gt;, &lt;code&gt;clientId&lt;/code&gt;, and &lt;code&gt;clientSecret&lt;/code&gt; to the &lt;code&gt;ClientSecretCredential&lt;/code&gt;. This is a static credential that does not change based on the runtime environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison Table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;DefaultAzureCredential&lt;/th&gt;
&lt;th&gt;Client ID &amp;amp; Client Secret&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Security&lt;/td&gt;
&lt;td&gt;Leverages managed identities in Azure, never stores secrets in code or config. Secrets only exist in dev environment as env vars.&lt;/td&gt;
&lt;td&gt;Secret stored in configuration (env var, file, or secret store). Higher risk of leakage.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Local Development&lt;/td&gt;
&lt;td&gt;Works with Azure CLI, VS Code, or environment variables automatically. No extra code changes when moving between dev and prod.&lt;/td&gt;
&lt;td&gt;Requires developers to provision and manage a secret locally, often duplicated across machines.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Production Overhead&lt;/td&gt;
&lt;td&gt;Zero‑code changes when deploying to Azure services (App Service, AKS, Functions) that support Managed Identity.&lt;/td&gt;
&lt;td&gt;Must provision secret in each target environment (e.g., Azure Key Vault, App Settings).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Credential Rotation&lt;/td&gt;
&lt;td&gt;Managed identity tokens rotate automatically; no manual secret rotation needed.&lt;/td&gt;
&lt;td&gt;Secret rotation is manual – you must update the secret in every deployment artifact.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compliance&lt;/td&gt;
&lt;td&gt;Aligns with Azure recommended best practices (least‑privilege, short‑lived tokens).&lt;/td&gt;
&lt;td&gt;May conflict with policies that forbid storing secrets in configuration files.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Complexity&lt;/td&gt;
&lt;td&gt;Slightly larger package size but simplifies code paths.&lt;/td&gt;
&lt;td&gt;Simpler code but adds operational complexity around secret handling.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Supported Languages&lt;/td&gt;
&lt;td&gt;All Azure SDKs that use Azure.Identity.&lt;/td&gt;
&lt;td&gt;All Azure SDKs that accept a TokenCredential.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Pros &amp;amp; Cons
&lt;/h2&gt;

&lt;h3&gt;
  
  
  DefaultAzureCredential
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Automatic credential selection across environments.&lt;br&gt;
Seamless integration with Managed Identity – no secrets in production.&lt;br&gt;
Simplifies CI/CD pipelines.&lt;br&gt;
Recommended by Microsoft for new projects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Slightly larger dependency footprint.&lt;br&gt;
Requires understanding of the credential chain for debugging.&lt;/p&gt;

&lt;h3&gt;
  
  
  Client ID &amp;amp; Client Secret
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Explicit and deterministic – you know exactly which credential is used.&lt;br&gt;
Works in environments that lack Azure SDK support for managed identity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Secrets must be stored and rotated manually.&lt;br&gt;
Higher risk of accidental exposure (e.g., committing to repo).&lt;br&gt;
Additional operational overhead for each deployment target.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Use Which
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;th&gt;Recommended Approach&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;New cloud‑native application running in Azure (App Service, AKS, Functions, etc.)&lt;/td&gt;
&lt;td&gt;DefaultAzureCredential – take advantage of managed identity.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Legacy on‑prem or non‑Azure environment where managed identity isn’t available&lt;/td&gt;
&lt;td&gt;Client ID &amp;amp; Client Secret – you must supply a static credential.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Quick prototype on a developer machine without Azure CLI installed&lt;/td&gt;
&lt;td&gt;Either works, but DefaultAzureCredential still recommended for consistency.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Strict compliance requiring no secrets in configuration files&lt;/td&gt;
&lt;td&gt;DefaultAzureCredential (managed identity) is the only compliant choice.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Code Samples (C# using Azure.Identity)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Using &lt;em&gt;DefaultAzureCredential&lt;/em&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Azure.Identity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Azure.Security.KeyVault.Secrets&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// The credential automatically picks the best source:&lt;/span&gt;
&lt;span class="c1"&gt;// - Azure Managed Identity (production)&lt;/span&gt;
&lt;span class="c1"&gt;// - Azure CLI / Visual Studio credentials (local dev)&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;credential&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;DefaultAzureCredential&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;vaultUrl&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://my-keyvault.vault.azure.net/"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SecretClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vaultUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;credential&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Retrieve a secret&lt;/span&gt;
&lt;span class="n"&gt;KeyVaultSecret&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetSecretAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MySecret"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Secret value: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Using Client ID &amp;amp; Client Secret
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Azure.Identity&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Azure.Security.KeyVault.Secrets&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;tenantId&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetEnvironmentVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"AZURE_TENANT_ID"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;clientId&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetEnvironmentVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"AZURE_CLIENT_ID"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;clientSecret&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetEnvironmentVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"AZURE_CLIENT_SECRET"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;credential&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ClientSecretCredential&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tenantId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clientId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clientSecret&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;vaultUrl&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Uri&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"https://my-keyvault.vault.azure.net/"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SecretClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;vaultUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;credential&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;KeyVaultSecret&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetSecretAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MySecret"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Secret value: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; In production, store the environment variables securely (e.g., Azure App Service Application Settings or Azure Key Vault references). Never hard‑code secrets.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://learn.microsoft.com/azure/developer/dotnet/azure-sdk-authentication" rel="noopener noreferrer"&gt;Azure SDK authentication overview (Azure Identity)&lt;/a&gt;&lt;br&gt;
&lt;a href="https://learn.microsoft.com/dotnet/api/azure.identity.defaultazurecredential?view=azure-dotnet" rel="noopener noreferrer"&gt;DefaultAzureCredential class documentation&lt;/a&gt;&lt;br&gt;
&lt;a href="https://learn.microsoft.com/dotnet/api/azure.identity.clientsecretcredential?view=azure-dotnet" rel="noopener noreferrer"&gt;ClientSecretCredential class documentation&lt;/a&gt;&lt;br&gt;
&lt;a href="https://learn.microsoft.com/azure/key-vault/general/authentication" rel="noopener noreferrer"&gt;Azure Key Vault authentication guide&lt;/a&gt;&lt;br&gt;
&lt;a href="https://learn.microsoft.com/azure/active-directory/managed-identities-azure-resources/overview" rel="noopener noreferrer"&gt;Managed identities for Azure resources&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DefaultAzureCredential&lt;/code&gt; is the &lt;strong&gt;recommended standard&lt;/strong&gt; for modern Azure applications. It provides a unified, secure, and low‑maintenance authentication experience that works consistently from local development to production with managed identities. The explicit Client ID &amp;amp; Client Secret approach still has a place for legacy or non‑Azure scenarios, but it introduces secret management overhead and security risk. Adopt &lt;code&gt;DefaultAzureCredential&lt;/code&gt; wherever possible to align with Azure’s best‑practice security model.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>productivity</category>
      <category>vineforce</category>
    </item>
    <item>
      <title>Docusaurus – The Modern Docs Framework</title>
      <dc:creator>Harsh Gupta</dc:creator>
      <pubDate>Sun, 14 Jun 2026 07:20:26 +0000</pubDate>
      <link>https://dev.to/harshgupta71/docusaurus-the-modern-docs-framework-22f4</link>
      <guid>https://dev.to/harshgupta71/docusaurus-the-modern-docs-framework-22f4</guid>
      <description>&lt;h2&gt;
  
  
  1. What is Docusaurus?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docusaurus.io/" rel="noopener noreferrer"&gt;Docusaurus&lt;/a&gt; is an open‑source static‑site generator focused on documentation. Built and maintained by Meta (formerly Facebook), it lets you create, version, and deploy documentation sites with &lt;strong&gt;zero configuration&lt;/strong&gt; or &lt;strong&gt;full customisation&lt;/strong&gt; using React, Markdown, and MDX.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;What it means&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Static‑site generation&lt;/td&gt;
&lt;td&gt;Pre‑renders pages to plain HTML → fast loads, cheap hosting.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;React‑powered&lt;/td&gt;
&lt;td&gt;Use React components inside your docs (MDX).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Zero‑config defaults&lt;/td&gt;
&lt;td&gt;npm init docusaurus gives you a working site in seconds.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Extensible plugin ecosystem&lt;/td&gt;
&lt;td&gt;Add search, analytics, theme tweaks, etc., without touching core code.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  2. Why Developers &amp;amp; Organizations Should Use It
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Speed to ship&lt;/strong&gt; – A working docs site is ready after &lt;code&gt;npm start&lt;/code&gt;.&lt;br&gt;
&lt;strong&gt;Maintainable codebase&lt;/strong&gt; – Docs live alongside source code, enabling PR‑driven updates.&lt;br&gt;
&lt;strong&gt;Scalable&lt;/strong&gt; – Handles single‑page docs to multi‑version portals with the same build pipeline.&lt;br&gt;
&lt;strong&gt;Community &amp;amp; Vendor backing&lt;/strong&gt; – Backed by Meta, with an active ecosystem of plugins and themes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: If you already use React or a Node‑based build system, Docusaurus fits naturally and reduces the overhead of maintaining separate documentation tooling.&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Key Features &amp;amp; Benefits
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Benefit&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Built‑in versioning&lt;/td&gt;
&lt;td&gt;Publish docs for each app release; users can switch versions.&lt;/td&gt;
&lt;td&gt;npx docusaurus docs:version 2.3.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Markdown + MDX&lt;/td&gt;
&lt;td&gt;Write prose in Markdown, embed React components when needed.&lt;/td&gt;
&lt;td&gt;See MDX example below.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Search (Algolia, Lunr, etc.)&lt;/td&gt;
&lt;td&gt;Instant full‑text search without external services (optional).&lt;/td&gt;
&lt;td&gt;npm install @docusaurus/theme-search-algolia&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Blog support&lt;/td&gt;
&lt;td&gt;Publish release notes, tutorials, or team updates side‑by‑side with docs.&lt;/td&gt;
&lt;td&gt;npx docusaurus blog:write&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Theming &amp;amp; Customisation&lt;/td&gt;
&lt;td&gt;Override theme files or create a custom React theme.&lt;/td&gt;
&lt;td&gt;npm run swizzle @docusaurus/theme-classic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Plugin ecosystem&lt;/td&gt;
&lt;td&gt;Add sitemap, RSS, Google Analytics, PWA, and more with a single line in docusaurus.config.js.&lt;/td&gt;
&lt;td&gt;plugins: ['@docusaurus/plugin-sitemap']&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CI/CD‑ready&lt;/td&gt;
&lt;td&gt;Generates static assets (/build) – easy to cache on CDNs.&lt;/td&gt;
&lt;td&gt;npm run build &amp;amp;&amp;amp; npx serve ./build&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi‑platform deployment&lt;/td&gt;
&lt;td&gt;Works on GitHub Pages, Azure Static Web Apps, Cloudflare Pages, Netlify, Vercel, etc.&lt;/td&gt;
&lt;td&gt;gh-pages -d build&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Internationalisation (i18n)&lt;/td&gt;
&lt;td&gt;Create docs in multiple languages with locale‑aware routing.&lt;/td&gt;
&lt;td&gt;i18n: { defaultLocale: 'en', locales: ['en','fr','zh'] }&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  4. Simplifying Documentation Management
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Docs live in the repo&lt;/strong&gt; – No separate repository or wiki.&lt;br&gt;
&lt;strong&gt;PR‑driven updates&lt;/strong&gt; – Docs are changed through normal code review flow.&lt;br&gt;
&lt;strong&gt;Automatic linking&lt;/strong&gt; – &lt;code&gt;[@site]&lt;/code&gt; URLs resolve to the site’s base URL, avoiding hard‑coded links.&lt;br&gt;
&lt;strong&gt;Consistent styling&lt;/strong&gt; – A single theme ensures all pages look identical, reducing UI drift.&lt;/p&gt;
&lt;h3&gt;
  
  
  Typical Workflow
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1️⃣ Create a new page&lt;/span&gt;
npx docusaurus docs:create my-new-feature

&lt;span class="c"&gt;# 2️⃣ Write Markdown/MDX (edit docs/my-new-feature.md)&lt;/span&gt;

&lt;span class="c"&gt;# 3️⃣ Run locally&lt;/span&gt;
npm start

&lt;span class="c"&gt;# 4️⃣ Open PR → review → merge&lt;/span&gt;

&lt;span class="c"&gt;# 5️⃣ CI builds &amp;amp; deploys automatically&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  5. CI/CD &amp;amp; Deployment
&lt;/h2&gt;

&lt;p&gt;Because Docusaurus outputs &lt;strong&gt;static HTML&lt;/strong&gt;, any CI system can treat it like a normal build artifact.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Example GitHub Actions workflow (docusaurus.yml)&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy Docusaurus site&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Node&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v3&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;20'&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm ci&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run build&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deploy to Cloudflare Pages&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cloudflare/pages-action@v1&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;apiToken&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.CF_PAGES_TOKEN }}&lt;/span&gt;
          &lt;span class="na"&gt;projectName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docusaurus-docs&lt;/span&gt;
          &lt;span class="na"&gt;directory&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;./build&lt;/span&gt;

      &lt;span class="c1"&gt;# Cloudflare Pages offers a generous free tier (up to 500 build minutes per month and unlimited bandwidth), perfect for open‑source docs. No credit‑card is required, and you can preview changes on PRs automatically.&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the &lt;code&gt;cloudflare/pages-action&lt;/code&gt; step with &lt;code&gt;gh-pages&lt;/code&gt;, &lt;code&gt;Azure/static-web-apps-deploy&lt;/code&gt;, or &lt;code&gt;Netlify&lt;/code&gt; steps as needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Versioning Support
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create a new version folder (e.g., v2.0)&lt;/span&gt;
npx docusaurus docs:version 2.0

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Docusaurus copies the current &lt;code&gt;docs/&lt;/code&gt; folder into &lt;code&gt;versioned_docs/version‑2.0/&lt;/code&gt;.&lt;br&gt;
A selector component appears automatically, letting visitors pick the version they need.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best‑Practice Tips&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Version only on major releases&lt;/strong&gt; – Keeps the version list short.&lt;br&gt;
&lt;strong&gt;Maintain a changelog&lt;/strong&gt; – Use the built‑in blog or a dedicated &lt;code&gt;CHANGELOG.md&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  7. Markdown &amp;amp; MDX
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Markdown&lt;/strong&gt; – Perfect for plain text, tables, code fences.&lt;br&gt;
&lt;strong&gt;MDX&lt;/strong&gt; – Allows JSX inside docs, letting you embed live components, charts, or interactive demos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;My&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="nx"&gt;Demo&lt;/span&gt;

&lt;span class="nx"&gt;Here&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;live&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="nx"&gt;chart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BarChart&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@site/src/components/BarChart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;BarChart&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;chartData&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When to use MDX?&lt;/strong&gt; When you need dynamic UI (e.g., visualising API responses) or want to reuse existing React components.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Search Functionality
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Algolia DocSearch&lt;/strong&gt; (recommended for large sites) – Free tier for open‑source projects.&lt;br&gt;
&lt;strong&gt;Lunr.js&lt;/strong&gt; – Zero‑config, client‑side index for smaller docs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// docusaurus.config.js – Algolia example&lt;/span&gt;
&lt;span class="nx"&gt;themeConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;algolia&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;appId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_APP_ID&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_SEARCH_ONLY_API_KEY&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;indexName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your-site&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;contextualSearch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  9. Blog &amp;amp; Documentation Features
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Area&lt;/th&gt;
&lt;th&gt;What Docusaurus Provides&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Blog&lt;/td&gt;
&lt;td&gt;Markdown‑based posts, RSS feed, pagination.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Docs&lt;/td&gt;
&lt;td&gt;Sidebar auto‑generation, version dropdown, edit‑URL links back to source.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Pages&lt;/td&gt;
&lt;td&gt;Free‑form React pages (src/pages).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Internationalisation&lt;/td&gt;
&lt;td&gt;Language switcher + per‑locale routes.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  10. Customisation &amp;amp; Plugin Ecosystem
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Theme Swizzling&lt;/strong&gt; – Override any component by copying it into &lt;code&gt;src/theme&lt;/code&gt;.&lt;br&gt;
&lt;strong&gt;Official Plugins&lt;/strong&gt; – &lt;code&gt;@docusaurus/plugin-content-docs&lt;/code&gt;, &lt;code&gt;@docusaurus/plugin-content-blog&lt;/code&gt;, &lt;code&gt;@docusaurus/plugin-google-analytics&lt;/code&gt;, etc.&lt;br&gt;
&lt;strong&gt;Community Plugins&lt;/strong&gt; – &lt;code&gt;docusaurus-plugin-sitemap&lt;/code&gt;, &lt;code&gt;docusaurus-plugin-pwa&lt;/code&gt;, &lt;code&gt;docusaurus-plugin-openapi&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick Custom Theme Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx docusaurus swizzle @docusaurus/theme-classic Navbar

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit &lt;code&gt;src/theme/Navbar/index.js&lt;/code&gt; to add a custom logo or extra navigation items.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Integration with CI Platforms
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Typical Integration&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GitHub&lt;/td&gt;
&lt;td&gt;Use GitHub Actions to run npm run build → gh-pages deploy.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Azure DevOps&lt;/td&gt;
&lt;td&gt;Add a pipeline step calling npm run build and publish the build/ folder to an Azure Static Web App.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloudflare Pages&lt;/td&gt;
&lt;td&gt;Push the build/ directory to a Cloudflare Pages project; automatic preview URLs on PRs.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;All integrations rely on the same static artifact (&lt;code&gt;/build&lt;/code&gt;).&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  12. Real‑World Use Cases
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Company&lt;/th&gt;
&lt;th&gt;Use‑case&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Meta&lt;/td&gt;
&lt;td&gt;Internal product documentation for React Native and Jest.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microsoft&lt;/td&gt;
&lt;td&gt;Docs for VS Code extensions, hosted on GitHub Pages.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Airbnb&lt;/td&gt;
&lt;td&gt;Public API reference &amp;amp; design system docs with versioning.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Open‑Source Projects (e.g., TensorFlow.js, Storybook)&lt;/td&gt;
&lt;td&gt;Community‑maintained docs, searchable, with a blog for release notes.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  13. Comparisons with Traditional Approaches
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Traditional Docs (e.g., MkDocs, Jekyll)&lt;/th&gt;
&lt;th&gt;Docusaurus&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Static‑only (no React)&lt;/td&gt;
&lt;td&gt;React + MDX – interactive demos possible&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Limited versioning&lt;/td&gt;
&lt;td&gt;Built‑in versioning via CLI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Plugin ecosystem&lt;/td&gt;
&lt;td&gt;Rich, officially supported plugins + community&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Zero‑config start&lt;/td&gt;
&lt;td&gt;npm init docusaurus gives a complete site instantly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TypeScript support&lt;/td&gt;
&lt;td&gt;Full TS in custom components and config&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  14. Best Practices &amp;amp; Recommendations
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Keep docs in the same repo&lt;/strong&gt; as the code they describe.&lt;br&gt;
&lt;strong&gt;Use versioning&lt;/strong&gt; for every public release.&lt;br&gt;
&lt;strong&gt;Leverage MDX&lt;/strong&gt; for component demos; avoid over‑using React in simple prose.&lt;br&gt;
&lt;strong&gt;Enable Algolia DocSearch&lt;/strong&gt; for larger sites (free for OSS).&lt;br&gt;
&lt;strong&gt;Add a “Edit this page” link&lt;/strong&gt; – &lt;code&gt;editUrl&lt;/code&gt; in &lt;code&gt;docusaurus.config.js&lt;/code&gt; encourages community contributions.&lt;br&gt;
&lt;strong&gt;Automate deployment&lt;/strong&gt; in your CI pipeline – a single &lt;code&gt;npm run build &amp;amp;&amp;amp; deploy-step&lt;/code&gt; is enough.&lt;br&gt;
&lt;strong&gt;Monitor bundle size&lt;/strong&gt; – Docusaurus ships a default theme (~200 KB gzipped); prune unused plugins for faster builds.&lt;/p&gt;

&lt;h2&gt;
  
  
  15. References
&lt;/h2&gt;

&lt;p&gt;Official site &amp;amp; docs – &lt;a href="https://docusaurus.io/" rel="noopener noreferrer"&gt;https://docusaurus.io&lt;/a&gt;&lt;br&gt;
GitHub repo – &lt;a href="https://github.com/facebook/docusaurus" rel="noopener noreferrer"&gt;https://github.com/facebook/docusaurus&lt;/a&gt;&lt;br&gt;
Algolia DocSearch – &lt;a href="https://docsearch.algolia.com/" rel="noopener noreferrer"&gt;https://docsearch.algolia.com/&lt;/a&gt;&lt;br&gt;
“Getting Started” tutorial – &lt;a href="https://docusaurus.io/docs/next/installation" rel="noopener noreferrer"&gt;https://docusaurus.io/docs/next/installation&lt;/a&gt;&lt;br&gt;
Blog post on versioning – &lt;a href="https://docusaurus.io/docs/next/versioning" rel="noopener noreferrer"&gt;https://docusaurus.io/docs/next/versioning&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Ready to publish?&lt;/em&gt; Save this file as &lt;code&gt;docusaurus-overview.md&lt;/code&gt; (or any slug you prefer) and run the CLI if you want to regenerate, or edit directly. Let me know if you need any further tweaks.&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>productivity</category>
      <category>vineforce</category>
    </item>
    <item>
      <title>How to Add a Module in the ABP.io Application?</title>
      <dc:creator>Harsh Gupta</dc:creator>
      <pubDate>Wed, 23 Jul 2025 09:45:19 +0000</pubDate>
      <link>https://dev.to/harshgupta71/how-to-add-a-module-in-the-abpio-application-1ccf</link>
      <guid>https://dev.to/harshgupta71/how-to-add-a-module-in-the-abpio-application-1ccf</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5qcu3qssxdoa82lznvgj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5qcu3qssxdoa82lznvgj.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’re building your application with ABP.io, you’re already on the right path to creating scalable and professional software. One of the best things about ABP.io is how it supports modular architecture. But what does that really mean?&lt;/p&gt;

&lt;p&gt;In simple words, a module in ABP.io is like a complete feature package. It comes with its own logic, database setup, APIs, and even user interface parts. Think of it as a plug-and-play part of your application that keeps your code clean, reusable, and easy to manage.&lt;/p&gt;

&lt;p&gt;ABP.io provides many useful built-in modules like Identity, Tenant Management, and Audit Logging. These help you quickly add common features without writing everything from scratch.&lt;/p&gt;

&lt;p&gt;But sometimes, you need to go beyond the default options. Maybe your project has unique requirements. That’s when creating a custom module becomes important.&lt;/p&gt;

&lt;p&gt;In this guide, I’ll show you how to add a custom module, like Vineforce.ProjectManagement, into your existing ABP.io application. You’ll learn how to do it step by step on both the backend using .NET and the frontend using Angular.&lt;/p&gt;

&lt;p&gt;Whether you’re just starting with ABP.io or already have experience, this blog is made to help you integrate modules smoothly and with confidence.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What You’ll Learn in This Guide&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to prepare your system for module integration&lt;/li&gt;
&lt;li&gt;How to add the module to your ABP.io backend using NuGet&lt;/li&gt;
&lt;li&gt;How to configure the database context and migrations&lt;/li&gt;
&lt;li&gt;How to link the Angular frontend with the module using npm&lt;/li&gt;
&lt;li&gt;Common pitfalls to avoid during integration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Prerequisites &amp;amp; Setup&lt;/strong&gt;&lt;br&gt;
Before you begin, make sure the following tools and environments are set up properly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.1 Required Software&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;.NET SDK (compatible with your ABP.io version)&lt;/li&gt;
&lt;li&gt;Node.js and npm&lt;/li&gt;
&lt;li&gt;Angular CLI (installed globally)&lt;/li&gt;
&lt;li&gt;ABP CLI (installed via dotnet tool)&lt;/li&gt;
&lt;li&gt;Visual Studio or Rider for .NET&lt;/li&gt;
&lt;li&gt;Git for version control&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;1.2 ABP.io Application Ready&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ensure you have an existing ABP.io application up and running. The application should be in either &lt;a href="https://www.vineforce.net/project-management-module/" rel="noopener noreferrer"&gt;Modular Monolith&lt;/a&gt; or Microservice architecture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Backend Integration Using NuGet (C# / .NET)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We’ll start by connecting your backend application to the custom module using NuGet packages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.1 Add Required Packages "Vineforce.Admin.HttpApi.Host"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F26wu04edqzzq9qwnq3lm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F26wu04edqzzq9qwnq3lm.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fym16c6awxtlx0j3h9sg3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fym16c6awxtlx0j3h9sg3.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.nuget.org/packages/Vineforce.ProjectManagement.Application" rel="noopener noreferrer"&gt;Vineforce.ProjectManagement.Application&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.nuget.org/packages/Vineforce.ProjectManagement.HttpApi" rel="noopener noreferrer"&gt;Vineforce.ProjectManagement.HttpApi&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft7yo3b1zo803rdieijax.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft7yo3b1zo803rdieijax.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.2 Register Module Dependencies&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the file AdminHttpApiHostModule.cs&lt;/li&gt;
&lt;li&gt;Add the module dependencies inside the [DependsOn] attribute:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[DependsOn(
    typeof(ProjectManagementHttpApiModule),
    typeof(ProjectManagementApplicationModule),
    typeof(ProjectManagementEntityFrameworkCoreModule),
    typeof(ProjectManagementDomainSharedModule)
)]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnlj7u6ihqk0g9ifr8ohg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnlj7u6ihqk0g9ifr8ohg.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Also, add the using statements at the top:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Vineforce.ProjectManagement;
using Vineforce.ProjectManagement.EntityFrameworkCore;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;2.3 Add Required Packages "Vineforce.Admin.EntityFrameworkCore"&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmhc5lpbb1umn3bar0rcg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmhc5lpbb1umn3bar0rcg.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqg6kxttaqccqqg65v3tb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqg6kxttaqccqqg65v3tb.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Also, add the using statements at the top:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Vineforce.ProjectManagement.EntityFrameworkCore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2.4 Update Your DbContext&lt;/strong&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   1. Open AdminDbContext.cs
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjr0hwwoyvdasz7bu4lqk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjr0hwwoyvdasz7bu4lqk.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Inside the OnModelCreating method, add the following:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv5b0lbavdpspuj7s19b5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv5b0lbavdpspuj7s19b5.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;builder.ConfigureProjectManagement();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This step tells your database context to load and apply table configurations from the ProjectManagement module.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.5 Apply Migrations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once you update the DbContext, run EF Core migrations to apply the updated schema to your database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option A: Using Terminal / PowerShell&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd src/Vineforce.Admin.EntityFrameworkCore
dotnet ef migrations add Add_ProjectManagement_Module
dotnet ef database update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, the new tables from the module will be added to your main database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fju3rynolrwl9m8kt5lf4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fju3rynolrwl9m8kt5lf4.png" alt=" " width="787" height="717"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Frontend Integration Using npm (Angular)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once the backend is configured, let’s integrate the Angular frontend with the module.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.1 Install the Angular Module&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open your Angular project root (usually /angular)&lt;/li&gt;
&lt;li&gt;Run this command in the terminal:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i @vineforce-modules/project-management
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;You can view this link to copy the command: &lt;a href="https://www.npmjs.com/package/@vineforce-modules/project-management" rel="noopener noreferrer"&gt;@vineforce-modules/project-management&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;This will also add the following entry in package.json:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"@vineforce-modules/project-management": "^9.0.0"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe7ho0pxj1i2ym73ni2zv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe7ho0pxj1i2ym73ni2zv.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.2 Update the app-routing.module.ts file&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftuk8d2u9kxqhzoxjye18.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftuk8d2u9kxqhzoxjye18.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  path: 'project-management',
  loadChildren: () =&amp;gt;
    import('@vineforce-modules/project-management').then(m =&amp;gt; m.ProjectManagementModule.forLazy()),
},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This step makes the ProjectManagement module visible in the frontend UI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Test the Integration&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now that everything is configured, it’s time to test.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4.1 Backend Checklist&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run the application using Visual Studio or dotnet run&lt;/li&gt;
&lt;li&gt;Check if there are any build errors&lt;/li&gt;
&lt;li&gt;Confirm that new database tables were created&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4.2 Frontend Checklist&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run npm start or ng serve for Angular&lt;/li&gt;
&lt;li&gt;Log in to the app&lt;/li&gt;
&lt;li&gt;Navigate through the new module in the side menu&lt;/li&gt;
&lt;li&gt;Test create/edit/delete operations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Common Issues &amp;amp; Troubleshooting&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuvtsr2958972sb7jbggr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuvtsr2958972sb7jbggr.png" alt=" " width="800" height="195"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final Summary&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You have now successfully done it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Added a module to your ABP.io backend&lt;/li&gt;
&lt;li&gt;Linked it with your database and ran migrations&lt;/li&gt;
&lt;li&gt;Integrated the Angular module using npm&lt;/li&gt;
&lt;li&gt;Updated routing and tested the entire module&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This setup allows you to build and scale your application using modular principles without repeating core logic again and again.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv5edxx609t9dubpr005q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv5edxx609t9dubpr005q.png" alt=" " width="800" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb2u2xko33r92ompj5yny.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb2u2xko33r92ompj5yny.png" alt=" " width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
Adding a custom module to your ABP.io application is not just a technical task, it is a smart way to keep your project scalable and organized. By following this step-by-step guide, you have successfully connected your backend using NuGet, updated your database context, applied migrations, and linked the frontend through npm and Angular routing.&lt;/p&gt;

&lt;p&gt;This process helps you avoid repeating code, improves maintainability, and prepares your application for future growth. Whether you are adding one module or planning to build a fully modular system, this method will save time and reduce errors.&lt;/p&gt;

&lt;p&gt;If you face any issues or want expert assistance, the Vineforce team is always ready to help with ABP.io development, custom modules, and performance optimization. You can reach us at &lt;a href="mailto:info@vineforce.net"&gt;info@vineforce.net&lt;/a&gt; for support or consultation.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Guide to Add Custom Modules in ABP.IO App</title>
      <dc:creator>Harsh Gupta</dc:creator>
      <pubDate>Thu, 29 May 2025 06:26:05 +0000</pubDate>
      <link>https://dev.to/vineforce/guide-to-add-custom-modules-in-abpio-app-45m</link>
      <guid>https://dev.to/vineforce/guide-to-add-custom-modules-in-abpio-app-45m</guid>
      <description>&lt;p&gt;If you want to extend your ABP.IO application with a custom module, like Vineforce.Test—this guide is for you. Whether you’re building a new feature or organizing your code into reusable parts, creating a custom module helps keep your application clean, scalable, and maintainable.&lt;/p&gt;

&lt;p&gt;In this guide, we’ll walk through the full integration process step by step, covering both the backend and the Angular frontend. You’ll learn how to properly register the module, configure dependencies, and connect the UI layer to your logic. By the end, you’ll have a working module that’s fully integrated into your ABP.IO solution, following best practices.&lt;/p&gt;

&lt;p&gt;No guesswork, no skipping steps—just a clear path to getting your custom module up and running.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Install ABP CLI&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If not already installed, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet tool install -g Volo.Abp.Cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Create the main Apb.io application with the name “Vineforce.Admin”&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;abp new Vineforce.Admin -t app -u angular -m none --separate-auth-server --database-provider ef -csf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F76akokznkm5t55xjaz14.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F76akokznkm5t55xjaz14.webp" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It creates the structure of backend of main abp application as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgjuzej0v7numd1gtgb90.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgjuzej0v7numd1gtgb90.webp" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Configure appsettings.json of the main ABP.IO&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Edit the appsettings.json files in the two projects below to include the correct connection strings:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Projects:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vineforce.Admin.HttpApi.Host&lt;/li&gt;
&lt;li&gt;Vineforce.Admin.DbMigrator &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Create the Module folder in main application as Follow the official guide to create your module:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://abp.io/docs/4.3/Startup-Templates/Module" rel="noopener noreferrer"&gt;Official Guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Framr0dtys396gtf3l4hk.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Framr0dtys396gtf3l4hk.webp" alt="Image description" width="758" height="632"&gt;&lt;/a&gt;&lt;br&gt;
If you choose Angular as the UI framework (by using the -u angular option), the generated solution will include a folder named angular. This folder contains all the client-side code for the application. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; A module named Vineforce.Test was created using the Angular UI option.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. When you open the angular folder in an IDE, the folder structure will appear as follows:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fym1f0cdh5miyehbt6jgx.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fym1f0cdh5miyehbt6jgx.webp" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. And backend structure as follows:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo4ofnexe7942rv9fhqfc.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo4ofnexe7942rv9fhqfc.webp" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Configure appsettings.json&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Edit the appsettings.json file in the Host projects to include correct connection strings: &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Projects:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vineforce.Test.AuthServer &lt;/li&gt;
&lt;li&gt;Vineforce.Test.HttpApi.Host &lt;/li&gt;
&lt;li&gt;Vineforce.Test.Web.Unified
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"ConnectionStrings": { "Default": "Server=servername;Database=Test_Main;Trusted_Connection=True;TrustServerCertificate=True", "Test": "Server=VINEFORCE-SHIVA;Database=Test_Module;Trusted_Connection=True;TrustServerCertificate=True" }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Make sure the server names and database details match your development environment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbayhaf6ez7qpuk2y6hgv.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbayhaf6ez7qpuk2y6hgv.webp" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Apply Database Update&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;In the Package Manager Console (under the EntityFrameworkCore project), run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Update-Database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9t8kwg5ze4dwi9vhf1cl.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9t8kwg5ze4dwi9vhf1cl.webp" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Run the Application&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Set Vineforce.Test.Web.Unified as the startup project and launch the application using the default credentials:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Username: admin &lt;/li&gt;
&lt;li&gt;Password: 1q2w3E*&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;6. Ensure Redis Is Running&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Redis is used for distributed caching. Make sure Redis is installed and running before starting the application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Application Startup Order&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run the following projects in order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;*.AuthServer or *.IdentityServer
*.HttpApi.Host
*.Web.Unified
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;1. Adding a Module to the Backend of the Main Application&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd C:\Users\Vineforce\source\repos\AbpAdmin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Add All Required Projects of the module to the Main ABP.IO Solution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzn4nynus8yf4emkrakms.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzn4nynus8yf4emkrakms.jpg" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To include various parts of your module (such as Domain, Application, EntityFrameworkCore, and HttpApi) in the main ABP solution, run the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet sln add modules\vineforce.test\src\Vineforce.Test.Domain\Vineforce.Test.Domain.csproj
dotnet sln add modules\vineforce.test\src\Vineforce.Test.Application\Vineforce.Test.Application.csproj
dotnet sln add modules\vineforce.test\src\Vineforce.Test.EntityFrameworkCore\Vineforce.Test.EntityFrameworkCore.csproj
dotnet sln add modules\vineforce.test\src\Vineforce.Test.HttpApi\Vineforce.Test.HttpApi.csproj
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Projects are added as below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7fvp3e7mkhrx7g6e2zsj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7fvp3e7mkhrx7g6e2zsj.jpg" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Add Project References Using Visual Studio&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;In the Vineforce.Admin.HttpApi.Host project: Right-click the project and select “Add” → “Project Reference”.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. In the dialog that appears, check the following projects:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vineforce.Test.Application &lt;/li&gt;
&lt;li&gt;Vineforce.Test.EntityFrameworkCore &lt;/li&gt;
&lt;li&gt;Vineforce.Test.HttpApi &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Click OK to confirm and add the references.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftxixiehuq7ut4kyq2lug.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftxixiehuq7ut4kyq2lug.jpg" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. After adding the project &amp;gt; reference, here you can add all module references you want.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmvm6d6ul82p1kco7w8qd.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmvm6d6ul82p1kco7w8qd.jpg" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjxtqgptui8owtg1tuqg0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjxtqgptui8owtg1tuqg0.jpg" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Register Module Dependencies in AdminHttpApiHostModule.cs&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;In AdminHttpApiHostModule.cs, update the [DependsOn(...)] attribute:.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7jghsfgavvqc33im31kr.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7jghsfgavvqc33im31kr.jpg" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;typeof(TestHttpApiModule),
typeof(TestApplicationModule),
typeof(TestEntityFrameworkCoreModule),
typeof(TestDomainSharedModule)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, add the necessary using statements:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using Vineforce.Test;
using Vineforce.Test.EntityFrameworkCore;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuf7nlc37crunyjipzuqm.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuf7nlc37crunyjipzuqm.jpg" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configure the Module in the EntityFrameworkCore Project&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;To ensure that schema, table mappings, and other Entity Framework configurations from the module are applied in the main ABP.IO application, follow these steps:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Add a Project Reference:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Right-click on the Vineforce.Admin.EntityFrameworkCore project. &lt;br&gt;
Select &lt;strong&gt;Add → Project Reference.&lt;/strong&gt; &lt;br&gt;
Check and add: Vineforce.Test.EntityFrameworkCore &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F67a5q3brh3cvhlxz41i1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F67a5q3brh3cvhlxz41i1.jpg" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F40ebdqipjw64pcldrota.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F40ebdqipjw64pcldrota.jpg" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update the DbContext Configuration&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open AdminDbContext.cs.&lt;/li&gt;
&lt;li&gt;Inside the OnModelCreating method, add the following line to apply the module’s configuration:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;builder.ConfigureTest();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzf1yd0fe8pl9dnvevay.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvzf1yd0fe8pl9dnvevay.jpg" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnlg3nz8siqq6zax9phsd.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnlg3nz8siqq6zax9phsd.jpg" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can verify this by navigating to the Vineforce.Test.EntityFrameworkCore module and opening the TestDbContext class. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1zsyd4q0f0h9kre2psdr.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1zsyd4q0f0h9kre2psdr.jpg" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1txkc18xde517n8k112j.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1txkc18xde517n8k112j.jpg" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Apply Migrations to Update the Database Schema&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;After completing the integration steps, you need to apply Entity Framework migrations to reflect the module’s schema changes in the database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 1: Using PowerShell or Terminal&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open a &lt;strong&gt;PowerShell&lt;/strong&gt; or &lt;strong&gt;terminal&lt;/strong&gt; window. &lt;/li&gt;
&lt;li&gt;Navigate to the EntityFrameworkCore project directory of your main application, for example:cd src/Vineforce.Admin.EntityFrameworkCore&lt;/li&gt;
&lt;li&gt;Run the following command to create a new migration:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dotnet ef migrations add Add_Test_Module
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Option 2: Using the Package Manager Console in Visual Studio&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open the &lt;strong&gt;Package Manager Console&lt;/strong&gt; (Tools → NuGet Package Manager → Package Manager Console). &lt;/li&gt;
&lt;li&gt;Set the &lt;strong&gt;Default Project&lt;/strong&gt; to src\Vineforce.Admin.EntityFrameworkCore. &lt;/li&gt;
&lt;li&gt;Run the following command:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PM&amp;gt; Add-Migration Add_Test_Module
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This will generate a new migration that includes all Entity Framework changes from the integrated module.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyakw4yzy41d9brhejlne.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyakw4yzy41d9brhejlne.jpg" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then run the following command to apply the migration and update the database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Update-Database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Steps to add the module application to the main ABP.IO application&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Build the Angular Module&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;Navigate to the module’s frontend directory and build the module using the Angular CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ng build test --configuration production
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command compiles the test Angular module in production mode and outputs the build artifacts to the dist folder. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdvsfav87lli2kgowsbu3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdvsfav87lli2kgowsbu3.jpg" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Output folder: &lt;br&gt;
C:\Users\Vineforce\source\repos\AbpAdmin\modules\Vineforce.Test\angular\dist &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Famqyi3ef0kgd1qwfeekq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Famqyi3ef0kgd1qwfeekq.jpg" alt="Image description" width="768" height="104"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Copy Module Output to Main App&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to your main app’s angular folder: C:\Users\Vineforce\source\repos\AbpAdmin\angular&lt;/li&gt;
&lt;li&gt;Create a projects folder inside it. &lt;/li&gt;
&lt;li&gt;Copy the test folder from the dist directory into projects.&lt;/li&gt;
&lt;li&gt;Final pathC:\Users\Vineforce\source\repos\AbpAdmin\angular\projects\test&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffbzyginn7g7ht65zza6n.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffbzyginn7g7ht65zza6n.jpg" alt="Image description" width="768" height="777"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyhjumw4koqz9z22bbd7j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyhjumw4koqz9z22bbd7j.png" alt="Image description" width="768" height="144"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Update App Routing&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Open app-routing.module.ts in the main app: &lt;/p&gt;

&lt;p&gt;C:\Users\Vineforce\source\repos\AbpAdmin\angular\src\app\app-routing.module.ts &lt;/p&gt;

&lt;p&gt;In app-routing.module.ts, import the module’s routing configuration and add it to the main route definitions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  path: 'test',
  loadChildren: () =&amp;gt;
    import('test').then(m =&amp;gt; m.TestModule.forLazy())
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4: Link the Module in package.json&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Open the package.json file having path C:\Users\Vineforce\source\repos\AbpAdmin\angular  add the following line under the “dependencies” section to link your local module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"test": "file:projects/test"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv2n54lo306bdinpq1bbo.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv2n54lo306bdinpq1bbo.jpg" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then install dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can now see the Test Module API controller in the Swagger UI of the main application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpj7uwm1vituv247ychk7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpj7uwm1vituv247ychk7.jpg" alt="Image description" width="800" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can now log in to the main application &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn2u3pg480lr6fiztongs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn2u3pg480lr6fiztongs.png" alt="Image description" width="800" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Test module now appears in the main application. You can add, edit, or delete items according to the assigned permissions. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4fq2v2v39ei9yg2qfwyc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4fq2v2v39ei9yg2qfwyc.png" alt="Image description" width="800" height="169"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Country ‘Russia’ has been added. You can view, edit, or delete it on the page&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxfdecanqzema7nyzh7qd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxfdecanqzema7nyzh7qd.png" alt="Image description" width="800" height="160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can grant or revoke permission by this following page &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxej6gt39xgqm0xy91u39.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxej6gt39xgqm0xy91u39.png" alt="Image description" width="800" height="195"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faruxrz6hdoigfy5gjugf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faruxrz6hdoigfy5gjugf.png" alt="Image description" width="800" height="236"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now Edit permission has been disabled for the current user/page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frsi3zlhd0lgrut7rz94x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frsi3zlhd0lgrut7rz94x.png" alt="Image description" width="800" height="544"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Currently, the delete option is visible, but the edit option is not showing on the pagepermission has been disabled for the current user/page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkbkeyk699j0cqa2n4r2k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkbkeyk699j0cqa2n4r2k.png" alt="Image description" width="800" height="202"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By following this step-by-step guide, you’ve learned how to successfully integrate a custom module—like Vineforce.Test—into your ABP.IO application. From backend setup to Angular frontend integration, you now have a solid foundation for building scalable, maintainable, and modular applications. With best practices in place, your ABP.IO projects are ready to grow more efficiently.&lt;/p&gt;

&lt;p&gt;If you're looking for expert help with ABP.IO SaaS development, feel free to reach out to &lt;a href="https://www.vineforce.net/contact-us/" rel="noopener noreferrer"&gt;Vineforce&lt;/a&gt;. For more tutorials and insights like this, be sure to explore the &lt;a href="https://blog.vineforce.net/" rel="noopener noreferrer"&gt;Vineforce Blog&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>abp</category>
      <category>vineforce</category>
      <category>angular</category>
      <category>netcore</category>
    </item>
  </channel>
</rss>
