A team builds a useful application in Lovable. The workflow makes sense, the screens are good enough to put in front of users, and somebody asks when it can become an internal service. That is the point at which the conversation changes. The application needs an owner, a production identity, somewhere appropriate to run, and a way to release the next version without reconstructing the deployment by hand.
Azure App Service can provide that operating environment. Lovable can continue to provide the development experience. A Git repository connects them, giving the organization a place to review the generated code and decide which version becomes a release.
I have put together a reusable deployment starter for that arrangement. It includes infrastructure in Bicep, GitHub Actions workflows, a small deployment runtime, environment configuration, and an adoption guide. The design supports both the older React and Vite applications and the newer TanStack Start applications produced by Lovable. This article explains the choices in the package and walks through adopting it for an internal delivery-review application.
Download the deployment starter
The complete code is available in the Lovable-Deployment GitHub repository, under the MIT License. It includes the infrastructure, runtime, workflow templates, example configuration, tests, and setup guides described here.
For a one-time copy, download the source ZIP and extract it. You can also select Code → Download ZIP on the repository page. To retain the Git history and pull future updates, clone the repository:
git clone https://github.com/JasonLMiles/Lovable-Deployment.gitcd Lovable-Deployment
Start with the README, then follow the adoption guide. Copy azure/ into your Lovable application’s repository root and copy the three files in workflow-templates/ into that application’s .github/workflows/ directory. Merge with existing files and retain the MIT copyright and permission notice with the copied code. Your application’s source remains in its own repository.
Give the application a release boundary
Lovable supports two-way GitHub synchronization and lets the project select the branch it edits. The practical arrangement is to let Lovable work on a development branch and require a reviewed pull request into the branch that releases the application. Developers can work in the same repository, and the organization keeps its normal history and review process. [1]
That release boundary is valuable because development and production operate at different speeds. A business user may refine a screen several times in an afternoon. Production should change when a specific revision has passed the relevant checks and someone is prepared to own the result.
In the starter, a merge to main starts a build. The resulting ZIP carries the full Git commit identifier and a checksum. That package is deployed to staging, checked, and promoted after approval. Production receives the build that was inspected in staging. Dependencies are resolved during CI, where the lockfile and build output can be retained.
Start with the application that actually exists
The first implementation step is to inspect package.json. Lovable’s external-hosting documentation distinguishes two deployment shapes. React/Vite projects produce static files. TanStack Start projects include server execution and need a runtime capable of running it. The presence of @tanstack/react-start identifies the latter. [2]
| Application shape | Release contents | Runtime behavior |
|---|---|---|
| React and Vite | The dist directory | Serve browser assets and resolve client routes |
| TanStack Start with Nitro | The complete .output directory | Run the generated Node server and serve its assets |
For TanStack, the build uses NITRO_PRESET=node-server. The expected entry point is .output/server/index.mjs. The repository must have Nitro and a current compatible Lovable build configuration. The packager checks for that output and fails when it is missing. [2]
The starter deploys to Linux App Service with Node.js 22. Its runtime serves a Vite build directly or forwards HTTP requests to the generated TanStack server on a loopback port. It also provides a health endpoint and the browser configuration endpoint. This keeps the Azure deployment contract consistent across the two application shapes.
Make the platform reusable
The Bicep template provisions an App Service plan, the application, a staging slot, runtime identity, deployment identities, authentication settings, and Log Analytics. It connects to an existing Key Vault and grants the runtime identity access to the login secret. An optional networking module creates private endpoints for production and staging.
I chose a compiled ZIP as the deployment unit. App Service supports this model, and Azure CLI can deploy the package through its deployment endpoint. The archive contains the files needed to run the application, with its entry structure at the archive root. Build automation on the destination is disabled. [3]
The infrastructure and application release processes remain separate. Infrastructure changes can be reviewed with Bicep what-if. Application changes use the established host and settings. A routine screen change therefore does not need permission to create identities, change networking, or assign Azure roles.
Work through one application
Consider an internal delivery-review tool that shows project status and lets assigned delivery managers update a review. This is an illustrative application, with no assumed client data. The first release will keep its existing backend, while Azure takes responsibility for the web application and its workforce sign-in boundary.
The people adopting the starter need repository administration access, Azure permissions to deploy resources and assign roles, and support from an Entra administrator. They also need a GitHub plan that supports the required environment protections for their repository. Those prerequisites belong in the setup plan because they determine who can complete the handoff. [4]
1 Prepare the repository and checks
Copy azure/ into the application’s repository root and the three workflow-templates/*.yml files into its .github/workflows/ directory. Preserve existing automation. Configure Lovable to edit a development branch, then protect main with pull-request review and the validation check. Assign platform owners to review changes to the infrastructure and workflows.
The package standardizes on npm and a committed package-lock.json. Its preflight requires real build, lint, typecheck, and test:ci scripts. These commands should validate the actual project. For example, a TypeScript command that points at an empty root configuration can succeed without checking the application.
For the delivery-review tool, include a test of who may change a review and what happens when required information is missing. That connects the pipeline to a behavior the service owner cares about. The template’s own tests cover hosting and packaging; application tests cover the work users perform.
2 Move browser configuration to startup
Frontend configuration is an easy source of deployment mistakes. Vite replaces browser environment values at build time. A backend URL compiled into JavaScript will remain there when that bundle reaches another environment. Values prefixed with VITE_ are exposed to the browser and must not contain secrets. [5]
The starter provides /_deployment/runtime-config.json. The browser reads it before creating its API clients. The runtime returns a fixed allowlist of values such as the application name, environment label, API address, and an optional Supabase publishable key. It sends Cache-Control: no-store and ignores every environment variable outside that allowlist.
Integrating the supplied loader requires a small application change. Existing production client initialization must use the returned object. Server functions continue to read server settings directly. For Lovable previews, retain a development-only path that uses nonproduction services. The adoption guide includes this complete implementation prompt:
Prepare this application’s browser configuration for Azure deployment. Inspect the existing frontend initialization and Supabase or API clients. Add a typed loader that fetches /_deployment/runtime-config.json with credentials same-origin and cache no-store before creating those clients. Return appName, environment, apiBaseUrl, supabaseUrl, and supabasePublishableKey. Preserve nonproduction preview behavior behind import.meta.env.DEV. Keep server secrets in server environment variables. Preserve authentication and data-access rules. Remove production dependencies on browser build-time backend URLs. Add tests for configuration-load failure and the existing business rules. Identify any backend behavior needing a separate migration. Do not modify azure/ or .github/workflows/.
This makes the requested code change specific enough to inspect. Repository protections carry the review requirement.
3 Establish identity and provision the host
Create a single-tenant Entra web application registration with callback URLs for production and staging. Require user assignment on the associated enterprise application and assign the intended users or groups. Store the login application’s secret in an application-specific Key Vault and record its versionless secret URI.
App Service authentication handles the sign-in boundary. The delivery application still has to decide which manager can edit which review, and the backend must enforce that decision on the actual API or data operation. Microsoft makes the distinction between authentication and authorization explicit in its documentation. [6]
Fill in the Bicep parameters with the application name, GitHub repository, login client ID, Key Vault reference, and environment values. Review the planned infrastructure change before creating it:
az deployment group what-if \ --resource-group YOUR-RESOURCE-GROUP \ --template-file azure/infra/main.bicep \ --parameters @azure/parameters.production.jsonaz deployment group create \ --name lovable-platform \ --resource-group YOUR-RESOURCE-GROUP \ --template-file azure/infra/main.bicep \ --parameters @azure/parameters.production.json
The runtime identity reads the configured Key Vault secret. GitHub uses a separate OIDC relationship with Azure, exchanging its workflow identity for short-lived access. The template has distinct identities for staging deployment and production promotion, with environment-specific trust subjects. [7, 8]
4 Protect and configure the release environments
Create GitHub environments named staging and production. Permit only main to deploy to either. Require reviewers for production and prevent self-review. Run the supplied configuration script to check those settings and populate the environment variables from the Bicep deployment outputs.
The release workflow builds once, packages the result, checks its checksum, and deploys staging. It then verifies the expected commit through /healthz and checks that anonymous requests to the app and configuration endpoint are redirected to sign-in.
Approval pauses the workflow with that candidate in place. A shared concurrency group prevents another release from replacing staging while the approval is pending. Immediately before promotion, the workflow checks the staged commit again. This makes the approval refer to an identifiable application version.
5 Verify a business outcome and promote
For the worked example, sign in as an assigned delivery manager, open a review, update it, and verify that the backend retained the change. Attempt an operation the user is not permitted to perform. Also verify that an unassigned user cannot enter the application.
Record those observations with the commit and workflow run. Approve the production environment when they meet the application’s acceptance criteria. The workflow swaps staging into production and repeats its release checks. App Service deployment slots provide the staging and swap mechanism; they require a qualifying service tier, which the starter provisions. [9]
This staging slot is configured as a production release-validation slot. It shares the production service configuration and plan capacity. Development, UAT, and load testing should have separately provisioned environments suited to their work.
Handle the backend as an explicit scope decision
The first delivery-review release can keep its current backend. That preserves the application’s existing data contract while establishing the Azure release process. The implementation team still needs to confirm allowed origins, authentication redirects, and integration callbacks for the new host.
If the requirement is to bring the whole runtime into Azure, work through each backend capability. A database move addresses records and schema. Authentication, file storage, server functions, realtime behavior, schedules, and AI or connector gateways need their own destinations and code changes. Lovable documents these as distinct migration concerns. [10]
The starter includes a backend mapping guide for that decision. Its purpose is to make the additional engineering visible before committing to a migration. Keeping Supabase, operating a compatible stack, and replacing its services with Azure components each imply a different amount of application change.
Plan for private access and recovery
For an internal private service, the networking module creates separate endpoints for production and staging and attaches them to an existing private DNS zone. The deployment runner must resolve and reach the SCM endpoint as well as the application endpoint. App Service’s private endpoint documentation specifically describes the additional SCM DNS requirement. [11]
After a successful swap, the former production version occupies staging. The rollback workflow checks the expected versions before swapping back. The operator must first confirm that the older application still works with the current database and other service contracts. If staging has been overwritten, the operations guide describes restoring the retained artifact and verifying it again.
Health checks and logging support that operation. For TanStack, the host probes an internal application route; the application can supply a dependency-aware readiness route. For Vite, the host checks the browser entry point. Azure Monitor receives runtime and platform logs, while the service owner configures alert thresholds and destinations appropriate to the application. [12]
What has been verified
The starter’s infrastructure has been compiled with the Bicep CLI. Local tests exercised browser deep links, missing assets and API routes, filesystem escape attempts, the configuration allowlist, server-rendered responses, POST bodies, multiple cookies, streaming, and the contents of both release-package shapes. These are observed checks of the starter components.
The package has not been deployed into a customer Azure tenant or attached to a particular Lovable repository. The first adoption therefore includes the tenant-specific checks already described: OIDC permissions, private connectivity if selected, real sign-in, backend authorization, application behavior, and a rollback rehearsal. The supplied verification record makes that handoff explicit.
Make the second application easier
The practical payoff arrives when another team has a useful application ready for users. It can supply its source, tests, environment values, and backend decisions to an established deployment process. Platform engineers maintain the common runtime and infrastructure. Application owners spend their review effort on the behavior and data access that make their application different.
Begin with one bounded application and complete the first release and rollback cycle. Keep the resulting configuration, evidence, and operating instructions with its repository. Once that path is proven in the organization, package its approved choices for the next team. Lovable can then contribute to an ongoing software delivery capability, with Azure and the organization’s release process providing a place for the resulting applications to live.