|
| 1 | +# Buildpack, Procfile, and Build Command Mapping |
| 2 | + |
| 3 | +## Buildpack → Render Runtime + Build Command |
| 4 | + |
| 5 | +Render needs explicit `buildCommand` and `startCommand`. Determine the runtime from local project files (dependency files, Procfile), or from Heroku buildpack URLs if available via MCP or `app.json`. Use these defaults, then refine based on the app's actual Procfile and package config. |
| 6 | + |
| 7 | +### Node.js |
| 8 | + |
| 9 | +| Buildpack | `heroku/nodejs` or `heroku-community/nodejs` | |
| 10 | +|-----------|----------------------------------------------| |
| 11 | +| Render runtime | `node` | |
| 12 | +| Default build command | `npm install && npm run build` | |
| 13 | +| Fallback build (no build script) | `npm install` | |
| 14 | +| Detection | Check `package.json` for `build` script. If missing, use fallback. | |
| 15 | + |
| 16 | +**Common variations:** |
| 17 | +- Yarn: `yarn install && yarn build` (detect via `yarn.lock` presence) |
| 18 | +- pnpm: `pnpm install && pnpm run build` (detect via `pnpm-lock.yaml`) |
| 19 | +- TypeScript without build script: `npm install && npx tsc` |
| 20 | +- Next.js: `npm install && npm run build` (start: `npm start` or `next start`) |
| 21 | +- Vite/CRA (static): use `create_static_site` instead, publishPath `dist` or `build` |
| 22 | + |
| 23 | +### Python |
| 24 | + |
| 25 | +| Buildpack | `heroku/python` | |
| 26 | +|-----------|-----------------| |
| 27 | +| Render runtime | `python` | |
| 28 | +| Default build command | `pip install -r requirements.txt` | |
| 29 | +| Django build | `pip install -r requirements.txt && python manage.py collectstatic --noinput` | |
| 30 | +| Detection | Check for `requirements.txt`, `Pipfile`, or `pyproject.toml` | |
| 31 | + |
| 32 | +**Common variations:** |
| 33 | +- Pipenv: `pip install pipenv && pipenv install` |
| 34 | +- Poetry: `pip install poetry && poetry install` |
| 35 | +- Django: look for `collectstatic` in Procfile or `django` in requirements |
| 36 | +- FastAPI/Flask: straightforward `pip install -r requirements.txt` |
| 37 | + |
| 38 | +### Ruby |
| 39 | + |
| 40 | +| Buildpack | `heroku/ruby` | |
| 41 | +|-----------|---------------| |
| 42 | +| Render runtime | `ruby` | |
| 43 | +| Default build command | `bundle install` | |
| 44 | +| Rails build | `bundle install && bundle exec rake assets:precompile` | |
| 45 | +| Detection | Check for `Gemfile`. If `rails` gem present, use Rails build. | |
| 46 | + |
| 47 | +### Go |
| 48 | + |
| 49 | +| Buildpack | `heroku/go` | |
| 50 | +|-----------|-------------| |
| 51 | +| Render runtime | `go` | |
| 52 | +| Default build command | `go build -o app .` | |
| 53 | +| Detection | Check for `go.mod` | |
| 54 | + |
| 55 | +### Rust |
| 56 | + |
| 57 | +| Buildpack | `emk/rust` or custom | |
| 58 | +|-----------|----------------------| |
| 59 | +| Render runtime | `rust` | |
| 60 | +| Default build command | `cargo build --release` | |
| 61 | +| Start command | `./target/release/<binary-name>` | |
| 62 | + |
| 63 | +### Java / Scala / PHP / Multi-buildpack |
| 64 | + |
| 65 | +| Buildpack | Any not listed above | |
| 66 | +|-----------|----------------------| |
| 67 | +| Render runtime | `docker` | |
| 68 | +| Action | Tell user they need a Dockerfile. Offer to generate one. | |
| 69 | + |
| 70 | +## Procfile Parsing |
| 71 | + |
| 72 | +Heroku Procfiles define process types. Extract these to map to Render services. |
| 73 | + |
| 74 | +### Format |
| 75 | +``` |
| 76 | +<process-type>: <command> |
| 77 | +``` |
| 78 | + |
| 79 | +### Mapping Rules |
| 80 | + |
| 81 | +| Procfile entry | Render service type | Render MCP tool | `startCommand` | |
| 82 | +|---------------|--------------------|-----------------|-----------------| |
| 83 | +| `web: <cmd>` | Web Service | `create_web_service` | `<cmd>` | |
| 84 | +| `worker: <cmd>` | Background Worker | Blueprint `type: worker` | `<cmd>` (MCP cannot create workers) | |
| 85 | +| `clock: <cmd>` | Cron Job | `create_cron_job` | `<cmd>` (ask user for schedule) | |
| 86 | +| `release: <cmd>` | Pre-deploy command | N/A | Add as build command suffix | |
| 87 | + |
| 88 | +### Common Procfile Patterns |
| 89 | + |
| 90 | +**Node.js:** |
| 91 | +``` |
| 92 | +web: npm start |
| 93 | +web: node server.js |
| 94 | +web: next start -p $PORT |
| 95 | +worker: node worker.js |
| 96 | +``` |
| 97 | + |
| 98 | +**Python:** |
| 99 | +``` |
| 100 | +web: gunicorn app:app |
| 101 | +web: gunicorn myproject.wsgi --log-file - |
| 102 | +web: uvicorn main:app --host 0.0.0.0 --port $PORT |
| 103 | +worker: celery -A myproject worker |
| 104 | +clock: celery -A myproject beat |
| 105 | +release: python manage.py migrate |
| 106 | +``` |
| 107 | + |
| 108 | +**Ruby:** |
| 109 | +``` |
| 110 | +web: bundle exec puma -C config/puma.rb |
| 111 | +worker: bundle exec sidekiq |
| 112 | +release: bundle exec rake db:migrate |
| 113 | +``` |
| 114 | + |
| 115 | +### Runtime Version Handling |
| 116 | + |
| 117 | +Do not assume or fabricate specific runtime versions for Render. Instead, carry over the version the Heroku app already uses: |
| 118 | + |
| 119 | +| Heroku file | What it contains | Render equivalent | |
| 120 | +|---|---|---| |
| 121 | +| `runtime.txt` | `python-3.11.6` | Set `PYTHON_VERSION=3.11.6` env var | |
| 122 | +| `runtime.txt` | `ruby-3.2.2` | Render auto-detects from `ruby-3.2.2` in `Gemfile` | |
| 123 | +| `.node-version` or `engines` in `package.json` | `18.17.0` | Set `NODE_VERSION=18.17.0` env var | |
| 124 | +| `.go-version` or `go.mod` | `1.21` | Render auto-detects from `go.mod` | |
| 125 | + |
| 126 | +**Rules:** |
| 127 | +- If the Heroku app pins a version via `runtime.txt` or similar, include the equivalent env var in the Blueprint |
| 128 | +- If no version is pinned, do not specify one — Render uses its own defaults |
| 129 | +- **Never state what Render's default version is** — it changes over time and any claim may be wrong |
| 130 | + |
| 131 | +### PORT Handling |
| 132 | + |
| 133 | +Heroku sets `$PORT` dynamically. Render also sets `PORT` (default 10000). Most Procfile commands work as-is. If the command hardcodes a port, it needs updating. |
| 134 | + |
| 135 | +- `--port $PORT` → works on both platforms |
| 136 | +- `--port 5000` → change to `--port $PORT` or `--port 10000` |
| 137 | +- Render auto-detects the port for common frameworks |
| 138 | + |
| 139 | +### Release Phase |
| 140 | + |
| 141 | +Heroku's `release:` process type runs before each deploy. Render has no direct equivalent. Options: |
| 142 | +1. Append to build command: `pip install -r requirements.txt && python manage.py migrate` |
| 143 | +2. Use Render's pre-deploy command feature (if available for the service type) |
| 144 | +3. Flag for the user to handle manually |
| 145 | + |
| 146 | +## Static Site Detection |
| 147 | + |
| 148 | +If the Heroku app is a static site (React, Vue, Gatsby, etc.), use `create_static_site` instead of `create_web_service`. |
| 149 | + |
| 150 | +**Indicators:** |
| 151 | +- Buildpack is `heroku-community/static` or `heroku/heroku-buildpack-static` |
| 152 | +- Procfile is missing or only has `web: bin/boot` (static buildpack default) |
| 153 | +- `package.json` has framework deps: `react-scripts`, `vue`, `gatsby`, `vite`, `@angular/cli` |
| 154 | +- `static.json` file present in repo root |
| 155 | + |
| 156 | +**Static site config:** |
| 157 | +| Framework | Build command | Publish path | |
| 158 | +|-----------|--------------|--------------| |
| 159 | +| Create React App | `npm install && npm run build` | `build` | |
| 160 | +| Vite (React/Vue) | `npm install && npm run build` | `dist` | |
| 161 | +| Gatsby | `npm install && gatsby build` | `public` | |
| 162 | +| Next.js (static export) | `npm install && next build` | `out` | |
| 163 | +| Angular | `npm install && ng build` | `dist/<project-name>` | |
| 164 | +| Hugo | `hugo` | `public` | |
0 commit comments