Skip to main content
Every fact on this page is labeled as of July 2026. This topology is the live YC-demo deployment, distinct from — and, as explained below, currently architecturally behind — the AWS/Azure IaC and local product stack documented elsewhere in Cloud environments. Treat this page as “what’s actually running,” not “what we’re building toward.”

Topology

  • app.causeloop.ai is a Vercel project named frontend, with its production branch set to release_demo. The entire causeloop.ai DNS zone runs on Vercel’s nameservers.
  • api.causeloop.ai is a CNAME to causeloop-backend.onrender.com — a Render web service.
backend/render.yaml (the Render Blueprint committed to this repo) names the web service causeloop-api, but the live hostname resolves to causeloop-backend.onrender.com. A Blueprint-managed service’s default Render hostname follows its name: field, so this mismatch is a strong signal that the live api.causeloop.ai backend was created manually in the Render dashboard (or renamed after creation) rather than purely from render.yaml. Don’t assume every setting on the live service — plan, scaling, alerting — matches the Blueprint exactly; verify in the Render dashboard before relying on a Blueprint-only assumption.

What render.yaml actually defines

As of this writing, render.yaml is not present in this backend repository’s current working branch — it was removed in the same commit that introduced the new product_app.py allowlisted API, infra/docker-compose.product.yml, and the deploy/aws/deploy/azure IaC (that work has not yet been merged into main or release_demo). The content below is what’s committed on the main and release_demo branches on GitHub, which is what the live Render deployment actually reads from. If you’re reading this from a checkout where render.yaml doesn’t exist at the repo root, that’s expected — go look at release_demo for the file this page describes.
render.yaml is a Render Blueprint defining one database, one Redis instance, and two services:
A few things worth reading carefully in the comments this file carries in the repo:
  • env: python, not runtime: python. An earlier version of this file used runtime: python (not a valid Blueprint key) with a pip install uv && ... build command; Render silently ignored both and fell back to its own default pip install -r requirements.txt detection, which fails outright since this project has no requirements.txt (it’s uv/pyproject.toml-managed). env: python is the key that actually makes buildCommand: uv sync --frozen run — Render’s Python environment already provisions uv itself.
  • alembic upgrade heads (plural) does not work here. The startCommand explicitly targets two revisions by ID — 20260714_0007 (the unlabeled/default branch head at the time this file was last edited) and 20260722_c002 (the control branch) — rather than alembic upgrade heads. That’s because the tenant_template branch is applied per-tenant by the provisioner at provisioning time, with -x schema=<tenant_schema> (see Migrations), and refuses to run without that argument. Targeting heads would fail on a fresh database for exactly that reason.
That startCommand is stale relative to the current migrations/ directory: the control branch has since grown a third revision (20260727_c003_durable_platform_jobs.py), which this startCommand never applies. If release_demo is ever fast-forwarded to include the durable-platform-jobs work without also updating this startCommand to alembic upgrade control@head (or the new head revision ID), the live API will start against a database missing that migration. See Migrations for the full branch layout.
The startCommand boots services.api.main:app — the historical, ~258-endpoint research application — not services.api.product_app:app, the allowlisted product surface described throughout the rest of this documentation set and used by every other environment’s Dockerfile CMD. This is a direct consequence of render.yaml (and the main/release_demo branches generally) predating the product_app.py split: at the commit these branches are currently on, services/api/main.py was the only application that existed. Until the newer product-boundary work is merged into release_demo, the live demo is running the legacy app, not the minimal allowlisted boundary.
Also note: this Blueprint provisions no object store and no email provider — there is no S3/Blob equivalent or SES/Communication-Services equivalent wired into causeloop-api or causeloop-pipeline-worker here. Whatever object storage and email delivery the demo currently relies on is whatever the pre-product_app.py application generation used; it is not the MinIO→S3/Blob or Mailpit→SES/ACS Email substitution described in Cloud environments, because that split is part of the same unmerged work.

The release_demo branch strategy

Both github.com/causeloop/backend and github.com/causeloop/frontend keep main as their default branch. release_demo is a separate, deliberately narrower branch that only ever receives what should currently be live at app.causeloop.ai / api.causeloop.ai. The reason, in the Blueprint’s own comment: deploying release_demo instead of main means day-to-day development on main can’t break the live demo. To ship a demo fix:
1

Land the fix on main as usual

Open a normal PR against main, review, and merge it there first — main is still the branch of record for ongoing work.
2

Merge or cherry-pick the fix into release_demo

Either merge main into release_demo (if you want everything currently on main) or git cherry-pick just the specific commit(s) that fix the demo-visible issue, if you don’t want to pull in unrelated in-flight work.
3

Push release_demo

A push to release_demo on github.com/causeloop/backend triggers Render’s Blueprint sync for causeloop-api and causeloop-pipeline-worker; a push to release_demo on github.com/causeloop/frontend triggers a Vercel production deployment for the frontend project.
4

Verify before announcing the fix is live

Check the Render service logs for the new build/deploy and confirm GET /health (the Blueprint’s healthCheckPath) returns healthy, then click through the actual demo flow the fix addresses.
This keeps the demo’s git history intentionally curated: release_demo should only ever contain commits someone deliberately decided belonged in the demo, never an accidental side effect of merging main.

Vercel deploy gotcha: commit author identity

Vercel’s GitHub integration only triggers a deploy for commits authored by the GitHub identity the integration is connected to. If a commit on release_demo (or on whatever branch feeds it) is authored by a different GitHub identity, Vercel silently skips the deploy — no error, just no new deployment. The frontend repo works around this with a repo-local git config author:
Because this is repo-local (not global), it only applies to commits made inside that specific checkout of the frontend repo — anyone pushing to release_demo on the frontend repo from a different clone (or with a different global git identity) should confirm this repo-local author config is in effect, or a merge/cherry-pick that looks successful in git can still fail to produce a new Vercel deployment.