# Manifest File — .rep.yaml Configuration Reference > Declare environment variables, types, defaults, and validation rules in .rep.yaml. Generate TypeScript types and validate config at gateway startup. Source: https://rep-protocol.dev/guides/manifest/ The `.rep.yaml` manifest is optional but powerful. It enables: - **Startup validation** — fail fast if a required variable is missing - **Type constraints** — enforce `url`, `number`, `enum`, `csv` shapes - **TypeScript types** — `rep typegen` generates typed `get()` / `getSecure()` overloads - **Documentation** — a single source of truth for every variable the app uses ## Example manifest ```yaml version: "0.1.0" variables: API_URL: tier: public type: url required: true description: "Base URL for the backend REST API" example: "https://api.example.com" FEATURE_FLAGS: tier: public type: csv required: false default: "" description: "Comma-separated feature flags" example: "dark-mode,new-checkout" ENV_NAME: tier: public type: enum required: true values: ["development", "staging", "production"] description: "Current deployment environment" ANALYTICS_WRITE_KEY: tier: sensitive type: string required: true description: "Analytics service write key" OAUTH_CLIENT_ID: tier: sensitive type: string required: true pattern: "^[a-zA-Z0-9]{20,}$" description: "OAuth 2.0 client identifier" UPSTREAM_AUTH_TOKEN: tier: server type: string required: false description: "Bearer token for upstream proxying" settings: strict_guardrails: true hot_reload: true session_key_ttl: "30s" session_key_max_rate: 10 allowed_origins: - "https://app.example.com" ``` ## Variable fields | Field | Type | Required | Description | |---|---|---|---| | `tier` | `public` / `sensitive` / `server` | Yes | Security classification | | `type` | see below | Yes | Value type constraint | | `required` | boolean | No | Whether the variable must be present at startup | | `default` | string | No | Value the gateway injects when the variable is unset. See [Defaults](#defaults) | | `description` | string | No | Human-readable description | | `example` | string | No | Example value | | `pattern` | string | No | Regex pattern the value must match | | `values` | string[] | No | Allowed values (for `enum` type) | | `deprecated` | boolean | No | Mark as deprecated | | `deprecated_message` | string | No | Migration guidance for deprecated vars | ## Supported types | Type | Validation | |---|---| | `string` | Any string value | | `url` | Must be a valid URL | | `number` | Must parse as a number | | `boolean` | Must be `true`, `false`, `1`, or `0` | | `csv` | Comma-separated values. [Guardrails](/concepts/variable-classification/#automatic-secret-detection-guardrails) scan each element separately. See [Feature Flags](/guides/feature-flags/) | | `json` | Must be valid JSON | | `enum` | Must match one of the `values` array entries | ## Defaults When a variable declares `default`, isn't `required`, and isn't set in any tier, the gateway injects the default as though it had been set. It goes into the declared `tier`, so a `public` default is in the payload and `rep.get()` returns it: ```yaml FEATURE_FLAGS: tier: public type: csv default: "" ``` With `REP_PUBLIC_FEATURE_FLAGS` unset, `rep.get('FEATURE_FLAGS')` returns `""`, not `undefined`. - An empty string is a default: `default: ""` injects `""`. - A value in the environment always wins, even an empty one. - A default is validated against `type` and `pattern` like a set value, even while the environment overrides it. A default that doesn't match is a manifest error and the gateway refuses to start. - A `public` default is scanned by the [guardrails](/concepts/variable-classification/#automatic-secret-detection-guardrails). - `required: true` wins. A required variable that is unset fails startup even if it declares a default. - Hot reload re-applies defaults. Removing a variable from the environment reverts it to its default. > **Upgrading to gateway 0.1.8** > > Gateways before 0.1.8 ignored defaults. After upgrading, an invalid default (for example `type: url` with `default: ""`) stops startup. See the [gateway upgrade notes](https://github.com/ruachtech/rep/blob/main/gateway/README.md#upgrading). Each injected default is logged as `rep.manifest.default_applied` with its name and tier (never its value). The startup summary counts defaults in `public_vars`, `sensitive_vars` and `server_vars` and totals them in `defaulted_vars`. ## Settings | Setting | Type | Default | Description | |---|---|---|---| | `strict_guardrails` | boolean | `false` | Exit on guardrail warnings | | `hot_reload` | boolean | `false` | Enable hot reload SSE | | `hot_reload_mode` | string | `signal` | `file_watch`, `signal`, or `poll` | | `hot_reload_poll_interval` | string | `30s` | Poll interval (Go duration) | | `session_key_ttl` | string | `30s` | Session key expiry | | `session_key_max_rate` | number | `10` | Max session key requests per minute per IP | | `allowed_origins` | string[] | `[]` | CORS allowed origins for session key endpoint | ## Validating ```bash rep validate --manifest .rep.yaml ``` Output: ``` ✓ Manifest is valid Version: 0.1.0 Variables: 6 total - PUBLIC: 3 - SENSITIVE: 2 - SERVER: 1 Settings configured: 4 ``` Use in CI to catch configuration errors before deployment: ```yaml - name: Validate REP manifest run: npx @rep-protocol/cli validate --manifest .rep.yaml ``` ## Type generation Generate TypeScript type definitions from your manifest: ```bash rep typegen --manifest .rep.yaml --output src/rep.d.ts ``` This creates typed overloads for `get()` and `getSecure()`: ```typescript declare module "@rep-protocol/sdk" { export interface REP { get(key: "API_URL" | "FEATURE_FLAGS" | "ENV_NAME"): string | undefined; getSecure(key: "ANALYTICS_WRITE_KEY" | "OAUTH_CLIENT_ID"): Promise; } } ``` > **Tip** > > Run `rep typegen` as part of your build script or as a pre-commit hook to keep types in sync with the manifest. For the full schema reference, see [Manifest Schema Reference](/reference/manifest-schema/).