> ## Documentation Index
> Fetch the complete documentation index at: https://nextjs-egg.nyxel.my.id/llms.txt
> Use this file to discover all available pages before exploring further.

# Startup Flow

> What happens inside the egg each time your server starts.

Every time your server starts, the egg runs `entrypoint.sh` in sequence. The exact steps depend on whether this is a first start, whether `GIT_URL` is set, and whether `AUTO_UPDATE` is enabled.

***

## First start (empty container, GIT\_URL set)

When the container has no `package.json` and `GIT_URL` is configured, the egg clones your repository from scratch before doing anything else.

<Steps>
  <Step title="Clone the repository">
    Because no `package.json` exists, the egg clears the container directory and clones your repository:

    ```bash theme={null}
    git clone --single-branch --branch $GIT_BRANCH $GIT_URL /home/container
    ```

    If `GIT_BRANCH` is empty, git uses the repository's default branch. If `USERNAME` and `ACCESS_TOKEN` are set, the egg injects them into the URL automatically — you never need to embed credentials in `GIT_URL` yourself.
  </Step>

  <Step title="Copy .env file (if present)">
    If `.env.pterodactyl` exists in `/home/container`, the egg copies it to `.env`:

    ```bash theme={null}
    cp /home/container/.env.pterodactyl /home/container/.env
    ```

    This is how you inject environment variables without exposing them in panel variables. Upload `.env.pterodactyl` via the File Manager before starting.
  </Step>

  <Step title="Detect or use the configured package manager">
    The egg reads the `PACKAGE_MANAGER` variable (default: `auto`). In `auto` mode it inspects your project for a lockfile:

    | Lockfile found   | Package manager used |
    | ---------------- | -------------------- |
    | `pnpm-lock.yaml` | pnpm                 |
    | `yarn.lock`      | yarn                 |
    | neither          | npm                  |

    If you set `PACKAGE_MANAGER` explicitly to `npm`, `pnpm`, or `yarn`, that value is used regardless of which lockfiles are present.

    If pnpm or yarn is not already installed in the container, the egg installs it globally via npm before continuing.
  </Step>

  <Step title="Install dependencies">
    Dependencies are installed using the detected or configured package manager:

    | Package manager                | Command                                                         |
    | ------------------------------ | --------------------------------------------------------------- |
    | npm (with `package-lock.json`) | `npm ci`                                                        |
    | npm (no lockfile)              | `npm install`                                                   |
    | pnpm                           | `pnpm install --frozen-lockfile` (falls back to `pnpm install`) |
    | yarn                           | `yarn install --frozen-lockfile` (falls back to `yarn install`) |
  </Step>

  <Step title="Build the application (production only)">
    If `NODE_RUN_ENV=production`, the egg builds your app before starting it:

    | Package manager | Build command    |
    | --------------- | ---------------- |
    | npm             | `npm run build`  |
    | pnpm            | `pnpm run build` |
    | yarn            | `yarn build`     |

    This step is skipped entirely when `NODE_RUN_ENV=development`.
  </Step>

  <Step title="Start Cloudflare Tunnel (if configured)">
    If `CLOUDFLARE_TOKEN` is set, the egg downloads `cloudflared` (if not already present) and starts the tunnel in the background before launching Next.js:

    ```bash theme={null}
    cloudflared tunnel --no-autoupdate run --token $CLOUDFLARE_TOKEN &
    ```

    If `CLOUDFLARE_TOKEN` is empty, this step is skipped.
  </Step>

  <Step title="Start Next.js">
    The egg starts Next.js in the foreground using the port assigned by the panel:

    ```bash theme={null}
    # Production
    npx next start -p $SERVER_PORT

    # Development
    npx next dev -p $SERVER_PORT
    ```

    The panel considers the server online once it detects one of these strings in stdout: `ready on`, `started server on`, `Local: http://`, `Compiled successfully`, `listening on`, or `▲ Next.js`.
  </Step>
</Steps>

<Note>
  The egg runs `npm run build` (or the equivalent pnpm/yarn command) on every start in production mode. This ensures your app always reflects the latest code.
</Note>

***

## Subsequent starts with AUTO\_UPDATE=1

When `AUTO_UPDATE=1` and a `.git` directory is present, the egg pulls the latest commits before reinstalling and rebuilding.

<Steps>
  <Step title="Pull latest changes">
    The egg resets any local changes and pulls from the remote:

    ```bash theme={null}
    git reset --hard
    git fetch origin
    git checkout $GIT_BRANCH
    git pull origin $GIT_BRANCH
    ```

    If `GIT_BRANCH` is empty, the egg runs `git pull` against the current tracking branch.
  </Step>

  <Step title="Copy .env file (if present)">
    Same as first start — if `.env.pterodactyl` exists, it is copied to `.env`.
  </Step>

  <Step title="Detect package manager">
    Same lockfile detection logic as on first start.
  </Step>

  <Step title="Install dependencies">
    Same install commands as on first start. Running this on every restart ensures any newly added packages from the latest commit are present.
  </Step>

  <Step title="Build the application (production only)">
    Same build step as on first start — `next build` runs every time in production mode.
  </Step>

  <Step title="Start Cloudflare Tunnel (if configured)">
    Same as first start — starts `cloudflared` in the background if `CLOUDFLARE_TOKEN` is set.
  </Step>

  <Step title="Start Next.js">
    Same as first start — `next start -p $SERVER_PORT` or `next dev -p $SERVER_PORT`.
  </Step>
</Steps>

***

## Subsequent starts with AUTO\_UPDATE=0

When `AUTO_UPDATE=0`, the egg skips all git operations and uses whatever code is already in the container.

<Steps>
  <Step title="Skip git pull">
    The egg detects that `AUTO_UPDATE` is not `1` and logs `AUTO_UPDATE disabled — skipping pull`. No git commands are run. The code currently on disk is used as-is.
  </Step>

  <Step title="Copy .env file (if present)">
    If `.env.pterodactyl` exists, it is still copied to `.env` on every start regardless of the `AUTO_UPDATE` setting.
  </Step>

  <Step title="Detect package manager">
    Same lockfile detection logic as on first start.
  </Step>

  <Step title="Install dependencies">
    Dependencies are still installed on every restart to account for any manual changes to `package.json`.
  </Step>

  <Step title="Build the application (production only)">
    The build still runs on every restart in production mode, even without a git pull.
  </Step>

  <Step title="Start Cloudflare Tunnel (if configured)">
    Same as first start — starts `cloudflared` in the background if `CLOUDFLARE_TOKEN` is set.
  </Step>

  <Step title="Start Next.js">
    Same as first start — `next start -p $SERVER_PORT` or `next dev -p $SERVER_PORT`.
  </Step>
</Steps>

***

## GIT\_URL is empty

If you leave `GIT_URL` blank, the egg skips all git operations entirely and expects you to have uploaded your project files manually.

* All git steps (clone, fetch, pull) are skipped.
* The egg checks whether `/home/container/package.json` exists. If it does not, the egg exits immediately with an error:
  ```
  [EGG] ERROR: No package.json found and GIT_URL is empty.
  [EGG] Please upload your project files via File Manager or set GIT_URL.
  ```
  You must upload your project files — including `package.json` — via the panel's **File Manager** before restarting.
* If `package.json` is found, the egg continues with the `.env` copy, dependency install, build (if production), and Next.js start steps as normal.
