Skip to content

Deploy the api to Render

Create the production api and its two scheduled jobs from the repo's render.yaml blueprint. About 15 minutes; it creates Render services and applies every database migration to the production Supabase project.

Before you start

Steps

  1. In Render, choose New → Blueprint and pick the repository. Render reads render.yaml, which defines both environments: monark-api, monark-cron-deletions, monark-cron-webhook-sweep and the monark-cron-shared group on main, and the same names with -staging on develop.

  2. Fill the monark-cron-shared group:

    KeyValue
    CRON_SECRETyour CRON_SECRET
    API_URLhttps://monark-api.onrender.com (a placeholder; fixed in step 6)
  3. Fill the monark-api prompts:

    KeyValue
    DATABASE_URL, DIRECT_URLthe pooler and direct URLs
    SUPABASE_URL, SUPABASE_PUBLISHABLE_KEY, SUPABASE_SECRET_KEYfrom Supabase
    WEB_ORIGIN, APP_URLhttps://monark.vercel.app (placeholders; fixed in the next phase)
    SMTP_URLyour SMTP URL
    SMTP_FROMMonark <noreply@yourdomain.com>
    TOTP_ENCRYPTION_KEY, SECRETS_ENCRYPTION_KEYyour generated keys
    INITIAL_ORG_SLUG, INITIAL_ORG_NAMEyour organization's slug and display name
    INITIAL_ORG_PRIMARY_COLORyour brand colour, quoted: "#2563EB"

    Leave SENTRY_DSN, WEBHOOK_SECRETS_JSON and the BRANDING_* keys blank for now; Rebrand an instance and Turn on error tracking cover them. Leave the -staging services for Add a staging environment; they fail to start until then.

  4. Click Apply. Render installs, runs prisma generate, then runs pnpm --filter @monark/db exec prisma migrate deploy before starting the api. A failed migration aborts the deploy and leaves nothing running.

  5. Once monark-api is live, open it, go to Environment, and add EMAIL_ACTION_SECRET with your generated value. It isn't in the blueprint, and without it the api signs email links with a public development value. Save; Render redeploys.

  6. Copy the service's public URL (for example https://monark-api.onrender.com) and set it as API_URL in the monark-cron-shared group.

Verify

curl -s https://<api-host>/health

Expect {"status":"ok","service":"api"}. The api's log shows webhook delivery worker started, Single-tenant bootstrap : created singleton organization and api listening.

If something goes wrong

SymptomCauseFix
Deploy stops at the pre-deploy stepprisma migrate deploy couldn't reach or migrate the databaseCheck DIRECT_URL and its password, then Manual Deploy.
Log shows Invalid environment: and the process exitsa required variable is missing or malformedFix the key named in the message.
Log shows INITIAL_ORG_SLUG / INITIAL_ORG_NAME not setthe org variables are emptySet them and redeploy.
INITIAL_ORG_PRIMARY_COLOR ignoredthe hex value wasn't quotedRe-enter it as "#2563EB".
Cron runs fail with CRON_SECRET unset or status 401the group value is missing or differs from the api'sMake both read from monark-cron-shared.

Next: Deploy the web app to Vercel