Skip to content

Quick Start — Runtime Environment Variables in 5 Minutes

The .rep.yaml manifest is entirely optional. The gateway works with just environment variables — the naming convention is the configuration.

  1. Rename your environment variables

    Add the REP_PUBLIC_, REP_SENSITIVE_, or REP_SERVER_ prefix to classify each variable:

    Terminal window
    # Before (Vite) → After (REP)
    VITE_API_URL → REP_PUBLIC_API_URL
    VITE_FEATURE_FLAGS → REP_PUBLIC_FEATURE_FLAGS
    # Before (CRA) → After (REP)
    REACT_APP_API_URL → REP_PUBLIC_API_URL
    # Should be encrypted in the browser
    REACT_APP_ANALYTICS_KEY → REP_SENSITIVE_ANALYTICS_KEY
    # Should never reach the browser
    DB_PASSWORD → REP_SERVER_DB_PASSWORD
  2. Install the SDK and update your code

    Terminal window
    npm install @rep-protocol/sdk

    Replace your import.meta.env.* / process.env.* reads:

    import { rep } from '@rep-protocol/sdk';
    // Was: import.meta.env.VITE_API_URL
    const apiUrl = rep.get('API_URL');
    // With a default value for local development
    const apiUrl = rep.get('API_URL', 'http://localhost:3001');
    // Sensitive variable — encrypted, decrypted on demand
    const key = await rep.getSecure('ANALYTICS_KEY');

    rep.get() is synchronous — the SDK reads the payload from the DOM on import, before your first component renders. No loading state needed.

  3. Build your app (nothing changes)

    Terminal window
    npm run build

    The output is now environment-agnostic. The same dist/ folder goes to every environment.

  4. Run the gateway

    Terminal window
    REP_PUBLIC_API_URL=https://api.example.com \
    REP_PUBLIC_FEATURE_FLAGS=dark-mode,new-checkout \
    REP_SENSITIVE_ANALYTICS_KEY=ak_live_abc123 \
    ./rep-gateway --mode embedded --static-dir ./dist

    Open http://localhost:8080 — the gateway injected your variables into every HTML response.

Stop the gateway. Restart with different values. Same dist/ folder, different runtime config:

Terminal window
REP_PUBLIC_API_URL=https://api.prod.example.com \
REP_PUBLIC_FEATURE_FLAGS=dark-mode \
REP_SENSITIVE_ANALYTICS_KEY=ak_live_prod_xyz \
./rep-gateway --mode embedded --static-dir ./dist

No rebuild. No new container image. This is the core proposition.

If you already have nginx, Caddy, or another static file server, run the gateway in front of it instead:

Terminal window
REP_PUBLIC_API_URL=https://api.example.com \
./rep-gateway --mode proxy --upstream localhost:80

The gateway intercepts text/html responses, injects the <script> tag, and passes everything else through unmodified.

For local development, point the gateway at a .env.local file and let it watch for changes automatically — no signals, no restarts:

.env.local
REP_PUBLIC_API_URL=http://localhost:3001
REP_PUBLIC_FEATURE_FLAGS=dark-mode
REP_SENSITIVE_ANALYTICS_KEY=ak_dev_abc123
Terminal window
./rep-gateway --mode embedded --static-dir ./dist \
--hot-reload \
--hot-reload-mode=file_watch \
--env-file=.env.local \
--watch-path=.env.local

Edit .env.local and save — the gateway picks up the changes immediately, re-encrypts sensitive vars with a fresh ephemeral key, and pushes a reload event over /rep/changes (SSE). Components using rep.onChange() re-render automatically without a browser refresh.

REP works the same way with a single index.html and no bundler — see the Simple HTML example for the SDK loaded straight from a CDN.

Running vite dev or next dev without the gateway? Install the Vite or Next.js plugin to get the same injected payload during development — no second terminal, no gateway binary needed locally.