Libra CodeHub

CedarCopilot/cedar-mail

Branch: staging

feat(deploy): serve the marketing site from cedarcopilot.com

merged#2629CedarCopilot

CedarCopilot wants to merge 2 commits into staging from fix/marketing-apex-flip

Live on prod, no production signal yetTimeline and evidence
  1. Opened
    Aug 30, 2026, 7:15 PM
  2. Aug 30, 2026, 11:05 PM
  3. Merged
    Aug 30, 2026, 11:14 PM
  4. Live on prod
    Aug 30, 2026, 11:14 PM
  5. Observed 2 hours
    Aug 30, 2026, 11:14 PM
  6. Pipelines steady after this deploy
    Aug 30, 2026, 11:14 PM
  7. Unobserved

    Live on prod, no production signal yet

    Aug 31, 2026, 1:22 AM

Behaviors Libra is checking

Email workflow behavior from mail/vite.config.ts keeps working in prod.Inconclusivelow confidence

Strict CloudWatch fallback saw 3,675 success-shaped log lines matching email, emails, gmail, mail, inbox, but no tied operation was present, so Libra is not calling this working.

prod, checked Aug 31, 2026, 1:22 AM

Libra has verdicts on 0 of 1 tracked behaviors on prod; 1 is still being checked. Libra checks hourly for 3 days after each deploy.

āš ļø Do not merge until the apex resolves to CloudFront

Draft on purpose. This PR is the switch. Once it lands, the next prod frontend deploy , including one shipped for an unrelated reason , starts bouncing marketing paths to the apex and app paths back to mail.*. If the apex still 301s to mail.cedarcopilot.com at that moment, the result is a redirect loop on /pricing, /blog and /bookdemo.

Merge only after the Cloudflare cutover (apex redirect rule deleted, apex + www CNAMEd to d3dcq98iblzth4.cloudfront.net).

Stacked on #2628, which attaches the aliases.

Summary

Derive the marketing origin per environment in publish-frontend-assets.sh instead of carrying it as a deploy variable:

cedar_marketing_url_for_env() {
  case "$1" in
    staging) printf '\n' ;;
    prod)    printf 'https://cedarcopilot.com\n' ;;
  esac
}

The apex is permanently the marketing home, so there is nothing per-deploy to decide. This matches how the app and API domains already resolve , a per-env default in code, overridable by env var.

Staging must stay empty rather than inherit the prod apex. With a marketing host set, useHostRouting would bounce mail-staging.cedarcopilot.com/pricing to production.

The host-split code itself (lib/marketing-host.ts, hooks/use-host-routing.ts, app/page.tsx) already shipped and has been inert; this is what activates it.

Rollback

VITE_PUBLIC_MARKETING_URL still wins if set in the environment, so an urgent rollback needs no commit , set it to the app origin and redeploy the frontend, and both origins go back to serving the whole site. Longer term, point cedar_marketing_url_for_env at the app origin.

Test plan

Change is 1 workflow YAML, 2 bash scripts, 1 markdown doc. Zero TS/JS.

  • cedar_marketing_url_for_env returns https://cedarcopilot.com for prod and empty for staging; sourcing it through the publish-frontend-assets.sh export path yields VITE_PUBLIC_MARKETING_URL="https://cedarcopilot.com" for prod and "" for staging (which hasSplitHosts() reads as not-split).
  • bash -n clean on both scripts; workflow parses as valid YAML.

pnpm run autofix:local was not run: every stage of it operates on application code this change cannot touch.

šŸ¤– Generated with Claude Code

Greptile Summary

This PR activates production host splitting by deriving the marketing origin during frontend publication, keeps staging unsplit, and documents the CloudFront and DNS cutover.

  • Adds environment-specific marketing URL derivation to the frontend publisher.
  • Supplies a production marketing URL during the AWS pull-request build.
  • Expands the deployment guide with certificate, Cloudflare, cutover, and rollback guidance.

Confidence Score: 4/5

The staging frontend artifact regression should be fixed before merging; the CI configuration mismatch is also worth aligning.

Exporting an empty staging marketing URL reaches the SEO generator without falling back to the staging app origin, producing relative robots and sitemap locations, while the pull-request build additionally exposes an override that production deployment ignores.

Files Needing Attention: aws/scripts/publish-frontend-assets.sh, .github/workflows/aws-builds.yml

Important Files Changed

FilenameOverview
aws/scripts/publish-frontend-assets.shAdds the marketing URL build export, but its empty staging value produces origin-less SEO artifacts through the existing Vite configuration.
aws/scripts/deploy-utils.shAdds deterministic staging and production marketing URL defaults with unsupported-environment validation.
.github/workflows/aws-builds.ymlBuilds the production frontend with the apex default, but introduces an override variable that the deployment path does not recognize.
aws/docs/marketing-domain-split.mdDocuments the alias, certificate, DNS, cutover,
Show production surfaces and changed-file mapping

Production surfaces

Libra has not measured any production surfaces for this change yet.

Changed files → surfaces

  • .github/workflows/aws-builds.ymlno production surface mapped
  • apps/mail/vite.config.tsno production surface mapped
  • aws/docs/marketing-domain-split.mdno production surface mapped
  • aws/scripts/deploy-utils.shno production surface mapped
  • aws/scripts/publish-frontend-assets.shno production surface mapped