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

# Add a "Deploy to InstaPods" button

> Let anyone deploy your open-source project to a real server in one click. Add the badge, test it, and verify the deploy end to end.

If you maintain an open-source web project, a **Deploy to InstaPods** button lets anyone run it on a real Linux server -- with HTTPS and auto-deploy on every push -- in one click. No Dockerfile, no CI, no setup.

[![Deploy to InstaPods](https://instapods.com/deploy-button.svg)](https://app.instapods.com/dashboard/pods/create?repo=https://github.com/OWNER/REPO)

It works for **Node.js, PHP, Python, and static** projects. When someone clicks the button, InstaPods reads your repo's root files to detect the stack, creates a pod, clones the repo, installs dependencies, builds, and starts your app behind HTTPS.

## Add the button

The badge is a Markdown image wrapped in a link. Paste this into your `README.md` and replace `OWNER/REPO` with your repository:

```markdown theme={null}
[![Deploy to InstaPods](https://instapods.com/deploy-button.svg)](https://app.instapods.com/dashboard/pods/create?repo=https://github.com/OWNER/REPO)
```

<Tip>
  Don't want to hand-edit it? Open the builder at [instapods.com/deploy/github](https://instapods.com/deploy/github), paste your repo URL, and copy the generated snippet.
</Tip>

### Link options

The button is just a link to the create page with query parameters:

| Parameter | Required | Description                                                      |
| --------- | -------- | ---------------------------------------------------------------- |
| `repo`    | Yes      | Your GitHub repository URL, e.g. `https://github.com/OWNER/REPO` |
| `branch`  | No       | Deploy a specific branch (defaults to the repo's default branch) |

```markdown theme={null}
<!-- deploy a specific branch -->
[![Deploy to InstaPods](https://instapods.com/deploy-button.svg)](https://app.instapods.com/dashboard/pods/create?repo=https://github.com/OWNER/REPO&branch=production)
```

GitHub URLs don't need URL-encoding here -- they contain no `&`, `?`, or `#`.

## Test it

<Steps>
  <Step title="Open the deploy link">
    Click your badge (or open the URL directly). You land in the create wizard with **From GitHub** preselected and your repo pre-filled. If you're not signed in, you'll sign in or sign up first, then continue.
  </Step>

  <Step title="Check detection">
    The wizard inspects your repo and shows the detected stack, e.g. **Detected nodejs (package.json)**, plus a suggested plan. If it can't detect a supported stack, pick a preset from the dropdown to continue.
  </Step>

  <Step title="Deploy">
    Confirm the plan and pod name, then deploy. You're taken to the pod's **Git** tab, where the first build streams live.
  </Step>
</Steps>

Prefer the terminal? The [CLI](/cli/deploy) does the same thing:

```bash theme={null}
instapods deploy --repo https://github.com/OWNER/REPO
# detects the stack, creates the pod, and follows the first build to completion
```

## Verify the deploy end to end

Use this checklist to confirm everything works -- it's the exact path the button triggers.

<Steps>
  <Step title="Stack detected correctly">
    On the create wizard (or in the CLI output) confirm the detected preset matches your project: `nodejs`, `php`, `python`, or `static`. If it's wrong, your manifest may not be at the repo root -- see [Make detection reliable](#make-detection-reliable).
  </Step>

  <Step title="Pod reaches Running">
    The pod goes `creating` -> `running` in about 10-30 seconds. The Git tab opens automatically and the first deployment appears.
  </Step>

  <Step title="Build log shows clone -> install -> build -> start">
    Open the deployment on the Git tab and read the build log. A successful Python deploy ends like this:

    ```text theme={null}
    === Cloning/pulling repository ===
    Cloning into '/home/instapod/app'...

    === Installing dependencies ===
    Successfully installed fastapi-0.x uvicorn-0.x ...

    === Restarting services ===
    Set start command (AI): source ~/app/venv/bin/activate && uvicorn app:app --host 0.0.0.0 --port 8000

    === Health check ===
    Service app: active

    === Deploy successful ===
    ```

    Node shows `npm install` + `npm run build`; PHP shows `composer install`; static skips install. If the build fails, the error and the log tail are right there -- fix it in your repo and push, or hit **Redeploy**.
  </Step>

  <Step title="App serves over HTTPS">
    Visit the pod's URL (shown on the dashboard), e.g. `https://your-app.nbg1-1.instapods.app`, or check from a terminal:

    ```bash theme={null}
    curl -I https://your-app.nbg1-1.instapods.app
    # HTTP/2 200
    ```
  </Step>

  <Step title="Push redeploys automatically">
    Push a commit to the tracked branch. A new deployment starts on its own (auto-deploy is on by default) and appears in the Git tab with its own build log.
  </Step>

  <Step title="Rollback works">
    From the Git tab's deployment history, roll back to any previous commit in one click (or `instapods git rollback <pod>`). The previous build is restored.
  </Step>
</Steps>

## Supported stacks

| Stack       | Detected by                                                      | What InstaPods runs                                                                 |
| ----------- | ---------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| **Node.js** | `package.json` (or `tsconfig.json`, `next.config.*`, a lockfile) | `npm install`, `npm run build` if a `build` script exists, then your `start` script |
| **PHP**     | `composer.json` (or `*.php`, `artisan`)                          | `composer install`, served by nginx + PHP-FPM 8.3 (Laravel `public/` detected)      |
| **Python**  | `requirements.txt` / `pyproject.toml`                            | `pip install` in a virtualenv; gunicorn/uvicorn auto-detected for WSGI/ASGI apps    |
| **Static**  | `index.html`                                                     | Served straight from nginx                                                          |

<Note>
  Dockerfile-based projects and other languages (Go, Rust, Java, Ruby) aren't supported yet -- the button currently builds Node, PHP, Python, and static projects.
</Note>

## Make detection reliable

A few things make the one-click experience smooth for your users:

* **Keep your manifest at the repo root.** Detection reads root-level files only -- `package.json`, `composer.json`, `requirements.txt`/`pyproject.toml`, or `index.html`.
* **Provide a start command.** Node: a `start` (or `server`/`serve`) script in `package.json`. Python: a gunicorn/uvicorn entry such as `app:app`.
* **Listen on the right host and port.** InstaPods sets `HOST=0.0.0.0` and `PORT` (3000 for Node, 8000 for Python). Read those env vars, or bind to that port directly, so the app is reachable.
* **Commit a lockfile** (`package-lock.json`, `composer.lock`, etc.) for reproducible installs.

## Troubleshooting

<AccordionGroup>
  <Accordion title="The build failed">
    Open the failed deployment on the pod's **Git** tab -- the error message and the tail of the build log are shown. Common causes: a dependency that needs a system package, a missing build/start script, or the app not listening on the expected port. Fix it in your repo and push (or hit **Redeploy**).
  </Accordion>

  <Accordion title="It detected the wrong stack (or none)">
    Pick a preset in the wizard before deploying, or pass `--preset` to the CLI. This usually means the manifest isn't at the repo root.
  </Accordion>

  <Accordion title="It's a private repository">
    Connect your GitHub account in the dashboard first (Settings -> GitHub). Once the InstaPods GitHub App can see the repo, the button deploys it like any other. The public button targets public repos.
  </Accordion>

  <Accordion title="The app deploys but the URL doesn't respond">
    Make sure your app listens on `0.0.0.0` and the port InstaPods sets (`PORT` env var: 3000 for Node, 8000 for Python). Apps that hardcode `localhost` or a different port won't be reachable through the proxy.
  </Accordion>
</AccordionGroup>

## Maintaining a popular project?

If your project gets real traffic, [get in touch](https://instapods.com/support) -- we partner with open-source maintainers (an "Official Cloud Hosting Partner" listing and revenue share) and are happy to help tune the deploy experience for your stack.
