# Building & Deploying

## The deployment workflow

1. **Build** — Compile your code

    ```bash
    npm run build
    ```

    This runs two build steps:
    - Client (Vite) to static assets in `dist/client/`
    - Server Worker bundle (esbuild) to `dist/server/`

    Build output includes size reporting so you can monitor bundle sizes.

2. **Sync** — Update app metadata

    ```bash
    bkper app sync
    ```

    Syncs your `bkper.yaml` configuration to Bkper — name, description, menu URLs, webhook URLs, access control, and branding. Run this whenever you change app settings.

3. **Deploy** — Upload code to the platform

    ```bash
    bkper app deploy
    ```

    Deploys your pre-built code from `dist/` to the Bkper Platform. Your app is live at `https://{appId}.bkper.app`.

The typical workflow combines all three:

```bash
npm run build && bkper app sync && bkper app deploy
```

### Production

The default deployment target. Your app runs at `https://{appId}.bkper.app`.

```bash
bkper app deploy
```

Production serves:

```txt
Client:       https://{appId}.bkper.app
API routes:   https://{appId}.bkper.app/api/*
OpenAPI spec: https://{appId}.bkper.app/openapi.json
Events:       https://{appId}.bkper.app/events
```

### Preview

Deploy to a separate preview environment for testing before production:

```bash
bkper app deploy --preview
```

Preview URLs use a dash suffix: `https://{appId}-preview.bkper.app`. For example, an app with `id: my-app` deploys to `https://my-app-preview.bkper.app`.

Preview serves:

```txt
Client:       https://{appId}-preview.bkper.app
API routes:   https://{appId}-preview.bkper.app/api/*
OpenAPI spec: https://{appId}-preview.bkper.app/openapi.json
Events:       https://{appId}-preview.bkper.app/events
```

Preview has independent secrets and KV storage from production.

There is one app deployment per environment. `/events` is handled by the same Worker as the client assets and `/api/*` routes.

## Secrets management

Secrets are environment variables stored securely on the platform. Declare them in `bkper.yaml`:

```yaml
deployment:
    secrets:
        - EXTERNAL_SERVICE_TOKEN
```

### Setting secrets

```bash
# Set for production
bkper app secrets put EXTERNAL_SERVICE_TOKEN

# Set for preview
bkper app secrets put EXTERNAL_SERVICE_TOKEN --preview
```

You'll be prompted to enter the value.

### Listing and deleting

```bash
# List all secrets
bkper app secrets list

# Delete a secret
bkper app secrets delete EXTERNAL_SERVICE_TOKEN
```

### Accessing in code

Secrets are available as `c.env.SECRET_NAME` in your Hono handlers:

```ts
app.get('/api/data', async c => {
    const token = c.env.EXTERNAL_SERVICE_TOKEN;
    // use token
});
```

During local development, use the `.dev.vars` file instead. See [Development Experience](https://bkper.com/docs/build/apps/development.md#local-secrets).

### KV storage

Declare KV in `bkper.yaml`:

```yaml
deployment:
    services:
        - KV
```

The platform provisions a KV namespace for your app. Access it via `c.env.KV`:

```ts
await c.env.KV.put('key', 'value', { expirationTtl: 3600 });
const value = await c.env.KV.get('key');
```

KV storage is separate between production and preview environments.

## Deployment status

Check the current state of your deployment:

```bash
bkper app status
```

## Installing on books

After deploying, install the app on specific books to activate it:

```bash
# Install on a book
bkper app install <appId> -b <bookId>

# Uninstall from a book
bkper app uninstall <appId> -b <bookId>
```

Once installed, the app's [event handlers](https://bkper.com/docs/build/apps/event-handlers.md) receive events from that book at `/events`, and the app's [context menu](https://bkper.com/docs/build/apps/context-menu.md) appears in the book's UI.
