> ## Documentation Index
> Fetch the complete documentation index at: https://docs.aspfox.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy to Render

> Deploy AspFox to Render using render.yaml infrastructure-as-code configuration.

Render offers a free tier suitable for testing and low-traffic applications. AspFox includes a `render.yaml` file that configures all services via Render's Blueprints feature.

## render.yaml

Add this file to the root of your repository:

```yaml theme={null}
# render.yaml
services:
  - type: web
    name: acme-api
    env: docker
    dockerfilePath: ./Dockerfile
    plan: starter
    healthCheckPath: /health
    envVars:
      - key: ASPNETCORE_ENVIRONMENT
        value: Production
      - key: DATABASE_URL
        fromDatabase:
          name: acme-db
          property: connectionString
      - key: REDIS_URL
        fromService:
          name: acme-redis
          type: redis
          property: connectionString
      - key: JWT_PRIVATE_KEY
        sync: false
      - key: JWT_PUBLIC_KEY
        sync: false
      - key: JWT_ISSUER
        sync: false
      - key: JWT_AUDIENCE
        sync: false
      - key: STRIPE_SECRET_KEY
        sync: false
      - key: STRIPE_WEBHOOK_SECRET
        sync: false
      - key: STRIPE_PRO_PRICE_ID
        sync: false
      - key: STRIPE_BUSINESS_PRICE_ID
        sync: false
      - key: RESEND_API_KEY
        sync: false
      - key: EMAIL_FROM_ADDRESS
        sync: false
      - key: EMAIL_FROM_NAME
        sync: false
      - key: APP_URL
        sync: false
      - key: API_URL
        sync: false

  - type: web
    name: acme-frontend
    env: static
    buildCommand: cd frontend && npm install && npm run build
    staticPublishPath: ./frontend/dist
    routes:
      - type: rewrite
        source: /*
        destination: /index.html
    envVars:
      - key: VITE_API_URL
        sync: false

  - type: redis
    name: acme-redis
    plan: starter
    maxmemoryPolicy: allkeys-lru

databases:
  - name: acme-db
    plan: starter
    databaseName: acme
    user: acme
```

Variables marked `sync: false` must be entered manually in the Render Dashboard after the Blueprint is deployed.

## Deploying

<Steps>
  <Step title="Push render.yaml to your repository">
    Commit `render.yaml` to the root of your repository and push to GitHub.
  </Step>

  <Step title="Create a Render account and Blueprint">
    1. Sign up at [render.com](https://render.com)
    2. Click **New** → **Blueprint**
    3. Connect your GitHub account and select your repository
    4. Render detects `render.yaml` and shows a preview of all services to be created
    5. Click **Apply**
  </Step>

  <Step title="Fill in manual environment variables">
    After the Blueprint deploys, go to the `acme-api` service:

    1. **Environment** tab → fill in all `sync: false` variables:
       * JWT keys (generate new ones — see [JWT Key Generation](/configuration/jwt-keys))
       * Stripe live keys
       * Resend API key and email address
       * `APP_URL` and `API_URL` (use the Render-provided URLs initially)
    2. Do the same for the `acme-frontend` service:
       * `VITE_API_URL` = the URL of your `acme-api` service
    3. Click **Save Changes** — Render triggers a new deploy
  </Step>

  <Step title="Run migrations">
    From the Render Dashboard:

    1. Click on the `acme-api` service
    2. Click **Shell** (top right)
    3. In the shell:

    ```bash theme={null}
    dotnet ef database update \
      --project src/Acme.Infrastructure \
      --startup-project src/Acme.Api
    ```
  </Step>

  <Step title="Run the database seeder">
    In the same shell:

    ```bash theme={null}
    dotnet run --project src/Acme.Api -- --seed-only
    ```
  </Step>

  <Step title="Add a custom domain (optional)">
    1. Go to your `acme-api` service → **Settings** → **Custom Domains**
    2. Add `api.yourdomain.com`
    3. Add the CNAME record Render provides to your DNS
    4. Repeat for the frontend service at `yourdomain.com`
    5. Update `APP_URL`, `API_URL`, and `VITE_API_URL` environment variables with the new domain names
  </Step>

  <Step title="Register the Stripe webhook">
    Stripe Dashboard → **Developers → Webhooks** → **Add endpoint**

    * URL: `https://api.yourdomain.com/api/v1/webhooks/stripe`
    * Events: checkout.session.completed, customer.subscription.updated, customer.subscription.deleted, invoice.payment\_failed, invoice.payment\_succeeded
    * Copy signing secret → update `STRIPE_WEBHOOK_SECRET` in Render
  </Step>
</Steps>

<Note>
  Render's free tier spins down services after 15 minutes of inactivity and takes \~30 seconds to wake up on the next request. This is noticeable for evaluation but not suitable for a real application. Upgrade to the Starter plan (\$7/mo) to keep services always running.
</Note>
