Simple HTML — No Build Step
A single HTML file using the REP SDK via esm.sh, served by the gateway in embedded mode. No build step, no bundler, no framework.
Source code at examples/simple-html/.
When to use this pattern
Section titled “When to use this pattern”- Static marketing pages or single-file dashboards
- Quick prototyping without a build pipeline
- Demonstrating REP concepts with minimal infrastructure
- Environments where adding a Node.js build step is impractical
File structure
Section titled “File structure”Directoryexamples/simple-html/
- index.html Single HTML file — the entire app
- Dockerfile Two-stage: gateway download → FROM scratch
- .rep.yaml Optional manifest for validate/typegen
- .env.example Template environment variables
How it works
Section titled “How it works”The REP gateway runs in embedded mode, serving index.html directly. When a browser requests the page, the gateway injects the __rep__ payload before the response is sent:
Browser → REP Gateway :8080 (embedded mode) ↓ injects <script id="__rep__" type="application/json">…</script> ↓ serves index.htmlThe HTML file imports the SDK as an ES module from esm.sh — no npm install, no bundler:
<script type="module">
// Public vars — synchronous, available immediately const apiUrl = rep.get('API_URL', 'http://localhost:3001'); const envName = rep.get('ENV_NAME', 'development');
// Sensitive var — AES-256-GCM encrypted, decrypted on demand const analyticsKey = await rep.getSecure('ANALYTICS_KEY');
// Hot reload — react to config changes pushed via SSE rep.onChange('FEATURE_FLAGS', (next) => { document.getElementById('features').textContent = next || '(none)'; });</script>Dockerfile
Section titled “Dockerfile”A two-stage build. No app build step is needed — the HTML file is copied as-is:
FROM alpine:3.21 AS gatewayARG GATEWAY_VERSION=0.1.3RUN apk add --no-cache curl ca-certificates && \ curl -fsSL "…/rep-gateway_${GATEWAY_VERSION}_linux_amd64.tar.gz" \ -o /tmp/gateway.tar.gz && \ tar -xzf /tmp/gateway.tar.gz -C /tmp && \ mv /tmp/rep-gateway /rep-gateway && \ chmod +x /rep-gateway
FROM scratchCOPY --from=gateway /rep-gateway /rep-gatewayCOPY index.html /static/index.htmlCOPY --from=gateway /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/USER 65534:65534EXPOSE 8080ENTRYPOINT ["/rep-gateway", "--mode", "embedded", "--static-dir", "/static"]The final image contains: gateway binary + one HTML file + CA certificates. Total size is approximately 6MB.
Running locally
Section titled “Running locally”Docker
Section titled “Docker”cd examples/simple-html
docker build -t rep-simple-html .
docker run --rm -p 8080:8080 \ -e REP_PUBLIC_APP_TITLE="My App" \ -e REP_PUBLIC_API_URL=https://api.example.com \ -e REP_PUBLIC_ENV_NAME=production \ -e REP_PUBLIC_FEATURE_FLAGS=dark-mode,beta \ -e REP_SENSITIVE_ANALYTICS_KEY=ak_live_abc123 \ rep-simple-htmlWithout Docker (CLI)
Section titled “Without Docker (CLI)”cd examples/simple-html
# Serve the HTML file locally with the gatewaynpx @rep-protocol/cli dev \ --mode embedded \ --static-dir . \ --env-file .env.localChanging config
Section titled “Changing config”No rebuild required. Stop, change env vars, restart:
# Production configdocker run --rm -p 8080:8080 \ -e REP_PUBLIC_API_URL=https://api.prod.example.com \ -e REP_PUBLIC_FEATURE_FLAGS=dark-mode \ rep-simple-html
# Staging config — same imagedocker run --rm -p 8080:8080 \ -e REP_PUBLIC_API_URL=https://api.staging.example.com \ -e REP_PUBLIC_FEATURE_FLAGS=dark-mode,beta,new-checkout \ rep-simple-htmlSame index.html. Same Docker image. Different runtime config.
Security note
Section titled “Security note”The esm.sh import call happens in the browser after the page loads. For production, consider pinning the SDK version and adding an import map or hosting the SDK on your own CDN to remove the esm.sh dependency. If you self-host the SDK and load it via <script type="module" src="...">, you can add an integrity attribute for Subresource Integrity (SRI) verification. Note that SRI works on <script src> / <link> tags, not on bare import statements inside a module.