Skip to content

feat(webapp): custom domain support, social graph assets & hardened sync prompt#110

Open
webmaxru wants to merge 32 commits intomicrosoft:mainfrom
webmaxru:webapp-custom-domain
Open

feat(webapp): custom domain support, social graph assets & hardened sync prompt#110
webmaxru wants to merge 32 commits intomicrosoft:mainfrom
webmaxru:webapp-custom-domain

Conversation

@webmaxru
Copy link
Copy Markdown
Contributor

@webmaxru webmaxru commented Apr 1, 2026

Summary

Extends the AgentRC web app with four improvements grouped into one PR since they shipped together on the webapp branch.


1. Configurable Custom Domain Name

Adds first-class support for binding a custom domain (with managed TLS certificate) to the Container Apps deployment and dynamically rendering absolute URLs in OG/Twitter meta tags.

Infrastructure (infra/webapp/main.bicep)

  • New parameters: customDomain (string), customDomainCertReady (bool, two-phase deploy), and useAcrAdminCredentials (bool, fallback for limited SP permissions)
  • Microsoft.App/managedEnvironments/managedCertificates resource, provisioned only when both params are set
  • customDomains array on the Container App ingress — SniEnabled when cert is ready, Disabled while DNS is pending
  • User-assigned managed identity (acrPullIdentity) with AcrPull role assignment — used by default instead of ACR admin credentials (admin mode still available via useAcrAdminCredentials flag)

CI/CD (.github/workflows/webapp-cd.yml)

  • Two-step Bicep deployment: first registers the domain (cert disabled), second binds the managed certificate
  • Reads vars.CUSTOM_DOMAIN and vars.CUSTOM_DOMAIN_CERT_READY from GitHub environment variables
  • Smoke test extended to verify the custom domain endpoint when active

Backend (webapp/backend/src/server.js)

  • parseCustomDomain() — validates and normalises CUSTOM_DOMAIN env var to a bare hostname at startup
  • renderIndex() — replaces %SITE_URL% placeholders in index.html at request time; uses pre-rendered HTML when a custom domain is configured, otherwise derives the base URL from the Host / X-Forwarded-Host header
  • SPA catch-all updated to use renderIndex() for consistent OG meta across all routes

Param file (infra/webapp/main.bicepparam)

  • Example values added (customDomain, customDomainCertReady)

Docker (Dockerfile.webapp)

  • Fixed frontend copy path (/app/frontend//app/webapp/frontend/) so static assets are found at runtime

Config (webapp/.env.example)

  • Added CUSTOM_DOMAIN env var documentation

Tests (webapp/backend/tests/routes.test.js)

  • 4 new tests verifying %SITE_URL% replacement on root and SPA catch-all routes with and without CUSTOM_DOMAIN

2. Social Graph (Open Graph & Favicon) Assets

Provides rich link-preview graphics when the webapp URL is shared on social platforms (Twitter/X, Slack, LinkedIn, etc.).

Assets added (webapp/frontend/assets/)

  • favicon.svg — scalable vector favicon
  • favicon.ico, favicon-16x16.png, favicon-32x32.png — classic favicons
  • apple-touch-icon.png, favicon-192x192.png, favicon-512x512.png — mobile/PWA icons
  • og-image.jpg and og-image.png — 1200×630 Open Graph preview images
  • site.webmanifest — PWA web manifest referencing icons

HTML (webapp/frontend/index.html)

  • Full set of <link rel="icon"> tags for all favicon sizes and formats
  • Open Graph meta tags (og:title, og:description, og:image, etc.) with %SITE_URL% placeholder for absolute URLs
  • Twitter Card meta tags (twitter:card, twitter:image, etc.)
  • theme-color meta tag

Tooling (webapp/frontend/scripts/generate-favicons.mjs)

  • Node script using sharp to regenerate all PNG sizes + ICO from the SVG source
  • Dev dependency sharp added to webapp/frontend/package.json

Tests (webapp/frontend/tests/favicon-og.test.js)

  • 30+ assertions: asset existence, PNG/JPEG/ICO binary signatures, HTML <link> / <meta> tags, manifest schema

3. Hardened Synchronization Prompt

Updates the Copilot prompt used for aligning CLI and webapp reports.

.github/prompts/align-cli-webapp-reports.prompt.md

  • Clarifies the "source of truth" constraint: all fixes must be in webapp/ only, never in packages/core/ or src/
  • Documents the architecture reference (shared core, CLI rendering, webapp backend/frontend) for safer AI-assisted debugging
  • Adds explicit rules about countStatus() excluding skipped checks and extras being non-scored

Test plan

# Existing unit tests
cd webapp/frontend && npx vitest run tests/favicon-og.test.js
cd webapp/frontend && npx vitest run tests/progress-spinner.test.js
cd webapp/backend && npx vitest run

# Infra — validate Bicep
az bicep build --file infra/webapp/main.bicep

# Visual — open index.html and verify favicon + OG tags in DevTools

webmaxru added 4 commits April 1, 2026 09:46
- Added favicon.ico and favicon.svg files for the application.
- Included og-image.png for Open Graph sharing.
- Created site.webmanifest for PWA support with icons.
- Implemented generate-favicons.mjs script to automate favicon generation from SVG.
- Added tests for favicon assets and Open Graph meta tags in index.html.
Copilot AI review requested due to automatic review settings April 1, 2026 19:59
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the AgentRC webapp with infrastructure support for custom domains + managed TLS, adds social/SEO assets (favicons, web manifest, Open Graph/Twitter tags) with a favicon generation script and tests, and tightens the “align CLI vs webapp report” prompt to enforce webapp-only fixes.

Changes:

  • Add Azure Container Apps custom-domain parameters + managed certificate workflow, and switch ACR pulls to a user-assigned managed identity.
  • Add favicon/OG/PWA asset set, generation script (sharp), and a Vitest suite verifying assets + HTML/meta/manifest wiring.
  • Harden the alignment prompt to treat CLI/core as the source of truth and constrain fixes to webapp/.

Reviewed changes

Copilot reviewed 9 out of 19 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
webapp/frontend/index.html Adds favicon <link> tags + Open Graph/Twitter meta tags.
webapp/frontend/assets/site.webmanifest Adds PWA manifest referencing 192/512 icons.
webapp/frontend/assets/favicon.svg Adds SVG favicon source.
webapp/frontend/assets/favicon.ico Adds ICO favicon asset.
webapp/frontend/assets/favicon-16x16.png Adds 16×16 PNG favicon asset.
webapp/frontend/assets/favicon-32x32.png Adds 32×32 PNG favicon asset.
webapp/frontend/assets/favicon-192x192.png Adds 192×192 PNG icon asset.
webapp/frontend/assets/favicon-512x512.png Adds 512×512 PNG icon asset.
webapp/frontend/assets/apple-touch-icon.png Adds Apple touch icon asset.
webapp/frontend/scripts/generate-favicons.mjs Adds a script to regenerate PNG/ICO assets from the SVG using sharp.
webapp/frontend/tests/favicon-og.test.js Adds tests validating asset presence/signatures and HTML/meta/manifest wiring.
webapp/frontend/package.json Adds sharp as a dev dependency for the generator script.
webapp/frontend/package-lock.json Locks sharp and its transitive deps.
infra/webapp/main.bicep Adds custom domain + managed cert resources and switches ACR pull auth to a user-assigned identity.
infra/webapp/main.bicepparam Adds example parameters for customDomain and customDomainCertReady.
.github/workflows/webapp-cd.yml Implements two-phase infra deploy (domain registration then cert bind) and custom-domain smoke test.
.github/prompts/align-cli-webapp-reports.prompt.md Tightens guidance: CLI/core is source of truth; fixes must be in webapp/ only.
Files not reviewed (1)
  • webapp/frontend/package-lock.json: Language not supported

Copilot AI review requested due to automatic review settings April 1, 2026 21:45
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 11 out of 21 changed files in this pull request and generated 3 comments.

Files not reviewed (1)
  • webapp/frontend/package-lock.json: Language not supported
Comments suppressed due to low confidence (1)

.github/workflows/webapp-cd.yml:159

  • Step 2 also hard-codes useAcrAdminCredentials=true, so even after the domain/cert second-phase deploy the infra continues to rely on ACR admin credentials rather than the user-assigned identity path. If the intention is to harden by default, propagate a consistent useAcrAdminCredentials value (ideally false) to both deploy steps.
          parameters: >
            containerImageTag=${{ needs.build-push.outputs.image-tag }}
            ghTokenForScan=${{ secrets.GH_TOKEN_FOR_SCAN }}
            useAcrAdminCredentials=true
            customDomain=${{ vars.CUSTOM_DOMAIN || '' }}
            customDomainCertReady=true

Copilot AI review requested due to automatic review settings April 1, 2026 22:19
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 22 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • webapp/frontend/package-lock.json: Language not supported
Comments suppressed due to low confidence (1)

webapp/backend/src/server.js:143

  • Only / and the SPA catch-all return the processed index.html. Requests to /index.html will still be served by express.static() as the raw file containing %SITE_URL%, which defeats the goal of always emitting absolute OG/Twitter URLs for that path. Consider also serving a processed response for /index.html (or prevent static from serving it) so the placeholder never leaks.
  // Serve processed index.html for root requests
  app.get("/", (req, res) => {
    res.type("html").send(renderIndex(req));
  });

  // Static frontend files (other assets)
  app.use(express.static(runtime.frontendPath));

  // SPA catch-all: serve processed index.html for non-API routes
  app.get(/^\/(?!api\/).*/, (req, res) => {
    res.type("html").send(renderIndex(req));

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 1, 2026 22:27
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 22 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • webapp/frontend/package-lock.json: Language not supported

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 1, 2026 22:38
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 22 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • webapp/frontend/package-lock.json: Language not supported

webmaxru and others added 2 commits April 2, 2026 00:46
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 1, 2026 23:19
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 24 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • webapp/frontend/package-lock.json: Language not supported

webmaxru and others added 2 commits April 2, 2026 01:24
Copilot AI review requested due to automatic review settings April 1, 2026 23:27
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 24 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • webapp/frontend/package-lock.json: Language not supported

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 2, 2026 07:30
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 24 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • webapp/frontend/package-lock.json: Language not supported

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 26 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • webapp/frontend/package-lock.json: Language not supported

webmaxru added 2 commits April 2, 2026 13:28
The eval workflow triggers on .github/**/*.instructions.md and
.github/copilot-instructions.md path changes. Since fork PRs cannot
access repository secrets (COPILOT_TOKEN), the eval step fails with
an auth error and the Node process hangs until the 30-min job timeout.

These Copilot instruction files will be re-added in a follow-up commit
directly on the base repo where secrets are available.
Copilot AI review requested due to automatic review settings April 2, 2026 16:47
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 24 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • webapp/frontend/package-lock.json: Language not supported

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 2, 2026 17:20
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 24 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • webapp/frontend/package-lock.json: Language not supported

Comment on lines +83 to +90
afterEach(() => {
server?.close();
// Restore original CUSTOM_DOMAIN so we don't leak state to other suites.
if (savedCustomDomain !== undefined) {
process.env.CUSTOM_DOMAIN = savedCustomDomain;
} else {
delete process.env.CUSTOM_DOMAIN;
}
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

server.close() is asynchronous, but the suite (and several tests) call server?.close() and then immediately start a new server without waiting for the close callback. This can create intermittent test flakiness and resource leaks, especially now that the new templating tests restart the server multiple times. Consider awaiting close (e.g., wrap in a Promise and await) in afterEach and before re-listening inside tests.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants