diff --git a/CLAUDE.md b/CLAUDE.md index 03e5805..8bbaf12 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -225,7 +225,7 @@ Full threat analysis in `spec/SECURITY-MODEL.md`. | Decision | Rationale | |---|---| -| **Go for the gateway** | Static compilation (CGO_ENABLED=0), zero runtime deps, ~3MB binary, `FROM scratch` compatible. No Node.js or bash needed in prod. | +| **Go for the gateway** | Static compilation (CGO_ENABLED=0), zero runtime deps, ~7MB binary, `FROM scratch` compatible. No Node.js or bash needed in prod. | | **Zero external Go dependencies** | Minimises supply chain risk. Only stdlib + crypto. Manifest parsing uses a hand-rolled YAML subset parser (~250 lines) to maintain this constraint. | | **`pkg/payload` imports from `internal/`** | Valid Go — `internal/` rule only restricts imports from outside the parent directory tree. Both live under `gateway/`. | | **`inject.go` strips `Accept-Encoding`** | Upstreams always respond with identity encoding, avoiding decompress/recompress. Gzip fallback via `compress/gzip` (stdlib) for non-compliant upstreams. Brotli unsupported (no stdlib, zero-dep constraint) — logged and passed through uninjected. | diff --git a/README.md b/README.md index a3d7fc9..b157d76 100644 --- a/README.md +++ b/README.md @@ -140,7 +140,7 @@ WORKDIR /app COPY . . RUN npm ci && npm run build -# Add REP gateway — single binary, ~3MB +# Add REP gateway — single binary, ~6MB FROM nginx:alpine COPY --from=build /app/dist /usr/share/nginx/html COPY --from=ghcr.io/ruachtech/rep/gateway:latest /usr/local/bin/rep-gateway /usr/local/bin/rep-gateway diff --git a/cli/package.json b/cli/package.json index 4644494..e020876 100644 --- a/cli/package.json +++ b/cli/package.json @@ -37,7 +37,7 @@ "ajv": "^8.12.0", "js-yaml": "^4.1.0", "dotenv": "^16.4.0", - "glob": "^10.3.0" + "glob": "^13.0.6" }, "devDependencies": { "typescript": "^5.4.0", diff --git a/docs/.astro/content-modules.mjs b/docs/.astro/content-modules.mjs index 5708671..c6f42a3 100644 --- a/docs/.astro/content-modules.mjs +++ b/docs/.astro/content-modules.mjs @@ -1,44 +1,44 @@ export default new Map([ ["src/content/docs/concepts/how-it-works.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fconcepts%2Fhow-it-works.mdx&astroContentModuleFlag=true")], -["src/content/docs/quick-start.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fquick-start.mdx&astroContentModuleFlag=true")], ["src/content/docs/concepts/security-model.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fconcepts%2Fsecurity-model.mdx&astroContentModuleFlag=true")], -["src/content/docs/contributing.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fcontributing.mdx&astroContentModuleFlag=true")], +["src/content/docs/quick-start.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fquick-start.mdx&astroContentModuleFlag=true")], +["src/content/docs/concepts/hot-reload.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fconcepts%2Fhot-reload.mdx&astroContentModuleFlag=true")], ["src/content/docs/concepts/variable-classification.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fconcepts%2Fvariable-classification.mdx&astroContentModuleFlag=true")], ["src/content/docs/concepts/wire-format.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fconcepts%2Fwire-format.mdx&astroContentModuleFlag=true")], -["src/content/docs/deployment/ci-cd.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdeployment%2Fci-cd.mdx&astroContentModuleFlag=true")], +["src/content/docs/contributing.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fcontributing.mdx&astroContentModuleFlag=true")], ["src/content/docs/deployment/docker-compose.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdeployment%2Fdocker-compose.mdx&astroContentModuleFlag=true")], ["src/content/docs/index.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Findex.mdx&astroContentModuleFlag=true")], -["src/content/docs/concepts/hot-reload.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fconcepts%2Fhot-reload.mdx&astroContentModuleFlag=true")], -["src/content/docs/deployment/docker-embedded.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdeployment%2Fdocker-embedded.mdx&astroContentModuleFlag=true")], +["src/content/docs/deployment/ci-cd.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdeployment%2Fci-cd.mdx&astroContentModuleFlag=true")], ["src/content/docs/deployment/docker-proxy.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdeployment%2Fdocker-proxy.mdx&astroContentModuleFlag=true")], +["src/content/docs/deployment/docker-embedded.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdeployment%2Fdocker-embedded.mdx&astroContentModuleFlag=true")], +["src/content/docs/examples/todo-react.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fexamples%2Ftodo-react.mdx&astroContentModuleFlag=true")], ["src/content/docs/deployment/kubernetes.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fdeployment%2Fkubernetes.mdx&astroContentModuleFlag=true")], -["src/content/docs/guides/installation.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fguides%2Finstallation.mdx&astroContentModuleFlag=true")], -["src/content/docs/guides/development.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fguides%2Fdevelopment.mdx&astroContentModuleFlag=true")], -["src/content/docs/guides/testing.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fguides%2Ftesting.mdx&astroContentModuleFlag=true")], -["src/content/docs/frameworks/angular.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fframeworks%2Fangular.mdx&astroContentModuleFlag=true")], -["src/content/docs/guides/manifest.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fguides%2Fmanifest.mdx&astroContentModuleFlag=true")], ["src/content/docs/frameworks/react.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fframeworks%2Freact.mdx&astroContentModuleFlag=true")], ["src/content/docs/frameworks/svelte.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fframeworks%2Fsvelte.mdx&astroContentModuleFlag=true")], -["src/content/docs/examples/quick-no-manifest.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fexamples%2Fquick-no-manifest.mdx&astroContentModuleFlag=true")], -["src/content/docs/examples/todo-react.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fexamples%2Ftodo-react.mdx&astroContentModuleFlag=true")], +["src/content/docs/frameworks/angular.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fframeworks%2Fangular.mdx&astroContentModuleFlag=true")], ["src/content/docs/frameworks/vanilla.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fframeworks%2Fvanilla.mdx&astroContentModuleFlag=true")], +["src/content/docs/examples/quick-no-manifest.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fexamples%2Fquick-no-manifest.mdx&astroContentModuleFlag=true")], ["src/content/docs/frameworks/vue.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fframeworks%2Fvue.mdx&astroContentModuleFlag=true")], -["src/content/docs/reference/codemod.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Freference%2Fcodemod.mdx&astroContentModuleFlag=true")], -["src/content/docs/reference/gateway-flags.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Freference%2Fgateway-flags.mdx&astroContentModuleFlag=true")], -["src/content/docs/reference/gateway-endpoints.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Freference%2Fgateway-endpoints.mdx&astroContentModuleFlag=true")], +["src/content/docs/guides/development.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fguides%2Fdevelopment.mdx&astroContentModuleFlag=true")], +["src/content/docs/guides/installation.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fguides%2Finstallation.mdx&astroContentModuleFlag=true")], +["src/content/docs/guides/testing.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fguides%2Ftesting.mdx&astroContentModuleFlag=true")], ["src/content/docs/reference/cli.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Freference%2Fcli.mdx&astroContentModuleFlag=true")], +["src/content/docs/reference/codemod.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Freference%2Fcodemod.mdx&astroContentModuleFlag=true")], +["src/content/docs/guides/manifest.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fguides%2Fmanifest.mdx&astroContentModuleFlag=true")], ["src/content/docs/reference/manifest-schema.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Freference%2Fmanifest-schema.mdx&astroContentModuleFlag=true")], ["src/content/docs/reference/sdk.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Freference%2Fsdk.mdx&astroContentModuleFlag=true")], -["src/content/docs/spec/security-model.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fspec%2Fsecurity-model.mdx&astroContentModuleFlag=true")], -["src/content/docs/spec/rfc-0001.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fspec%2Frfc-0001.mdx&astroContentModuleFlag=true")], +["src/content/docs/reference/gateway-endpoints.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Freference%2Fgateway-endpoints.mdx&astroContentModuleFlag=true")], +["src/content/docs/reference/gateway-flags.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Freference%2Fgateway-flags.mdx&astroContentModuleFlag=true")], ["src/content/docs/spec/conformance.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fspec%2Fconformance.mdx&astroContentModuleFlag=true")], ["src/content/docs/spec/index.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fspec%2Findex.mdx&astroContentModuleFlag=true")], -["src/content/docs/guides/migration/overview.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fguides%2Fmigration%2Foverview.mdx&astroContentModuleFlag=true")], -["src/content/docs/guides/migration/from-next.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fguides%2Fmigration%2Ffrom-next.mdx&astroContentModuleFlag=true")], +["src/content/docs/spec/rfc-0001.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fspec%2Frfc-0001.mdx&astroContentModuleFlag=true")], +["src/content/docs/spec/security-model.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fspec%2Fsecurity-model.mdx&astroContentModuleFlag=true")], ["src/content/docs/guides/migration/from-cra.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fguides%2Fmigration%2Ffrom-cra.mdx&astroContentModuleFlag=true")], ["src/content/docs/guides/migration/from-vite.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fguides%2Fmigration%2Ffrom-vite.mdx&astroContentModuleFlag=true")], -["src/content/docs/reference/adapters/vue.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Freference%2Fadapters%2Fvue.mdx&astroContentModuleFlag=true")], +["src/content/docs/guides/migration/overview.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fguides%2Fmigration%2Foverview.mdx&astroContentModuleFlag=true")], +["src/content/docs/guides/migration/from-next.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Fguides%2Fmigration%2Ffrom-next.mdx&astroContentModuleFlag=true")], ["src/content/docs/reference/adapters/svelte.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Freference%2Fadapters%2Fsvelte.mdx&astroContentModuleFlag=true")], -["src/content/docs/reference/adapters/react.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Freference%2Fadapters%2Freact.mdx&astroContentModuleFlag=true")]]); +["src/content/docs/reference/adapters/react.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Freference%2Fadapters%2Freact.mdx&astroContentModuleFlag=true")], +["src/content/docs/reference/adapters/vue.mdx", () => import("astro:content-layer-deferred-module?astro%3Acontent-layer-deferred-module=&fileName=src%2Fcontent%2Fdocs%2Freference%2Fadapters%2Fvue.mdx&astroContentModuleFlag=true")]]); \ No newline at end of file diff --git a/docs/.astro/data-store.json b/docs/.astro/data-store.json index 6b30e60..6e3bad4 100644 --- a/docs/.astro/data-store.json +++ b/docs/.astro/data-store.json @@ -1 +1 @@ -[["Map",1,2,9,10],"meta::meta",["Map",3,4,5,6,7,8],"astro-version","5.17.3","content-config-digest","28e7bc87492477d9","astro-config-digest","{\"root\":{},\"srcDir\":{},\"publicDir\":{},\"outDir\":{},\"cacheDir\":{},\"site\":\"https://rep-protocol.dev\",\"compressHTML\":true,\"base\":\"/\",\"trailingSlash\":\"ignore\",\"output\":\"static\",\"scopedStyleStrategy\":\"where\",\"build\":{\"format\":\"directory\",\"client\":{},\"server\":{},\"assets\":\"_astro\",\"serverEntry\":\"entry.mjs\",\"redirects\":true,\"inlineStylesheets\":\"auto\",\"concurrency\":1},\"server\":{\"open\":false,\"host\":false,\"port\":4321,\"streaming\":true,\"allowedHosts\":[]},\"redirects\":{},\"image\":{\"endpoint\":{\"route\":\"/_image\"},\"service\":{\"entrypoint\":\"astro/assets/services/sharp\",\"config\":{}},\"domains\":[],\"remotePatterns\":[],\"responsiveStyles\":false},\"devToolbar\":{\"enabled\":true},\"markdown\":{\"syntaxHighlight\":false,\"shikiConfig\":{\"langs\":[],\"langAlias\":{},\"theme\":\"github-dark\",\"themes\":{},\"wrap\":false,\"transformers\":[]},\"remarkPlugins\":[null,null,null],\"rehypePlugins\":[null,[null,{\"experimentalHeadingIdCompat\":false}],null,[null,{\"themes\":[{\"name\":\"Night Owl No Italics\",\"type\":\"dark\",\"colors\":{\"focusBorder\":\"#122d42\",\"foreground\":\"#d6deeb\",\"disabledForeground\":\"#cccccc80\",\"descriptionForeground\":\"#d6deebb3\",\"errorForeground\":\"#ef5350\",\"icon.foreground\":\"#c5c5c5\",\"contrastActiveBorder\":null,\"contrastBorder\":\"#122d42\",\"textBlockQuote.background\":\"#7f7f7f1a\",\"textBlockQuote.border\":\"#007acc80\",\"textCodeBlock.background\":\"#4f4f4f\",\"textLink.activeForeground\":\"#3794ff\",\"textLink.foreground\":\"#3794ff\",\"textPreformat.foreground\":\"#d7ba7d\",\"textSeparator.foreground\":\"#ffffff2e\",\"editor.background\":\"#23262f\",\"editor.foreground\":\"#d6deeb\",\"editorLineNumber.foreground\":\"#4b6479\",\"editorLineNumber.activeForeground\":\"#c5e4fd\",\"editorActiveLineNumber.foreground\":\"#c6c6c6\",\"editor.selectionBackground\":\"#1d3b53\",\"editor.inactiveSelectionBackground\":\"#7e57c25a\",\"editor.selectionHighlightBackground\":\"#5f7e9779\",\"editorError.foreground\":\"#ef5350\",\"editorWarning.foreground\":\"#b39554\",\"editorInfo.foreground\":\"#3794ff\",\"editorHint.foreground\":\"#eeeeeeb2\",\"problemsErrorIcon.foreground\":\"#ef5350\",\"problemsWarningIcon.foreground\":\"#b39554\",\"problemsInfoIcon.foreground\":\"#3794ff\",\"editor.findMatchBackground\":\"#5f7e9779\",\"editor.findMatchHighlightBackground\":\"#1085bb5d\",\"editor.findRangeHighlightBackground\":\"#3a3d4166\",\"editorLink.activeForeground\":\"#4e94ce\",\"editorLightBulb.foreground\":\"#ffcc00\",\"editorLightBulbAutoFix.foreground\":\"#75beff\",\"diffEditor.insertedTextBackground\":\"#99b76d23\",\"diffEditor.insertedTextBorder\":\"#c5e47833\",\"diffEditor.removedTextBackground\":\"#ef535033\",\"diffEditor.removedTextBorder\":\"#ef53504d\",\"diffEditor.insertedLineBackground\":\"#9bb95533\",\"diffEditor.removedLineBackground\":\"#ff000033\",\"editorStickyScroll.background\":\"#011627\",\"editorStickyScrollHover.background\":\"#2a2d2e\",\"editorInlayHint.background\":\"#5f7e97cc\",\"editorInlayHint.foreground\":\"#ffffff\",\"editorInlayHint.typeBackground\":\"#5f7e97cc\",\"editorInlayHint.typeForeground\":\"#ffffff\",\"editorInlayHint.parameterBackground\":\"#5f7e97cc\",\"editorInlayHint.parameterForeground\":\"#ffffff\",\"editorPane.background\":\"#011627\",\"editorGroup.emptyBackground\":\"#011627\",\"editorGroup.focusedEmptyBorder\":null,\"editorGroupHeader.tabsBackground\":\"var(--sl-color-black)\",\"editorGroupHeader.tabsBorder\":\"color-mix(in srgb, var(--sl-color-gray-5), transparent 25%)\",\"editorGroupHeader.noTabsBackground\":\"#011627\",\"editorGroupHeader.border\":null,\"editorGroup.border\":\"#011627\",\"editorGroup.dropBackground\":\"#7e57c273\",\"editorGroup.dropIntoPromptForeground\":\"#d6deeb\",\"editorGroup.dropIntoPromptBackground\":\"#021320\",\"editorGroup.dropIntoPromptBorder\":null,\"sideBySideEditor.horizontalBorder\":\"#011627\",\"sideBySideEditor.verticalBorder\":\"#011627\",\"scrollbar.shadow\":\"#010b14\",\"scrollbarSlider.background\":\"#ffffff17\",\"scrollbarSlider.hoverBackground\":\"#ffffff40\",\"scrollbarSlider.activeBackground\":\"#084d8180\",\"panel.background\":\"#011627\",\"panel.border\":\"#5f7e97\",\"panelTitle.activeBorder\":\"#5f7e97\",\"panelTitle.activeForeground\":\"#ffffffcc\",\"panelTitle.inactiveForeground\":\"#d6deeb80\",\"panelSectionHeader.background\":\"#80808051\",\"terminal.background\":\"#011627\",\"widget.shadow\":\"#011627\",\"editorWidget.background\":\"#021320\",\"editorWidget.foreground\":\"#d6deeb\",\"editorWidget.border\":\"#5f7e97\",\"quickInput.background\":\"#021320\",\"quickInput.foreground\":\"#d6deeb\",\"quickInputTitle.background\":\"#ffffff1a\",\"pickerGroup.foreground\":\"#d1aaff\",\"pickerGroup.border\":\"#011627\",\"editor.hoverHighlightBackground\":\"#7e57c25a\",\"editorHoverWidget.background\":\"#011627\",\"editorHoverWidget.foreground\":\"#d6deeb\",\"editorHoverWidget.border\":\"#5f7e97\",\"editorHoverWidget.statusBarBackground\":\"#011a2f\",\"titleBar.activeBackground\":\"var(--sl-color-black)\",\"titleBar.activeForeground\":\"var(--sl-color-text)\",\"titleBar.inactiveBackground\":\"#010e1a\",\"titleBar.inactiveForeground\":\"#eeefff99\",\"titleBar.border\":\"color-mix(in srgb, var(--sl-color-gray-5), transparent 25%)\",\"toolbar.hoverBackground\":\"#5a5d5e50\",\"toolbar.activeBackground\":\"#63666750\",\"tab.activeBackground\":\"#0b2942\",\"tab.unfocusedActiveBackground\":\"#0b2942\",\"tab.inactiveBackground\":\"#01111d\",\"tab.unfocusedInactiveBackground\":\"#01111d\",\"tab.activeForeground\":\"var(--sl-color-text)\",\"tab.inactiveForeground\":\"#5f7e97\",\"tab.unfocusedActiveForeground\":\"#5f7e97\",\"tab.unfocusedInactiveForeground\":\"#5f7e97\",\"tab.hoverBackground\":null,\"tab.unfocusedHoverBackground\":null,\"tab.hoverForeground\":null,\"tab.unfocusedHoverForeground\":null,\"tab.border\":\"#272b3b\",\"tab.lastPinnedBorder\":\"#585858\",\"tab.activeBorder\":\"transparent\",\"tab.unfocusedActiveBorder\":\"#262a39\",\"tab.activeBorderTop\":\"var(--sl-color-accent-high)\",\"tab.unfocusedActiveBorderTop\":null,\"tab.hoverBorder\":null,\"tab.unfocusedHoverBorder\":null,\"tab.activeModifiedBorder\":\"#3399cc\",\"tab.inactiveModifiedBorder\":\"#3399cc80\",\"tab.unfocusedActiveModifiedBorder\":\"#3399cc80\",\"tab.unfocusedInactiveModifiedBorder\":\"#3399cc40\",\"badge.background\":\"#5f7e97\",\"badge.foreground\":\"#ffffff\",\"button.background\":\"#7e57c2cc\",\"button.foreground\":\"#ffffffcc\",\"button.border\":\"#122d42\",\"button.separator\":\"#ffffff52\",\"button.hoverBackground\":\"#7e57c2\",\"button.secondaryBackground\":\"#3a3d41\",\"button.secondaryForeground\":\"#ffffff\",\"button.secondaryHoverBackground\":\"#46494e\",\"dropdown.background\":\"#011627\",\"dropdown.foreground\":\"#ffffffcc\",\"dropdown.border\":\"#5f7e97\",\"list.activeSelectionBackground\":\"#234d708c\",\"list.activeSelectionForeground\":\"#ffffff\",\"tree.indentGuidesStroke\":\"#585858\",\"input.background\":\"#0b253a\",\"input.foreground\":\"#ffffffcc\",\"input.placeholderForeground\":\"#5f7e97\",\"inputOption.activeBorder\":\"#ffffffcc\",\"inputOption.hoverBackground\":\"#5a5d5e80\",\"inputOption.activeBackground\":\"#122d4266\",\"inputOption.activeForeground\":\"#ffffff\",\"inputValidation.infoBackground\":\"#00589ef2\",\"inputValidation.infoBorder\":\"#64b5f6\",\"inputValidation.warningBackground\":\"#675700f2\",\"inputValidation.warningBorder\":\"#ffca28\",\"inputValidation.errorBackground\":\"#ab0300f2\",\"inputValidation.errorBorder\":\"#ef5350\",\"keybindingLabel.background\":\"#8080802b\",\"keybindingLabel.foreground\":\"#cccccc\",\"keybindingLabel.border\":\"#33333399\",\"keybindingLabel.bottomBorder\":\"#44444499\",\"menu.foreground\":\"#ffffffcc\",\"menu.background\":\"#011627\",\"menu.selectionForeground\":\"#ffffff\",\"menu.selectionBackground\":\"#234d708c\",\"menu.separatorBackground\":\"#606060\",\"editor.snippetTabstopHighlightBackground\":\"#7c7c74c\",\"editor.snippetFinalTabstopHighlightBorder\":\"#525252\",\"terminal.ansiBlack\":\"#011627\",\"terminal.ansiRed\":\"#ef5350\",\"terminal.ansiGreen\":\"#22da6e\",\"terminal.ansiYellow\":\"#c5e478\",\"terminal.ansiBlue\":\"#82aaff\",\"terminal.ansiMagenta\":\"#c792ea\",\"terminal.ansiCyan\":\"#21c7a8\",\"terminal.ansiWhite\":\"#ffffff\",\"terminal.ansiBrightBlack\":\"#575656\",\"terminal.ansiBrightRed\":\"#ef5350\",\"terminal.ansiBrightGreen\":\"#22da6e\",\"terminal.ansiBrightYellow\":\"#ffeb95\",\"terminal.ansiBrightBlue\":\"#82aaff\",\"terminal.ansiBrightMagenta\":\"#c792ea\",\"terminal.ansiBrightCyan\":\"#7fdbca\",\"terminal.ansiBrightWhite\":\"#ffffff\",\"selection.background\":\"#4373c2\",\"input.border\":\"#5f7e97\",\"punctuation.definition.generic.begin.html\":\"#ef5350f2\",\"progress.background\":\"#7e57c2\",\"breadcrumb.foreground\":\"#a599e9\",\"breadcrumb.focusForeground\":\"#ffffff\",\"breadcrumb.activeSelectionForeground\":\"#ffffff\",\"breadcrumbPicker.background\":\"#001122\",\"list.invalidItemForeground\":\"#975f94\",\"list.dropBackground\":\"#011627\",\"list.focusBackground\":\"#010d18\",\"list.focusForeground\":\"#ffffff\",\"list.highlightForeground\":\"#ffffff\",\"list.hoverBackground\":\"#011627\",\"list.hoverForeground\":\"#ffffff\",\"list.inactiveSelectionBackground\":\"#0e293f\",\"list.inactiveSelectionForeground\":\"#5f7e97\",\"activityBar.background\":\"#011627\",\"activityBar.dropBackground\":\"#5f7e97\",\"activityBar.foreground\":\"#5f7e97\",\"activityBar.border\":\"#011627\",\"activityBarBadge.background\":\"#44596b\",\"activityBarBadge.foreground\":\"#ffffff\",\"sideBar.background\":\"#011627\",\"sideBar.foreground\":\"#89a4bb\",\"sideBar.border\":\"#011627\",\"sideBarTitle.foreground\":\"#5f7e97\",\"sideBarSectionHeader.background\":\"#011627\",\"sideBarSectionHeader.foreground\":\"#5f7e97\",\"editorCursor.foreground\":\"#80a4c2\",\"editor.wordHighlightBackground\":\"#f6bbe533\",\"editor.wordHighlightStrongBackground\":\"#e2a2f433\",\"editor.lineHighlightBackground\":\"#0003\",\"editor.rangeHighlightBackground\":\"#7e57c25a\",\"editorIndentGuide.background\":\"#5e81ce52\",\"editorIndentGuide.activeBackground\":\"#7e97ac\",\"editorRuler.foreground\":\"#5e81ce52\",\"editorCodeLens.foreground\":\"#5e82ceb4\",\"editorBracketMatch.background\":\"#5f7e974d\",\"editorOverviewRuler.currentContentForeground\":\"#7e57c2\",\"editorOverviewRuler.incomingContentForeground\":\"#7e57c2\",\"editorOverviewRuler.commonContentForeground\":\"#7e57c2\",\"editorGutter.background\":\"#011627\",\"editorGutter.modifiedBackground\":\"#e2b93d\",\"editorGutter.addedBackground\":\"#9ccc65\",\"editorGutter.deletedBackground\":\"#ef5350\",\"editorSuggestWidget.background\":\"#2c3043\",\"editorSuggestWidget.border\":\"#2b2f40\",\"editorSuggestWidget.foreground\":\"#d6deeb\",\"editorSuggestWidget.highlightForeground\":\"#ffffff\",\"editorSuggestWidget.selectedBackground\":\"#5f7e97\",\"debugExceptionWidget.background\":\"#011627\",\"debugExceptionWidget.border\":\"#5f7e97\",\"editorMarkerNavigation.background\":\"#0b2942\",\"editorMarkerNavigationError.background\":\"#ef5350\",\"editorMarkerNavigationWarning.background\":\"#ffca28\",\"peekView.border\":\"#5f7e97\",\"peekViewEditor.background\":\"#011627\",\"peekViewEditor.matchHighlightBackground\":\"#7e57c25a\",\"peekViewResult.background\":\"#011627\",\"peekViewResult.fileForeground\":\"#5f7e97\",\"peekViewResult.lineForeground\":\"#5f7e97\",\"peekViewResult.matchHighlightBackground\":\"#ffffffcc\",\"peekViewResult.selectionBackground\":\"#2e3250\",\"peekViewResult.selectionForeground\":\"#5f7e97\",\"peekViewTitle.background\":\"#011627\",\"peekViewTitleDescription.foreground\":\"#697098\",\"peekViewTitleLabel.foreground\":\"#5f7e97\",\"merge.currentHeaderBackground\":\"#5f7e97\",\"merge.incomingHeaderBackground\":\"#7e57c25a\",\"statusBar.background\":\"#011627\",\"statusBar.foreground\":\"#5f7e97\",\"statusBar.border\":\"#262a39\",\"statusBar.debuggingBackground\":\"#202431\",\"statusBar.debuggingBorder\":\"#1f2330\",\"statusBar.noFolderBackground\":\"#011627\",\"statusBar.noFolderBorder\":\"#25293a\",\"statusBarItem.activeBackground\":\"#202431\",\"statusBarItem.hoverBackground\":\"#202431\",\"statusBarItem.prominentBackground\":\"#202431\",\"statusBarItem.prominentHoverBackground\":\"#202431\",\"notifications.background\":\"#01111d\",\"notifications.border\":\"#262a39\",\"notificationCenter.border\":\"#262a39\",\"notificationToast.border\":\"#262a39\",\"notifications.foreground\":\"#ffffffcc\",\"notificationLink.foreground\":\"#80cbc4\",\"extensionButton.prominentForeground\":\"#ffffffcc\",\"extensionButton.prominentBackground\":\"#7e57c2cc\",\"extensionButton.prominentHoverBackground\":\"#7e57c2\",\"terminal.selectionBackground\":\"#1b90dd4d\",\"terminalCursor.background\":\"#234d70\",\"debugToolBar.background\":\"#011627\",\"welcomePage.buttonBackground\":\"#011627\",\"welcomePage.buttonHoverBackground\":\"#011627\",\"walkThrough.embeddedEditorBackground\":\"#011627\",\"gitDecoration.modifiedResourceForeground\":\"#a2bffc\",\"gitDecoration.deletedResourceForeground\":\"#ef535090\",\"gitDecoration.untrackedResourceForeground\":\"#c5e478ff\",\"gitDecoration.ignoredResourceForeground\":\"#395a75\",\"gitDecoration.conflictingResourceForeground\":\"#ffeb95cc\",\"source.elm\":\"#5f7e97\",\"string.quoted.single.js\":\"#ffffff\",\"meta.objectliteral.js\":\"#82aaff\"},\"fg\":\"#d6deeb\",\"bg\":\"#23262f\",\"semanticHighlighting\":false,\"settings\":[{\"name\":\"Changed\",\"scope\":[\"markup.changed\",\"meta.diff.header.git\",\"meta.diff.header.from-file\",\"meta.diff.header.to-file\"],\"settings\":{\"foreground\":\"#a2bffc\"}},{\"name\":\"Deleted\",\"scope\":[\"markup.deleted.diff\"],\"settings\":{\"foreground\":\"#f27775fe\"}},{\"name\":\"Inserted\",\"scope\":[\"markup.inserted.diff\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Global settings\",\"settings\":{\"background\":\"#011627\",\"foreground\":\"#d6deeb\"}},{\"name\":\"Comment\",\"scope\":[\"comment\"],\"settings\":{\"foreground\":\"#919f9f\",\"fontStyle\":\"\"}},{\"name\":\"String\",\"scope\":[\"string\"],\"settings\":{\"foreground\":\"#ecc48d\"}},{\"name\":\"String Quoted\",\"scope\":[\"string.quoted\",\"variable.other.readwrite.js\"],\"settings\":{\"foreground\":\"#ecc48d\"}},{\"name\":\"Support Constant Math\",\"scope\":[\"support.constant.math\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Number\",\"scope\":[\"constant.numeric\",\"constant.character.numeric\"],\"settings\":{\"foreground\":\"#f78c6c\",\"fontStyle\":\"\"}},{\"name\":\"Built-in constant\",\"scope\":[\"constant.language\",\"punctuation.definition.constant\",\"variable.other.constant\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"User-defined constant\",\"scope\":[\"constant.character\",\"constant.other\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"Constant Character Escape\",\"scope\":[\"constant.character.escape\"],\"settings\":{\"foreground\":\"#f78c6c\"}},{\"name\":\"RegExp String\",\"scope\":[\"string.regexp\",\"string.regexp keyword.other\"],\"settings\":{\"foreground\":\"#5ca7e4\"}},{\"name\":\"Comma in functions\",\"scope\":[\"meta.function punctuation.separator.comma\"],\"settings\":{\"foreground\":\"#889fb2\"}},{\"name\":\"Variable\",\"scope\":[\"variable\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Keyword\",\"scope\":[\"punctuation.accessor\",\"keyword\"],\"settings\":{\"foreground\":\"#c792ea\",\"fontStyle\":\"\"}},{\"name\":\"Storage\",\"scope\":[\"storage\",\"meta.var.expr\",\"meta.class meta.method.declaration meta.var.expr storage.type.js\",\"storage.type.property.js\",\"storage.type.property.ts\",\"storage.type.property.tsx\"],\"settings\":{\"foreground\":\"#c792ea\",\"fontStyle\":\"\"}},{\"name\":\"Storage type\",\"scope\":[\"storage.type\"],\"settings\":{\"foreground\":\"#c792ea\"}},{\"name\":\"Storage type\",\"scope\":[\"storage.type.function.arrow.js\"],\"settings\":{\"fontStyle\":\"\"}},{\"name\":\"Class name\",\"scope\":[\"entity.name.class\",\"meta.class entity.name.type.class\"],\"settings\":{\"foreground\":\"#ffcb8b\"}},{\"name\":\"Inherited class\",\"scope\":[\"entity.other.inherited-class\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Function name\",\"scope\":[\"entity.name.function\"],\"settings\":{\"foreground\":\"#c792ea\",\"fontStyle\":\"\"}},{\"name\":\"Meta Tag\",\"scope\":[\"punctuation.definition.tag\",\"meta.tag\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"HTML Tag names\",\"scope\":[\"entity.name.tag\",\"meta.tag.other.html\",\"meta.tag.other.js\",\"meta.tag.other.tsx\",\"entity.name.tag.tsx\",\"entity.name.tag.js\",\"entity.name.tag\",\"meta.tag.js\",\"meta.tag.tsx\",\"meta.tag.html\"],\"settings\":{\"foreground\":\"#caece6\",\"fontStyle\":\"\"}},{\"name\":\"Tag attribute\",\"scope\":[\"entity.other.attribute-name\"],\"settings\":{\"fontStyle\":\"\",\"foreground\":\"#c5e478\"}},{\"name\":\"Entity Name Tag Custom\",\"scope\":[\"entity.name.tag.custom\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Library (function & constant)\",\"scope\":[\"support.function\",\"support.constant\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"Support Constant Property Value meta\",\"scope\":[\"support.constant.meta.property-value\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"Library class/type\",\"scope\":[\"support.type\",\"support.class\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Support Variable DOM\",\"scope\":[\"support.variable.dom\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Invalid\",\"scope\":[\"invalid\"],\"settings\":{\"background\":\"#ff2c83\",\"foreground\":\"#ffffff\"}},{\"name\":\"Invalid deprecated\",\"scope\":[\"invalid.deprecated\"],\"settings\":{\"foreground\":\"#ffffff\",\"background\":\"#d3423e\"}},{\"name\":\"Keyword Operator\",\"scope\":[\"keyword.operator\"],\"settings\":{\"foreground\":\"#7fdbca\",\"fontStyle\":\"\"}},{\"name\":\"Keyword Operator Relational\",\"scope\":[\"keyword.operator.relational\"],\"settings\":{\"foreground\":\"#c792ea\",\"fontStyle\":\"\"}},{\"name\":\"Keyword Operator Assignment\",\"scope\":[\"keyword.operator.assignment\"],\"settings\":{\"foreground\":\"#c792ea\"}},{\"name\":\"Keyword Operator Arithmetic\",\"scope\":[\"keyword.operator.arithmetic\"],\"settings\":{\"foreground\":\"#c792ea\"}},{\"name\":\"Keyword Operator Bitwise\",\"scope\":[\"keyword.operator.bitwise\"],\"settings\":{\"foreground\":\"#c792ea\"}},{\"name\":\"Keyword Operator Increment\",\"scope\":[\"keyword.operator.increment\"],\"settings\":{\"foreground\":\"#c792ea\"}},{\"name\":\"Keyword Operator Ternary\",\"scope\":[\"keyword.operator.ternary\"],\"settings\":{\"foreground\":\"#c792ea\"}},{\"name\":\"Double-Slashed Comment\",\"scope\":[\"comment.line.double-slash\"],\"settings\":{\"foreground\":\"#919f9f\"}},{\"name\":\"Object\",\"scope\":[\"object\"],\"settings\":{\"foreground\":\"#cdebf7\"}},{\"name\":\"Null\",\"scope\":[\"constant.language.null\"],\"settings\":{\"foreground\":\"#ff6a83\"}},{\"name\":\"Meta Brace\",\"scope\":[\"meta.brace\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"Meta Delimiter Period\",\"scope\":[\"meta.delimiter.period\"],\"settings\":{\"foreground\":\"#c792ea\",\"fontStyle\":\"\"}},{\"name\":\"Punctuation Definition String\",\"scope\":[\"punctuation.definition.string\"],\"settings\":{\"foreground\":\"#d9f5dd\"}},{\"name\":\"Punctuation Definition String Markdown\",\"scope\":[\"punctuation.definition.string.begin.markdown\"],\"settings\":{\"foreground\":\"#ff6a83\"}},{\"name\":\"Boolean\",\"scope\":[\"constant.language.boolean\"],\"settings\":{\"foreground\":\"#ff6a83\"}},{\"name\":\"Object Comma\",\"scope\":[\"object.comma\"],\"settings\":{\"foreground\":\"#ffffff\"}},{\"name\":\"Variable Parameter Function\",\"scope\":[\"variable.parameter.function\"],\"settings\":{\"foreground\":\"#7fdbca\",\"fontStyle\":\"\"}},{\"name\":\"Support Type Property Name & entity name tags\",\"scope\":[\"support.type.vendor.property-name\",\"support.constant.vendor.property-value\",\"support.type.property-name\",\"meta.property-list entity.name.tag\"],\"settings\":{\"foreground\":\"#80cbc4\",\"fontStyle\":\"\"}},{\"name\":\"Entity Name tag reference in stylesheets\",\"scope\":[\"meta.property-list entity.name.tag.reference\"],\"settings\":{\"foreground\":\"#57eaf1\"}},{\"name\":\"Constant Other Color RGB Value Punctuation Definition Constant\",\"scope\":[\"constant.other.color.rgb-value punctuation.definition.constant\"],\"settings\":{\"foreground\":\"#f78c6c\"}},{\"name\":\"Constant Other Color\",\"scope\":[\"constant.other.color\"],\"settings\":{\"foreground\":\"#ffeb95\"}},{\"name\":\"Keyword Other Unit\",\"scope\":[\"keyword.other.unit\"],\"settings\":{\"foreground\":\"#ffeb95\"}},{\"name\":\"Meta Selector\",\"scope\":[\"meta.selector\"],\"settings\":{\"foreground\":\"#c792ea\",\"fontStyle\":\"\"}},{\"name\":\"Entity Other Attribute Name Id\",\"scope\":[\"entity.other.attribute-name.id\"],\"settings\":{\"foreground\":\"#fad430\"}},{\"name\":\"Meta Property Name\",\"scope\":[\"meta.property-name\"],\"settings\":{\"foreground\":\"#80cbc4\"}},{\"name\":\"Doctypes\",\"scope\":[\"entity.name.tag.doctype\",\"meta.tag.sgml.doctype\"],\"settings\":{\"foreground\":\"#c792ea\",\"fontStyle\":\"\"}},{\"name\":\"Punctuation Definition Parameters\",\"scope\":[\"punctuation.definition.parameters\"],\"settings\":{\"foreground\":\"#d9f5dd\"}},{\"name\":\"Keyword Control Operator\",\"scope\":[\"keyword.control.operator\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"Keyword Operator Logical\",\"scope\":[\"keyword.operator.logical\"],\"settings\":{\"foreground\":\"#c792ea\",\"fontStyle\":\"\"}},{\"name\":\"Variable Instances\",\"scope\":[\"variable.instance\",\"variable.other.instance\",\"variable.readwrite.instance\",\"variable.other.readwrite.instance\",\"variable.other.property\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"Variable Property Other object property\",\"scope\":[\"variable.other.object.property\"],\"settings\":{\"foreground\":\"#faf39f\",\"fontStyle\":\"\"}},{\"name\":\"Variable Property Other object\",\"scope\":[\"variable.other.object.js\"],\"settings\":{\"fontStyle\":\"\"}},{\"name\":\"Entity Name Function\",\"scope\":[\"entity.name.function\"],\"settings\":{\"foreground\":\"#82aaff\",\"fontStyle\":\"\"}},{\"name\":\"Keyword Operator Comparison, returns, imports, and Keyword Operator Ruby\",\"scope\":[\"keyword.control.conditional.js\",\"keyword.operator.comparison\",\"keyword.control.flow.js\",\"keyword.control.flow.ts\",\"keyword.control.flow.tsx\",\"keyword.control.ruby\",\"keyword.control.def.ruby\",\"keyword.control.loop.js\",\"keyword.control.loop.ts\",\"keyword.control.import.js\",\"keyword.control.import.ts\",\"keyword.control.import.tsx\",\"keyword.control.from.js\",\"keyword.control.from.ts\",\"keyword.control.from.tsx\",\"keyword.control.conditional.js\",\"keyword.control.conditional.ts\",\"keyword.control.switch.js\",\"keyword.control.switch.ts\",\"keyword.operator.instanceof.js\",\"keyword.operator.expression.instanceof.ts\",\"keyword.operator.expression.instanceof.tsx\"],\"settings\":{\"foreground\":\"#c792ea\",\"fontStyle\":\"\"}},{\"name\":\"Support Constant, `new` keyword, Special Method Keyword, `debugger`, other keywords\",\"scope\":[\"support.constant\",\"keyword.other.special-method\",\"keyword.other.new\",\"keyword.other.debugger\",\"keyword.control\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"Support Function\",\"scope\":[\"support.function\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Invalid Broken\",\"scope\":[\"invalid.broken\"],\"settings\":{\"foreground\":\"#989da0\",\"background\":\"#F78C6C\"}},{\"name\":\"Invalid Unimplemented\",\"scope\":[\"invalid.unimplemented\"],\"settings\":{\"background\":\"#8BD649\",\"foreground\":\"#ffffff\"}},{\"name\":\"Invalid Illegal\",\"scope\":[\"invalid.illegal\"],\"settings\":{\"foreground\":\"#ffffff\",\"background\":\"#ec5f67\"}},{\"name\":\"Language Variable\",\"scope\":[\"variable.language\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"Support Variable Property\",\"scope\":[\"support.variable.property\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"Variable Function\",\"scope\":[\"variable.function\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"Variable Interpolation\",\"scope\":[\"variable.interpolation\"],\"settings\":{\"foreground\":\"#ef787f\"}},{\"name\":\"Meta Function Call\",\"scope\":[\"meta.function-call\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"Punctuation Section Embedded\",\"scope\":[\"punctuation.section.embedded\"],\"settings\":{\"foreground\":\"#e2817f\"}},{\"name\":\"Punctuation Tweaks\",\"scope\":[\"punctuation.terminator.expression\",\"punctuation.definition.arguments\",\"punctuation.definition.array\",\"punctuation.section.array\",\"meta.array\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"More Punctuation Tweaks\",\"scope\":[\"punctuation.definition.list.begin\",\"punctuation.definition.list.end\",\"punctuation.separator.arguments\",\"punctuation.definition.list\"],\"settings\":{\"foreground\":\"#d9f5dd\"}},{\"name\":\"Template Strings\",\"scope\":[\"string.template meta.template.expression\"],\"settings\":{\"foreground\":\"#e2817f\"}},{\"name\":\"Backtics(``) in Template Strings\",\"scope\":[\"string.template punctuation.definition.string\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"Italics\",\"scope\":[\"italic\"],\"settings\":{\"foreground\":\"#c792ea\",\"fontStyle\":\"italic\"}},{\"name\":\"Bold\",\"scope\":[\"bold\"],\"settings\":{\"foreground\":\"#c5e478\",\"fontStyle\":\"bold\"}},{\"name\":\"Quote\",\"scope\":[\"quote\"],\"settings\":{\"foreground\":\"#969bb7\",\"fontStyle\":\"\"}},{\"name\":\"Raw Code\",\"scope\":[\"raw\"],\"settings\":{\"foreground\":\"#80cbc4\"}},{\"name\":\"CoffeScript Variable Assignment\",\"scope\":[\"variable.assignment.coffee\"],\"settings\":{\"foreground\":\"#31e1eb\"}},{\"name\":\"CoffeScript Parameter Function\",\"scope\":[\"variable.parameter.function.coffee\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"CoffeeScript Assignments\",\"scope\":[\"variable.assignment.coffee\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"C# Readwrite Variables\",\"scope\":[\"variable.other.readwrite.cs\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"C# Classes & Storage types\",\"scope\":[\"entity.name.type.class.cs\",\"storage.type.cs\"],\"settings\":{\"foreground\":\"#ffcb8b\"}},{\"name\":\"C# Namespaces\",\"scope\":[\"entity.name.type.namespace.cs\"],\"settings\":{\"foreground\":\"#b2ccd6\"}},{\"name\":\"C# Unquoted String Zone\",\"scope\":[\"string.unquoted.preprocessor.message.cs\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"C# Region\",\"scope\":[\"punctuation.separator.hash.cs\",\"keyword.preprocessor.region.cs\",\"keyword.preprocessor.endregion.cs\"],\"settings\":{\"foreground\":\"#ffcb8b\",\"fontStyle\":\"bold\"}},{\"name\":\"C# Other Variables\",\"scope\":[\"variable.other.object.cs\"],\"settings\":{\"foreground\":\"#b2ccd6\"}},{\"name\":\"C# Enum\",\"scope\":[\"entity.name.type.enum.cs\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Dart String\",\"scope\":[\"string.interpolated.single.dart\",\"string.interpolated.double.dart\"],\"settings\":{\"foreground\":\"#ffcb8b\"}},{\"name\":\"Dart Class\",\"scope\":[\"support.class.dart\"],\"settings\":{\"foreground\":\"#ffcb8b\"}},{\"name\":\"Tag names in Stylesheets\",\"scope\":[\"entity.name.tag.css\",\"entity.name.tag.less\",\"entity.name.tag.custom.css\",\"support.constant.property-value.css\"],\"settings\":{\"foreground\":\"#ff6d6d\",\"fontStyle\":\"\"}},{\"name\":\"Wildcard(*) selector in Stylesheets\",\"scope\":[\"entity.name.tag.wildcard.css\",\"entity.name.tag.wildcard.less\",\"entity.name.tag.wildcard.scss\",\"entity.name.tag.wildcard.sass\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"CSS Keyword Other Unit\",\"scope\":[\"keyword.other.unit.css\"],\"settings\":{\"foreground\":\"#ffeb95\"}},{\"name\":\"Attribute Name for CSS\",\"scope\":[\"meta.attribute-selector.css entity.other.attribute-name.attribute\",\"variable.other.readwrite.js\"],\"settings\":{\"foreground\":\"#f78c6c\"}},{\"name\":\"Elixir Classes\",\"scope\":[\"source.elixir support.type.elixir\",\"source.elixir meta.module.elixir entity.name.class.elixir\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"Elixir Functions\",\"scope\":[\"source.elixir entity.name.function\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Elixir Constants\",\"scope\":[\"source.elixir constant.other.symbol.elixir\",\"source.elixir constant.other.keywords.elixir\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"Elixir String Punctuations\",\"scope\":[\"source.elixir punctuation.definition.string\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Elixir\",\"scope\":[\"source.elixir variable.other.readwrite.module.elixir\",\"source.elixir variable.other.readwrite.module.elixir punctuation.definition.variable.elixir\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Elixir Binary Punctuations\",\"scope\":[\"source.elixir .punctuation.binary.elixir\"],\"settings\":{\"foreground\":\"#c792ea\",\"fontStyle\":\"\"}},{\"name\":\"Closure Constant Keyword\",\"scope\":[\"constant.keyword.clojure\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"Go Function Calls\",\"scope\":[\"source.go meta.function-call.go\"],\"settings\":{\"foreground\":\"#dddddd\"}},{\"name\":\"Go Keywords\",\"scope\":[\"source.go keyword.package.go\",\"source.go keyword.import.go\",\"source.go keyword.function.go\",\"source.go keyword.type.go\",\"source.go keyword.struct.go\",\"source.go keyword.interface.go\",\"source.go keyword.const.go\",\"source.go keyword.var.go\",\"source.go keyword.map.go\",\"source.go keyword.channel.go\",\"source.go keyword.control.go\"],\"settings\":{\"foreground\":\"#c792ea\"}},{\"name\":\"Go Constants e.g. nil, string format (%s, %d, etc.)\",\"scope\":[\"source.go constant.language.go\",\"source.go constant.other.placeholder.go\"],\"settings\":{\"foreground\":\"#ff6a83\"}},{\"name\":\"C++ Functions\",\"scope\":[\"entity.name.function.preprocessor.cpp\",\"entity.scope.name.cpp\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"C++ Meta Namespace\",\"scope\":[\"meta.namespace-block.cpp\"],\"settings\":{\"foreground\":\"#e0dec6\"}},{\"name\":\"C++ Language Primitive Storage\",\"scope\":[\"storage.type.language.primitive.cpp\"],\"settings\":{\"foreground\":\"#ff6a83\"}},{\"name\":\"C++ Preprocessor Macro\",\"scope\":[\"meta.preprocessor.macro.cpp\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"C++ Variable Parameter\",\"scope\":[\"variable.parameter\"],\"settings\":{\"foreground\":\"#ffcb8b\"}},{\"name\":\"Powershell Variables\",\"scope\":[\"variable.other.readwrite.powershell\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"Powershell Function\",\"scope\":[\"support.function.powershell\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"ID Attribute Name in HTML\",\"scope\":[\"entity.other.attribute-name.id.html\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"HTML Punctuation Definition Tag\",\"scope\":[\"punctuation.definition.tag.html\"],\"settings\":{\"foreground\":\"#6ae9f0\"}},{\"name\":\"HTML Doctype\",\"scope\":[\"meta.tag.sgml.doctype.html\"],\"settings\":{\"foreground\":\"#c792ea\",\"fontStyle\":\"\"}},{\"name\":\"JavaScript Classes\",\"scope\":[\"meta.class entity.name.type.class.js\"],\"settings\":{\"foreground\":\"#ffcb8b\"}},{\"name\":\"JavaScript Method Declaration e.g. `constructor`\",\"scope\":[\"meta.method.declaration storage.type.js\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"JavaScript Terminator\",\"scope\":[\"terminator.js\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"JavaScript Meta Punctuation Definition\",\"scope\":[\"meta.js punctuation.definition.js\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"Entity Names in Code Documentations\",\"scope\":[\"entity.name.type.instance.jsdoc\",\"entity.name.type.instance.phpdoc\"],\"settings\":{\"foreground\":\"#889fb2\"}},{\"name\":\"Other Variables in Code Documentations\",\"scope\":[\"variable.other.jsdoc\",\"variable.other.phpdoc\"],\"settings\":{\"foreground\":\"#78ccf0\"}},{\"name\":\"JavaScript module imports and exports\",\"scope\":[\"variable.other.meta.import.js\",\"meta.import.js variable.other\",\"variable.other.meta.export.js\",\"meta.export.js variable.other\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"JavaScript Variable Parameter Function\",\"scope\":[\"variable.parameter.function.js\"],\"settings\":{\"foreground\":\"#8b96ea\"}},{\"name\":\"JavaScript[React] Variable Other Object\",\"scope\":[\"variable.other.object.js\",\"variable.other.object.jsx\",\"variable.object.property.js\",\"variable.object.property.jsx\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"JavaScript Variables\",\"scope\":[\"variable.js\",\"variable.other.js\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"JavaScript Entity Name Type\",\"scope\":[\"entity.name.type.js\",\"entity.name.type.module.js\"],\"settings\":{\"foreground\":\"#ffcb8b\",\"fontStyle\":\"\"}},{\"name\":\"JavaScript Support Classes\",\"scope\":[\"support.class.js\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"JSON Property Names\",\"scope\":[\"support.type.property-name.json\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"JSON Support Constants\",\"scope\":[\"support.constant.json\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"JSON Property values (string)\",\"scope\":[\"meta.structure.dictionary.value.json string.quoted.double\"],\"settings\":{\"foreground\":\"#c789d6\"}},{\"name\":\"Strings in JSON values\",\"scope\":[\"string.quoted.double.json punctuation.definition.string.json\"],\"settings\":{\"foreground\":\"#80cbc4\"}},{\"name\":\"Specific JSON Property values like null\",\"scope\":[\"meta.structure.dictionary.json meta.structure.dictionary.value constant.language\"],\"settings\":{\"foreground\":\"#ff6a83\"}},{\"name\":\"JavaScript Other Variable\",\"scope\":[\"variable.other.object.js\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"Ruby Variables\",\"scope\":[\"variable.other.ruby\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"Ruby Class\",\"scope\":[\"entity.name.type.class.ruby\"],\"settings\":{\"foreground\":\"#ecc48d\"}},{\"name\":\"Ruby Hashkeys\",\"scope\":[\"constant.language.symbol.hashkey.ruby\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"LESS Tag names\",\"scope\":[\"entity.name.tag.less\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"LESS Keyword Other Unit\",\"scope\":[\"keyword.other.unit.css\"],\"settings\":{\"foreground\":\"#ffeb95\"}},{\"name\":\"Attribute Name for LESS\",\"scope\":[\"meta.attribute-selector.less entity.other.attribute-name.attribute\"],\"settings\":{\"foreground\":\"#f78c6c\"}},{\"name\":\"Markdown Headings\",\"scope\":[\"markup.heading.markdown\",\"markup.heading.setext.1.markdown\",\"markup.heading.setext.2.markdown\"],\"settings\":{\"foreground\":\"#82b1ff\"}},{\"name\":\"Markdown Italics\",\"scope\":[\"markup.italic.markdown\"],\"settings\":{\"foreground\":\"#c792ea\",\"fontStyle\":\"italic\"}},{\"name\":\"Markdown Bold\",\"scope\":[\"markup.bold.markdown\"],\"settings\":{\"foreground\":\"#c5e478\",\"fontStyle\":\"bold\"}},{\"name\":\"Markdown Quote + others\",\"scope\":[\"markup.quote.markdown\"],\"settings\":{\"foreground\":\"#969bb7\",\"fontStyle\":\"\"}},{\"name\":\"Markdown Raw Code + others\",\"scope\":[\"markup.inline.raw.markdown\"],\"settings\":{\"foreground\":\"#80cbc4\"}},{\"name\":\"Markdown Links\",\"scope\":[\"markup.underline.link.markdown\",\"markup.underline.link.image.markdown\"],\"settings\":{\"foreground\":\"#ff869a\",\"fontStyle\":\"underline\"}},{\"name\":\"Markdown Link Title and Description\",\"scope\":[\"string.other.link.title.markdown\",\"string.other.link.description.markdown\"],\"settings\":{\"foreground\":\"#d6deeb\",\"fontStyle\":\"underline\"}},{\"name\":\"Markdown Punctuation\",\"scope\":[\"punctuation.definition.string.markdown\",\"punctuation.definition.string.begin.markdown\",\"punctuation.definition.string.end.markdown\",\"meta.link.inline.markdown punctuation.definition.string\"],\"settings\":{\"foreground\":\"#82b1ff\"}},{\"name\":\"Markdown MetaData Punctuation\",\"scope\":[\"punctuation.definition.metadata.markdown\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"Markdown List Punctuation\",\"scope\":[\"beginning.punctuation.definition.list.markdown\"],\"settings\":{\"foreground\":\"#82b1ff\"}},{\"name\":\"Markdown Inline Raw String\",\"scope\":[\"markup.inline.raw.string.markdown\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"PHP Variables\",\"scope\":[\"variable.other.php\"],\"settings\":{\"foreground\":\"#bec5d4\"}},{\"name\":\"Support Classes in PHP\",\"scope\":[\"support.class.php\"],\"settings\":{\"foreground\":\"#ffcb8b\"}},{\"name\":\"Punctuations in PHP function calls\",\"scope\":[\"meta.function-call.php punctuation\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"PHP Global Variables\",\"scope\":[\"variable.other.global.php\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Declaration Punctuation in PHP Global Variables\",\"scope\":[\"variable.other.global.php punctuation.definition.variable\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Language Constants in Python\",\"scope\":[\"constant.language.python\"],\"settings\":{\"foreground\":\"#ff6a83\"}},{\"name\":\"Python Function Parameter and Arguments\",\"scope\":[\"variable.parameter.function.python\",\"meta.function-call.arguments.python\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"Python Function Call\",\"scope\":[\"meta.function-call.python\",\"meta.function-call.generic.python\"],\"settings\":{\"foreground\":\"#b2ccd6\"}},{\"name\":\"Punctuations in Python\",\"scope\":[\"punctuation.python\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"Decorator Functions in Python\",\"scope\":[\"entity.name.function.decorator.python\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Python Language Variable\",\"scope\":[\"source.python variable.language.special\"],\"settings\":{\"foreground\":\"#8eace3\"}},{\"name\":\"Python import control keyword\",\"scope\":[\"keyword.control\"],\"settings\":{\"foreground\":\"#c792ea\"}},{\"name\":\"SCSS Variable\",\"scope\":[\"variable.scss\",\"variable.sass\",\"variable.parameter.url.scss\",\"variable.parameter.url.sass\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Variables in SASS At-Rules\",\"scope\":[\"source.css.scss meta.at-rule variable\",\"source.css.sass meta.at-rule variable\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"Variables in SASS At-Rules\",\"scope\":[\"source.css.scss meta.at-rule variable\",\"source.css.sass meta.at-rule variable\"],\"settings\":{\"foreground\":\"#bec5d4\"}},{\"name\":\"Attribute Name for SASS\",\"scope\":[\"meta.attribute-selector.scss entity.other.attribute-name.attribute\",\"meta.attribute-selector.sass entity.other.attribute-name.attribute\"],\"settings\":{\"foreground\":\"#f78c6c\"}},{\"name\":\"Tag names in SASS\",\"scope\":[\"entity.name.tag.scss\",\"entity.name.tag.sass\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"SASS Keyword Other Unit\",\"scope\":[\"keyword.other.unit.scss\",\"keyword.other.unit.sass\"],\"settings\":{\"foreground\":\"#ffeb95\"}},{\"name\":\"TypeScript[React] Variables and Object Properties\",\"scope\":[\"variable.other.readwrite.alias.ts\",\"variable.other.readwrite.alias.tsx\",\"variable.other.readwrite.ts\",\"variable.other.readwrite.tsx\",\"variable.other.object.ts\",\"variable.other.object.tsx\",\"variable.object.property.ts\",\"variable.object.property.tsx\",\"variable.other.ts\",\"variable.other.tsx\",\"variable.tsx\",\"variable.ts\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"TypeScript[React] Entity Name Types\",\"scope\":[\"entity.name.type.ts\",\"entity.name.type.tsx\"],\"settings\":{\"foreground\":\"#ffcb8b\"}},{\"name\":\"TypeScript[React] Node Classes\",\"scope\":[\"support.class.node.ts\",\"support.class.node.tsx\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"TypeScript[React] Entity Name Types as Parameters\",\"scope\":[\"meta.type.parameters.ts entity.name.type\",\"meta.type.parameters.tsx entity.name.type\"],\"settings\":{\"foreground\":\"#889fb2\"}},{\"name\":\"TypeScript[React] Import/Export Punctuations\",\"scope\":[\"meta.import.ts punctuation.definition.block\",\"meta.import.tsx punctuation.definition.block\",\"meta.export.ts punctuation.definition.block\",\"meta.export.tsx punctuation.definition.block\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"TypeScript[React] Punctuation Decorators\",\"scope\":[\"meta.decorator punctuation.decorator.ts\",\"meta.decorator punctuation.decorator.tsx\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"TypeScript[React] Punctuation Decorators\",\"scope\":[\"meta.tag.js meta.jsx.children.tsx\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"YAML Entity Name Tags\",\"scope\":[\"entity.name.tag.yaml\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"JavaScript Variable Other ReadWrite\",\"scope\":[\"variable.other.readwrite.js\",\"variable.parameter\"],\"settings\":{\"foreground\":\"#d7dbe0\"}},{\"name\":\"Support Class Component\",\"scope\":[\"support.class.component.js\",\"support.class.component.tsx\"],\"settings\":{\"foreground\":\"#f78c6c\",\"fontStyle\":\"\"}},{\"name\":\"Text nested in React tags\",\"scope\":[\"meta.jsx.children\",\"meta.jsx.children.js\",\"meta.jsx.children.tsx\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"TypeScript Classes\",\"scope\":[\"meta.class entity.name.type.class.tsx\"],\"settings\":{\"foreground\":\"#ffcb8b\"}},{\"name\":\"TypeScript Entity Name Type\",\"scope\":[\"entity.name.type.tsx\",\"entity.name.type.module.tsx\"],\"settings\":{\"foreground\":\"#ffcb8b\"}},{\"name\":\"TypeScript Class Variable Keyword\",\"scope\":[\"meta.class.ts meta.var.expr.ts storage.type.ts\",\"meta.class.tsx meta.var.expr.tsx storage.type.tsx\"],\"settings\":{\"foreground\":\"#c792ea\"}},{\"name\":\"TypeScript Method Declaration e.g. `constructor`\",\"scope\":[\"meta.method.declaration storage.type.ts\",\"meta.method.declaration storage.type.tsx\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"normalize font style of certain components\",\"scope\":[\"meta.property-list.css meta.property-value.css variable.other.less\",\"meta.property-list.scss variable.scss\",\"meta.property-list.sass variable.sass\",\"meta.brace\",\"keyword.operator.operator\",\"keyword.operator.or.regexp\",\"keyword.operator.expression.in\",\"keyword.operator.relational\",\"keyword.operator.assignment\",\"keyword.operator.comparison\",\"keyword.operator.type\",\"keyword.operator\",\"keyword\",\"punctuation.definintion.string\",\"punctuation\",\"variable.other.readwrite.js\",\"storage.type\",\"source.css\",\"string.quoted\"],\"settings\":{\"fontStyle\":\"\"}}],\"styleOverrides\":{\"frames\":{\"editorBackground\":\"var(--sl-color-gray-6)\",\"terminalBackground\":\"var(--sl-color-gray-6)\",\"editorActiveTabBackground\":\"var(--sl-color-gray-6)\",\"terminalTitlebarDotsForeground\":\"color-mix(in srgb, var(--sl-color-gray-5), transparent 25%)\",\"terminalTitlebarDotsOpacity\":\"0.75\",\"inlineButtonForeground\":\"var(--sl-color-text)\",\"frameBoxShadowCssValue\":\"none\"},\"textMarkers\":{\"markBackground\":\"#ffffff17\",\"markBorderColor\":\"#ffffff40\"}}},{\"name\":\"Night Owl Light\",\"type\":\"light\",\"colors\":{\"focusBorder\":\"#93a1a1\",\"foreground\":\"#403f53\",\"disabledForeground\":\"#61616180\",\"descriptionForeground\":\"#403f53\",\"errorForeground\":\"#403f53\",\"icon.foreground\":\"#424242\",\"contrastActiveBorder\":null,\"contrastBorder\":null,\"textBlockQuote.background\":\"#7f7f7f1a\",\"textBlockQuote.border\":\"#007acc80\",\"textCodeBlock.background\":\"#dcdcdc66\",\"textLink.activeForeground\":\"#006ab1\",\"textLink.foreground\":\"#006ab1\",\"textPreformat.foreground\":\"#a31515\",\"textSeparator.foreground\":\"#0000002e\",\"editor.background\":\"#f6f7f9\",\"editor.foreground\":\"#403f53\",\"editorLineNumber.foreground\":\"#90a7b2\",\"editorLineNumber.activeForeground\":\"#403f53\",\"editorActiveLineNumber.foreground\":\"#0b216f\",\"editor.selectionBackground\":\"#e0e0e0\",\"editor.inactiveSelectionBackground\":\"#e0e0e080\",\"editor.selectionHighlightBackground\":\"#339cec33\",\"editorError.foreground\":\"#e64d49\",\"editorWarning.foreground\":\"#daaa01\",\"editorInfo.foreground\":\"#1a85ff\",\"editorHint.foreground\":\"#6c6c6c\",\"problemsErrorIcon.foreground\":\"#e64d49\",\"problemsWarningIcon.foreground\":\"#daaa01\",\"problemsInfoIcon.foreground\":\"#1a85ff\",\"editor.findMatchBackground\":\"#93a1a16c\",\"editor.findMatchHighlightBackground\":\"#93a1a16c\",\"editor.findRangeHighlightBackground\":\"#7497a633\",\"editorLink.activeForeground\":\"#0000ff\",\"editorLightBulb.foreground\":\"#ddb100\",\"editorLightBulbAutoFix.foreground\":\"#007acc\",\"diffEditor.insertedTextBackground\":\"#9ccc2c40\",\"diffEditor.insertedTextBorder\":null,\"diffEditor.removedTextBackground\":\"#ff000033\",\"diffEditor.removedTextBorder\":null,\"diffEditor.insertedLineBackground\":\"#9bb95533\",\"diffEditor.removedLineBackground\":\"#ff000033\",\"editorStickyScroll.background\":\"#fbfbfb\",\"editorStickyScrollHover.background\":\"#f0f0f0\",\"editorInlayHint.background\":\"#2aa29899\",\"editorInlayHint.foreground\":\"#f0f0f0\",\"editorInlayHint.typeBackground\":\"#2aa29899\",\"editorInlayHint.typeForeground\":\"#f0f0f0\",\"editorInlayHint.parameterBackground\":\"#2aa29899\",\"editorInlayHint.parameterForeground\":\"#f0f0f0\",\"editorPane.background\":\"#fbfbfb\",\"editorGroup.emptyBackground\":null,\"editorGroup.focusedEmptyBorder\":null,\"editorGroupHeader.tabsBackground\":\"var(--sl-color-gray-6)\",\"editorGroupHeader.tabsBorder\":\"color-mix(in srgb, var(--sl-color-gray-5), transparent 25%)\",\"editorGroupHeader.noTabsBackground\":\"#f0f0f0\",\"editorGroupHeader.border\":null,\"editorGroup.border\":\"#f0f0f0\",\"editorGroup.dropBackground\":\"#2677cb2d\",\"editorGroup.dropIntoPromptForeground\":\"#403f53\",\"editorGroup.dropIntoPromptBackground\":\"#f0f0f0\",\"editorGroup.dropIntoPromptBorder\":null,\"sideBySideEditor.horizontalBorder\":\"#f0f0f0\",\"sideBySideEditor.verticalBorder\":\"#f0f0f0\",\"scrollbar.shadow\":\"#cccccc\",\"scrollbarSlider.background\":\"#0000001a\",\"scrollbarSlider.hoverBackground\":\"#00000055\",\"scrollbarSlider.activeBackground\":\"#00000099\",\"panel.background\":\"#f0f0f0\",\"panel.border\":\"#d9d9d9\",\"panelTitle.activeBorder\":\"#424242\",\"panelTitle.activeForeground\":\"#424242\",\"panelTitle.inactiveForeground\":\"#424242bf\",\"panelSectionHeader.background\":\"#80808051\",\"terminal.background\":\"#f6f6f6\",\"widget.shadow\":\"#d9d9d9\",\"editorWidget.background\":\"#f0f0f0\",\"editorWidget.foreground\":\"#403f53\",\"editorWidget.border\":\"#d9d9d9\",\"quickInput.background\":\"#f0f0f0\",\"quickInput.foreground\":\"#403f53\",\"quickInputTitle.background\":\"#0000000f\",\"pickerGroup.foreground\":\"#403f53\",\"pickerGroup.border\":\"#d9d9d9\",\"editor.hoverHighlightBackground\":\"#339cec33\",\"editorHoverWidget.background\":\"#f0f0f0\",\"editorHoverWidget.foreground\":\"#403f53\",\"editorHoverWidget.border\":\"#d9d9d9\",\"editorHoverWidget.statusBarBackground\":\"#e4e4e4\",\"titleBar.activeBackground\":\"var(--sl-color-gray-6)\",\"titleBar.activeForeground\":\"var(--sl-color-text)\",\"titleBar.inactiveBackground\":\"#f0f0f099\",\"titleBar.inactiveForeground\":\"#33333399\",\"titleBar.border\":\"color-mix(in srgb, var(--sl-color-gray-5), transparent 25%)\",\"toolbar.hoverBackground\":\"#b8b8b850\",\"toolbar.activeBackground\":\"#a6a6a650\",\"tab.activeBackground\":\"#f6f6f6\",\"tab.unfocusedActiveBackground\":\"#f6f6f6\",\"tab.inactiveBackground\":\"#f0f0f0\",\"tab.unfocusedInactiveBackground\":\"#f0f0f0\",\"tab.activeForeground\":\"var(--sl-color-text)\",\"tab.inactiveForeground\":\"#403f53\",\"tab.unfocusedActiveForeground\":\"#403f53b3\",\"tab.unfocusedInactiveForeground\":\"#403f5380\",\"tab.hoverBackground\":null,\"tab.unfocusedHoverBackground\":null,\"tab.hoverForeground\":null,\"tab.unfocusedHoverForeground\":null,\"tab.border\":\"#f0f0f0\",\"tab.lastPinnedBorder\":\"#a9a9a9\",\"tab.activeBorder\":\"transparent\",\"tab.unfocusedActiveBorder\":null,\"tab.activeBorderTop\":\"var(--sl-color-accent)\",\"tab.unfocusedActiveBorderTop\":null,\"tab.hoverBorder\":null,\"tab.unfocusedHoverBorder\":null,\"tab.activeModifiedBorder\":\"#2aa298\",\"tab.inactiveModifiedBorder\":\"#93a1a1\",\"tab.unfocusedActiveModifiedBorder\":\"#93a1a1\",\"tab.unfocusedInactiveModifiedBorder\":\"#93a1a1\",\"badge.background\":\"#2aa298\",\"badge.foreground\":\"#f0f0f0\",\"button.background\":\"#2aa298\",\"button.foreground\":\"#f0f0f0\",\"button.border\":null,\"button.separator\":\"#f0f0f066\",\"button.hoverBackground\":\"#22827a\",\"button.secondaryBackground\":\"#5f6a79\",\"button.secondaryForeground\":\"#ffffff\",\"button.secondaryHoverBackground\":\"#4c5561\",\"dropdown.background\":\"#f0f0f0\",\"dropdown.foreground\":\"#403f53\",\"dropdown.border\":\"#d9d9d9\",\"list.activeSelectionBackground\":\"#d3e8f8\",\"list.activeSelectionForeground\":\"#403f53\",\"tree.indentGuidesStroke\":\"#a9a9a9\",\"input.background\":\"#f0f0f0\",\"input.foreground\":\"#403f53\",\"input.placeholderForeground\":\"#93a1a1\",\"inputOption.activeBorder\":\"#2aa298\",\"inputOption.hoverBackground\":\"#b8b8b850\",\"inputOption.activeBackground\":\"#93a1a133\",\"inputOption.activeForeground\":\"#000000\",\"inputValidation.infoBackground\":\"#f0f0f0\",\"inputValidation.infoBorder\":\"#d0d0d0\",\"inputValidation.warningBackground\":\"#daaa01\",\"inputValidation.warningBorder\":\"#e0af02\",\"inputValidation.errorBackground\":\"#f76e6e\",\"inputValidation.errorBorder\":\"#de3d3b\",\"keybindingLabel.background\":\"#dddddd66\",\"keybindingLabel.foreground\":\"#555555\",\"keybindingLabel.border\":\"#cccccc66\",\"keybindingLabel.bottomBorder\":\"#bbbbbb66\",\"menu.foreground\":\"#403f53\",\"menu.background\":\"#f0f0f0\",\"menu.selectionForeground\":\"#403f53\",\"menu.selectionBackground\":\"#d3e8f8\",\"menu.separatorBackground\":\"#d4d4d4\",\"editor.snippetTabstopHighlightBackground\":\"#0a326433\",\"editor.snippetFinalTabstopHighlightBorder\":\"#0a326480\",\"terminal.ansiBlack\":\"#403f53\",\"terminal.ansiRed\":\"#de3d3b\",\"terminal.ansiGreen\":\"#08916a\",\"terminal.ansiYellow\":\"#e0af02\",\"terminal.ansiBlue\":\"#288ed7\",\"terminal.ansiMagenta\":\"#d6438a\",\"terminal.ansiCyan\":\"#2aa298\",\"terminal.ansiWhite\":\"#f0f0f0\",\"terminal.ansiBrightBlack\":\"#403f53\",\"terminal.ansiBrightRed\":\"#de3d3b\",\"terminal.ansiBrightGreen\":\"#08916a\",\"terminal.ansiBrightYellow\":\"#daaa01\",\"terminal.ansiBrightBlue\":\"#288ed7\",\"terminal.ansiBrightMagenta\":\"#d6438a\",\"terminal.ansiBrightCyan\":\"#2aa298\",\"terminal.ansiBrightWhite\":\"#f0f0f0\",\"selection.background\":\"#7a8181ad\",\"notifications.background\":\"#f0f0f0\",\"notifications.foreground\":\"#403f53\",\"notificationLink.foreground\":\"#994cc3\",\"notifications.border\":\"#cccccc\",\"notificationCenter.border\":\"#cccccc\",\"notificationToast.border\":\"#cccccc\",\"notificationCenterHeader.foreground\":\"#403f53\",\"notificationCenterHeader.background\":\"#f0f0f0\",\"input.border\":\"#d9d9d9\",\"progressBar.background\":\"#2aa298\",\"list.inactiveSelectionBackground\":\"#e0e7ea\",\"list.inactiveSelectionForeground\":\"#403f53\",\"list.focusBackground\":\"#d3e8f8\",\"list.hoverBackground\":\"#d3e8f8\",\"list.focusForeground\":\"#403f53\",\"list.hoverForeground\":\"#403f53\",\"list.highlightForeground\":\"#403f53\",\"list.errorForeground\":\"#e64d49\",\"list.warningForeground\":\"#daaa01\",\"activityBar.background\":\"#f0f0f0\",\"activityBar.foreground\":\"#403f53\",\"activityBar.dropBackground\":\"#d0d0d0\",\"activityBarBadge.background\":\"#403f53\",\"activityBarBadge.foreground\":\"#f0f0f0\",\"activityBar.border\":\"#f0f0f0\",\"sideBar.background\":\"#f0f0f0\",\"sideBar.foreground\":\"#403f53\",\"sideBarTitle.foreground\":\"#403f53\",\"sideBar.border\":\"#f0f0f0\",\"editorGroup.background\":\"#f6f6f6\",\"editorCursor.foreground\":\"#90a7b2\",\"editor.wordHighlightBackground\":\"#339cec33\",\"editor.wordHighlightStrongBackground\":\"#007dd659\",\"editor.lineHighlightBackground\":\"#f0f0f0\",\"editor.rangeHighlightBackground\":\"#7497a633\",\"editorWhitespace.foreground\":\"#d9d9d9\",\"editorIndentGuide.background\":\"#d9d9d9\",\"editorCodeLens.foreground\":\"#403f53\",\"editorBracketMatch.background\":\"#d3e8f8\",\"editorBracketMatch.border\":\"#2aa298\",\"editorError.border\":\"#fbfbfb\",\"editorWarning.border\":\"#daaa01\",\"editorGutter.addedBackground\":\"#49d0c5\",\"editorGutter.modifiedBackground\":\"#6fbef6\",\"editorGutter.deletedBackground\":\"#f76e6e\",\"editorRuler.foreground\":\"#d9d9d9\",\"editorOverviewRuler.errorForeground\":\"#e64d49\",\"editorOverviewRuler.warningForeground\":\"#daaa01\",\"editorSuggestWidget.background\":\"#f0f0f0\",\"editorSuggestWidget.foreground\":\"#403f53\",\"editorSuggestWidget.highlightForeground\":\"#403f53\",\"editorSuggestWidget.selectedBackground\":\"#d3e8f8\",\"editorSuggestWidget.border\":\"#d9d9d9\",\"debugExceptionWidget.background\":\"#f0f0f0\",\"debugExceptionWidget.border\":\"#d9d9d9\",\"editorMarkerNavigation.background\":\"#d0d0d0\",\"editorMarkerNavigationError.background\":\"#f76e6e\",\"editorMarkerNavigationWarning.background\":\"#daaa01\",\"debugToolBar.background\":\"#f0f0f0\",\"extensionButton.prominentBackground\":\"#2aa298\",\"extensionButton.prominentForeground\":\"#f0f0f0\",\"statusBar.background\":\"#f0f0f0\",\"statusBar.border\":\"#f0f0f0\",\"statusBar.debuggingBackground\":\"#f0f0f0\",\"statusBar.debuggingForeground\":\"#403f53\",\"statusBar.foreground\":\"#403f53\",\"statusBar.noFolderBackground\":\"#f0f0f0\",\"statusBar.noFolderForeground\":\"#403f53\",\"peekView.border\":\"#d9d9d9\",\"peekViewEditor.background\":\"#f6f6f6\",\"peekViewEditorGutter.background\":\"#f6f6f6\",\"peekViewEditor.matchHighlightBackground\":\"#49d0c5\",\"peekViewResult.background\":\"#f0f0f0\",\"peekViewResult.fileForeground\":\"#403f53\",\"peekViewResult.lineForeground\":\"#403f53\",\"peekViewResult.matchHighlightBackground\":\"#49d0c5\",\"peekViewResult.selectionBackground\":\"#e0e7ea\",\"peekViewResult.selectionForeground\":\"#403f53\",\"peekViewTitle.background\":\"#f0f0f0\",\"peekViewTitleLabel.foreground\":\"#403f53\",\"peekViewTitleDescription.foreground\":\"#403f53\",\"terminal.foreground\":\"#403f53\"},\"fg\":\"#403f53\",\"bg\":\"#f6f7f9\",\"semanticHighlighting\":false,\"settings\":[{\"name\":\"Changed\",\"scope\":[\"markup.changed\",\"meta.diff.header.git\",\"meta.diff.header.from-file\",\"meta.diff.header.to-file\"],\"settings\":{\"foreground\":\"#556484\"}},{\"name\":\"Deleted\",\"scope\":[\"markup.deleted.diff\"],\"settings\":{\"foreground\":\"#ae3c3afd\"}},{\"name\":\"Inserted\",\"scope\":[\"markup.inserted.diff\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Global settings\",\"settings\":{\"background\":\"#011627\",\"foreground\":\"#403f53\"}},{\"name\":\"Comment\",\"scope\":[\"comment\"],\"settings\":{\"foreground\":\"#5f636f\"}},{\"name\":\"String\",\"scope\":[\"string\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"String Quoted\",\"scope\":[\"string.quoted\",\"variable.other.readwrite.js\"],\"settings\":{\"foreground\":\"#984e4d\"}},{\"name\":\"Support Constant Math\",\"scope\":[\"support.constant.math\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Number\",\"scope\":[\"constant.numeric\",\"constant.character.numeric\"],\"settings\":{\"foreground\":\"#aa0982\",\"fontStyle\":\"\"}},{\"name\":\"Built-in constant\",\"scope\":[\"constant.language\",\"punctuation.definition.constant\",\"variable.other.constant\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"User-defined constant\",\"scope\":[\"constant.character\",\"constant.other\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Constant Character Escape\",\"scope\":[\"constant.character.escape\"],\"settings\":{\"foreground\":\"#aa0982\"}},{\"name\":\"RegExp String\",\"scope\":[\"string.regexp\",\"string.regexp keyword.other\"],\"settings\":{\"foreground\":\"#3a688f\"}},{\"name\":\"Comma in functions\",\"scope\":[\"meta.function punctuation.separator.comma\"],\"settings\":{\"foreground\":\"#4d667b\"}},{\"name\":\"Variable\",\"scope\":[\"variable\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Keyword\",\"scope\":[\"punctuation.accessor\",\"keyword\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Storage\",\"scope\":[\"storage\",\"meta.var.expr\",\"meta.class meta.method.declaration meta.var.expr storage.type.js\",\"storage.type.property.js\",\"storage.type.property.ts\",\"storage.type.property.tsx\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Storage type\",\"scope\":[\"storage.type\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Storage type\",\"scope\":[\"storage.type.function.arrow.js\"],\"settings\":{\"fontStyle\":\"\"}},{\"name\":\"Class name\",\"scope\":[\"entity.name.class\",\"meta.class entity.name.type.class\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"Inherited class\",\"scope\":[\"entity.other.inherited-class\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Function name\",\"scope\":[\"entity.name.function\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Meta Tag\",\"scope\":[\"punctuation.definition.tag\",\"meta.tag\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"HTML Tag names\",\"scope\":[\"entity.name.tag\",\"meta.tag.other.html\",\"meta.tag.other.js\",\"meta.tag.other.tsx\",\"entity.name.tag.tsx\",\"entity.name.tag.js\",\"entity.name.tag\",\"meta.tag.js\",\"meta.tag.tsx\",\"meta.tag.html\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Tag attribute\",\"scope\":[\"entity.other.attribute-name\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Entity Name Tag Custom\",\"scope\":[\"entity.name.tag.custom\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Library (function & constant)\",\"scope\":[\"support.function\",\"support.constant\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Support Constant Property Value meta\",\"scope\":[\"support.constant.meta.property-value\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Library class/type\",\"scope\":[\"support.type\",\"support.class\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Support Variable DOM\",\"scope\":[\"support.variable.dom\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Invalid\",\"scope\":[\"invalid\"],\"settings\":{\"foreground\":\"#bb2060\"}},{\"name\":\"Invalid deprecated\",\"scope\":[\"invalid.deprecated\"],\"settings\":{\"foreground\":\"#b23834\"}},{\"name\":\"Keyword Operator\",\"scope\":[\"keyword.operator\"],\"settings\":{\"foreground\":\"#096e72\",\"fontStyle\":\"\"}},{\"name\":\"Keyword Operator Relational\",\"scope\":[\"keyword.operator.relational\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Keyword Operator Assignment\",\"scope\":[\"keyword.operator.assignment\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Keyword Operator Arithmetic\",\"scope\":[\"keyword.operator.arithmetic\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Keyword Operator Bitwise\",\"scope\":[\"keyword.operator.bitwise\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Keyword Operator Increment\",\"scope\":[\"keyword.operator.increment\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Keyword Operator Ternary\",\"scope\":[\"keyword.operator.ternary\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Double-Slashed Comment\",\"scope\":[\"comment.line.double-slash\"],\"settings\":{\"foreground\":\"#5d6376\"}},{\"name\":\"Object\",\"scope\":[\"object\"],\"settings\":{\"foreground\":\"#58656a\"}},{\"name\":\"Null\",\"scope\":[\"constant.language.null\"],\"settings\":{\"foreground\":\"#a24848\"}},{\"name\":\"Meta Brace\",\"scope\":[\"meta.brace\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"Meta Delimiter Period\",\"scope\":[\"meta.delimiter.period\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Punctuation Definition String\",\"scope\":[\"punctuation.definition.string\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"Punctuation Definition String Markdown\",\"scope\":[\"punctuation.definition.string.begin.markdown\"],\"settings\":{\"foreground\":\"#a24848\"}},{\"name\":\"Boolean\",\"scope\":[\"constant.language.boolean\"],\"settings\":{\"foreground\":\"#a24848\"}},{\"name\":\"Object Comma\",\"scope\":[\"object.comma\"],\"settings\":{\"foreground\":\"#646464\"}},{\"name\":\"Variable Parameter Function\",\"scope\":[\"variable.parameter.function\"],\"settings\":{\"foreground\":\"#096e72\",\"fontStyle\":\"\"}},{\"name\":\"Support Type Property Name & entity name tags\",\"scope\":[\"support.type.vendor.property-name\",\"support.constant.vendor.property-value\",\"support.type.property-name\",\"meta.property-list entity.name.tag\"],\"settings\":{\"foreground\":\"#096e72\",\"fontStyle\":\"\"}},{\"name\":\"Entity Name tag reference in stylesheets\",\"scope\":[\"meta.property-list entity.name.tag.reference\"],\"settings\":{\"foreground\":\"#286d70\"}},{\"name\":\"Constant Other Color RGB Value Punctuation Definition Constant\",\"scope\":[\"constant.other.color.rgb-value punctuation.definition.constant\"],\"settings\":{\"foreground\":\"#aa0982\"}},{\"name\":\"Constant Other Color\",\"scope\":[\"constant.other.color\"],\"settings\":{\"foreground\":\"#aa0982\"}},{\"name\":\"Keyword Other Unit\",\"scope\":[\"keyword.other.unit\"],\"settings\":{\"foreground\":\"#aa0982\"}},{\"name\":\"Meta Selector\",\"scope\":[\"meta.selector\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Entity Other Attribute Name Id\",\"scope\":[\"entity.other.attribute-name.id\"],\"settings\":{\"foreground\":\"#aa0982\"}},{\"name\":\"Meta Property Name\",\"scope\":[\"meta.property-name\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Doctypes\",\"scope\":[\"entity.name.tag.doctype\",\"meta.tag.sgml.doctype\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Punctuation Definition Parameters\",\"scope\":[\"punctuation.definition.parameters\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"Keyword Control Operator\",\"scope\":[\"keyword.control.operator\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Keyword Operator Logical\",\"scope\":[\"keyword.operator.logical\"],\"settings\":{\"foreground\":\"#8844ae\",\"fontStyle\":\"\"}},{\"name\":\"Variable Instances\",\"scope\":[\"variable.instance\",\"variable.other.instance\",\"variable.readwrite.instance\",\"variable.other.readwrite.instance\",\"variable.other.property\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Variable Property Other object property\",\"scope\":[\"variable.other.object.property\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"Variable Property Other object\",\"scope\":[\"variable.other.object.js\"],\"settings\":{\"fontStyle\":\"\"}},{\"name\":\"Entity Name Function\",\"scope\":[\"entity.name.function\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Keyword Operator Comparison, imports, returns and Keyword Operator Ruby\",\"scope\":[\"keyword.operator.comparison\",\"keyword.control.flow.js\",\"keyword.control.flow.ts\",\"keyword.control.flow.tsx\",\"keyword.control.ruby\",\"keyword.control.module.ruby\",\"keyword.control.class.ruby\",\"keyword.control.def.ruby\",\"keyword.control.loop.js\",\"keyword.control.loop.ts\",\"keyword.control.import.js\",\"keyword.control.import.ts\",\"keyword.control.import.tsx\",\"keyword.control.from.js\",\"keyword.control.from.ts\",\"keyword.control.from.tsx\",\"keyword.operator.instanceof.js\",\"keyword.operator.expression.instanceof.ts\",\"keyword.operator.expression.instanceof.tsx\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Keyword Control Conditional\",\"scope\":[\"keyword.control.conditional.js\",\"keyword.control.conditional.ts\",\"keyword.control.switch.js\",\"keyword.control.switch.ts\"],\"settings\":{\"foreground\":\"#8844ae\",\"fontStyle\":\"\"}},{\"name\":\"Support Constant, `new` keyword, Special Method Keyword, `debugger`, other keywords\",\"scope\":[\"support.constant\",\"keyword.other.special-method\",\"keyword.other.new\",\"keyword.other.debugger\",\"keyword.control\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Support Function\",\"scope\":[\"support.function\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Invalid Broken\",\"scope\":[\"invalid.broken\"],\"settings\":{\"foreground\":\"#aa0982\"}},{\"name\":\"Invalid Unimplemented\",\"scope\":[\"invalid.unimplemented\"],\"settings\":{\"foreground\":\"#486e26\"}},{\"name\":\"Invalid Illegal\",\"scope\":[\"invalid.illegal\"],\"settings\":{\"foreground\":\"#984e4d\"}},{\"name\":\"Language Variable\",\"scope\":[\"variable.language\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Support Variable Property\",\"scope\":[\"support.variable.property\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Variable Function\",\"scope\":[\"variable.function\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Variable Interpolation\",\"scope\":[\"variable.interpolation\"],\"settings\":{\"foreground\":\"#a64348\"}},{\"name\":\"Meta Function Call\",\"scope\":[\"meta.function-call\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Punctuation Section Embedded\",\"scope\":[\"punctuation.section.embedded\"],\"settings\":{\"foreground\":\"#b23834\"}},{\"name\":\"Punctuation Tweaks\",\"scope\":[\"punctuation.terminator.expression\",\"punctuation.definition.arguments\",\"punctuation.definition.array\",\"punctuation.section.array\",\"meta.array\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"More Punctuation Tweaks\",\"scope\":[\"punctuation.definition.list.begin\",\"punctuation.definition.list.end\",\"punctuation.separator.arguments\",\"punctuation.definition.list\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"Template Strings\",\"scope\":[\"string.template meta.template.expression\"],\"settings\":{\"foreground\":\"#b23834\"}},{\"name\":\"Backtics(``) in Template Strings\",\"scope\":[\"string.template punctuation.definition.string\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"Italics\",\"scope\":[\"italic\"],\"settings\":{\"foreground\":\"#8844ae\",\"fontStyle\":\"italic\"}},{\"name\":\"Bold\",\"scope\":[\"bold\"],\"settings\":{\"foreground\":\"#3b61b0\",\"fontStyle\":\"bold\"}},{\"name\":\"Quote\",\"scope\":[\"quote\"],\"settings\":{\"foreground\":\"#5c6285\"}},{\"name\":\"Raw Code\",\"scope\":[\"raw\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"CoffeScript Variable Assignment\",\"scope\":[\"variable.assignment.coffee\"],\"settings\":{\"foreground\":\"#186e73\"}},{\"name\":\"CoffeScript Parameter Function\",\"scope\":[\"variable.parameter.function.coffee\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"CoffeeScript Assignments\",\"scope\":[\"variable.assignment.coffee\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"C# Readwrite Variables\",\"scope\":[\"variable.other.readwrite.cs\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"C# Classes & Storage types\",\"scope\":[\"entity.name.type.class.cs\",\"storage.type.cs\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"C# Namespaces\",\"scope\":[\"entity.name.type.namespace.cs\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Tag names in Stylesheets\",\"scope\":[\"entity.name.tag.css\",\"entity.name.tag.less\",\"entity.name.tag.custom.css\",\"support.constant.property-value.css\"],\"settings\":{\"foreground\":\"#984e4d\",\"fontStyle\":\"\"}},{\"name\":\"Wildcard(*) selector in Stylesheets\",\"scope\":[\"entity.name.tag.wildcard.css\",\"entity.name.tag.wildcard.less\",\"entity.name.tag.wildcard.scss\",\"entity.name.tag.wildcard.sass\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"CSS Keyword Other Unit\",\"scope\":[\"keyword.other.unit.css\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Attribute Name for CSS\",\"scope\":[\"meta.attribute-selector.css entity.other.attribute-name.attribute\",\"variable.other.readwrite.js\"],\"settings\":{\"foreground\":\"#aa0982\"}},{\"name\":\"Elixir Classes\",\"scope\":[\"source.elixir support.type.elixir\",\"source.elixir meta.module.elixir entity.name.class.elixir\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Elixir Functions\",\"scope\":[\"source.elixir entity.name.function\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Elixir Constants\",\"scope\":[\"source.elixir constant.other.symbol.elixir\",\"source.elixir constant.other.keywords.elixir\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Elixir String Punctuations\",\"scope\":[\"source.elixir punctuation.definition.string\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Elixir\",\"scope\":[\"source.elixir variable.other.readwrite.module.elixir\",\"source.elixir variable.other.readwrite.module.elixir punctuation.definition.variable.elixir\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Elixir Binary Punctuations\",\"scope\":[\"source.elixir .punctuation.binary.elixir\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Closure Constant Keyword\",\"scope\":[\"constant.keyword.clojure\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Go Function Calls\",\"scope\":[\"source.go meta.function-call.go\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Go Keywords\",\"scope\":[\"source.go keyword.package.go\",\"source.go keyword.import.go\",\"source.go keyword.function.go\",\"source.go keyword.type.go\",\"source.go keyword.struct.go\",\"source.go keyword.interface.go\",\"source.go keyword.const.go\",\"source.go keyword.var.go\",\"source.go keyword.map.go\",\"source.go keyword.channel.go\",\"source.go keyword.control.go\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Go Constants e.g. nil, string format (%s, %d, etc.)\",\"scope\":[\"source.go constant.language.go\",\"source.go constant.other.placeholder.go\"],\"settings\":{\"foreground\":\"#a24848\"}},{\"name\":\"C++ Functions\",\"scope\":[\"entity.name.function.preprocessor.cpp\",\"entity.scope.name.cpp\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"C++ Meta Namespace\",\"scope\":[\"meta.namespace-block.cpp\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"C++ Language Primitive Storage\",\"scope\":[\"storage.type.language.primitive.cpp\"],\"settings\":{\"foreground\":\"#a24848\"}},{\"name\":\"C++ Preprocessor Macro\",\"scope\":[\"meta.preprocessor.macro.cpp\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"C++ Variable Parameter\",\"scope\":[\"variable.parameter\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"Powershell Variables\",\"scope\":[\"variable.other.readwrite.powershell\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Powershell Function\",\"scope\":[\"support.function.powershell\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"ID Attribute Name in HTML\",\"scope\":[\"entity.other.attribute-name.id.html\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"HTML Punctuation Definition Tag\",\"scope\":[\"punctuation.definition.tag.html\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"HTML Doctype\",\"scope\":[\"meta.tag.sgml.doctype.html\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"JavaScript Classes\",\"scope\":[\"meta.class entity.name.type.class.js\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"JavaScript Method Declaration e.g. `constructor`\",\"scope\":[\"meta.method.declaration storage.type.js\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"JavaScript Terminator\",\"scope\":[\"terminator.js\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"JavaScript Meta Punctuation Definition\",\"scope\":[\"meta.js punctuation.definition.js\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"Entity Names in Code Documentations\",\"scope\":[\"entity.name.type.instance.jsdoc\",\"entity.name.type.instance.phpdoc\"],\"settings\":{\"foreground\":\"#4d667b\"}},{\"name\":\"Other Variables in Code Documentations\",\"scope\":[\"variable.other.jsdoc\",\"variable.other.phpdoc\"],\"settings\":{\"foreground\":\"#3e697c\"}},{\"name\":\"JavaScript module imports and exports\",\"scope\":[\"variable.other.meta.import.js\",\"meta.import.js variable.other\",\"variable.other.meta.export.js\",\"meta.export.js variable.other\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"JavaScript Variable Parameter Function\",\"scope\":[\"variable.parameter.function.js\"],\"settings\":{\"foreground\":\"#555ea2\"}},{\"name\":\"JavaScript[React] Variable Other Object\",\"scope\":[\"variable.other.object.js\",\"variable.other.object.jsx\",\"variable.object.property.js\",\"variable.object.property.jsx\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"JavaScript Variables\",\"scope\":[\"variable.js\",\"variable.other.js\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"JavaScript Entity Name Type\",\"scope\":[\"entity.name.type.js\",\"entity.name.type.module.js\"],\"settings\":{\"foreground\":\"#111111\",\"fontStyle\":\"\"}},{\"name\":\"JavaScript Support Classes\",\"scope\":[\"support.class.js\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"JSON Property Names\",\"scope\":[\"support.type.property-name.json\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"JSON Support Constants\",\"scope\":[\"support.constant.json\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"JSON Property values (string)\",\"scope\":[\"meta.structure.dictionary.value.json string.quoted.double\"],\"settings\":{\"foreground\":\"#7c5686\"}},{\"name\":\"Strings in JSON values\",\"scope\":[\"string.quoted.double.json punctuation.definition.string.json\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Specific JSON Property values like null\",\"scope\":[\"meta.structure.dictionary.json meta.structure.dictionary.value constant.language\"],\"settings\":{\"foreground\":\"#a24848\"}},{\"name\":\"JavaScript Other Variable\",\"scope\":[\"variable.other.object.js\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Ruby Variables\",\"scope\":[\"variable.other.ruby\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"Ruby Class\",\"scope\":[\"entity.name.type.class.ruby\"],\"settings\":{\"foreground\":\"#984e4d\"}},{\"name\":\"Ruby Hashkeys\",\"scope\":[\"constant.language.symbol.hashkey.ruby\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Ruby Symbols\",\"scope\":[\"constant.language.symbol.ruby\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"LESS Tag names\",\"scope\":[\"entity.name.tag.less\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"LESS Keyword Other Unit\",\"scope\":[\"keyword.other.unit.css\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Attribute Name for LESS\",\"scope\":[\"meta.attribute-selector.less entity.other.attribute-name.attribute\"],\"settings\":{\"foreground\":\"#aa0982\"}},{\"name\":\"Markdown Headings\",\"scope\":[\"markup.heading.markdown\",\"markup.heading.setext.1.markdown\",\"markup.heading.setext.2.markdown\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Markdown Italics\",\"scope\":[\"markup.italic.markdown\"],\"settings\":{\"foreground\":\"#8844ae\",\"fontStyle\":\"italic\"}},{\"name\":\"Markdown Bold\",\"scope\":[\"markup.bold.markdown\"],\"settings\":{\"foreground\":\"#3b61b0\",\"fontStyle\":\"bold\"}},{\"name\":\"Markdown Quote + others\",\"scope\":[\"markup.quote.markdown\"],\"settings\":{\"foreground\":\"#5c6285\"}},{\"name\":\"Markdown Raw Code + others\",\"scope\":[\"markup.inline.raw.markdown\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Markdown Links\",\"scope\":[\"markup.underline.link.markdown\",\"markup.underline.link.image.markdown\"],\"settings\":{\"foreground\":\"#954f5a\",\"fontStyle\":\"underline\"}},{\"name\":\"Markdown Link Title and Description\",\"scope\":[\"string.other.link.title.markdown\",\"string.other.link.description.markdown\"],\"settings\":{\"foreground\":\"#403f53\",\"fontStyle\":\"underline\"}},{\"name\":\"Markdown Punctuation\",\"scope\":[\"punctuation.definition.string.markdown\",\"punctuation.definition.string.begin.markdown\",\"punctuation.definition.string.end.markdown\",\"meta.link.inline.markdown punctuation.definition.string\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Markdown MetaData Punctuation\",\"scope\":[\"punctuation.definition.metadata.markdown\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Markdown List Punctuation\",\"scope\":[\"beginning.punctuation.definition.list.markdown\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Markdown Inline Raw String\",\"scope\":[\"markup.inline.raw.string.markdown\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"PHP Variables\",\"scope\":[\"variable.other.php\",\"variable.other.property.php\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"Support Classes in PHP\",\"scope\":[\"support.class.php\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"Punctuations in PHP function calls\",\"scope\":[\"meta.function-call.php punctuation\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"PHP Global Variables\",\"scope\":[\"variable.other.global.php\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Declaration Punctuation in PHP Global Variables\",\"scope\":[\"variable.other.global.php punctuation.definition.variable\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Language Constants in Python\",\"scope\":[\"constant.language.python\"],\"settings\":{\"foreground\":\"#a24848\"}},{\"name\":\"Python Function Parameter and Arguments\",\"scope\":[\"variable.parameter.function.python\",\"meta.function-call.arguments.python\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Python Function Call\",\"scope\":[\"meta.function-call.python\",\"meta.function-call.generic.python\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Punctuations in Python\",\"scope\":[\"punctuation.python\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"Decorator Functions in Python\",\"scope\":[\"entity.name.function.decorator.python\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Python Language Variable\",\"scope\":[\"source.python variable.language.special\"],\"settings\":{\"foreground\":\"#aa0982\"}},{\"name\":\"Python import control keyword\",\"scope\":[\"keyword.control\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"SCSS Variable\",\"scope\":[\"variable.scss\",\"variable.sass\",\"variable.parameter.url.scss\",\"variable.parameter.url.sass\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Variables in SASS At-Rules\",\"scope\":[\"source.css.scss meta.at-rule variable\",\"source.css.sass meta.at-rule variable\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Variables in SASS At-Rules\",\"scope\":[\"source.css.scss meta.at-rule variable\",\"source.css.sass meta.at-rule variable\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"Attribute Name for SASS\",\"scope\":[\"meta.attribute-selector.scss entity.other.attribute-name.attribute\",\"meta.attribute-selector.sass entity.other.attribute-name.attribute\"],\"settings\":{\"foreground\":\"#aa0982\"}},{\"name\":\"Tag names in SASS\",\"scope\":[\"entity.name.tag.scss\",\"entity.name.tag.sass\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"SASS Keyword Other Unit\",\"scope\":[\"keyword.other.unit.scss\",\"keyword.other.unit.sass\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"TypeScript[React] Variables and Object Properties\",\"scope\":[\"variable.other.readwrite.alias.ts\",\"variable.other.readwrite.alias.tsx\",\"variable.other.readwrite.ts\",\"variable.other.readwrite.tsx\",\"variable.other.object.ts\",\"variable.other.object.tsx\",\"variable.object.property.ts\",\"variable.object.property.tsx\",\"variable.other.ts\",\"variable.other.tsx\",\"variable.tsx\",\"variable.ts\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"TypeScript[React] Entity Name Types\",\"scope\":[\"entity.name.type.ts\",\"entity.name.type.tsx\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"TypeScript[React] Node Classes\",\"scope\":[\"support.class.node.ts\",\"support.class.node.tsx\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"TypeScript[React] Entity Name Types as Parameters\",\"scope\":[\"meta.type.parameters.ts entity.name.type\",\"meta.type.parameters.tsx entity.name.type\"],\"settings\":{\"foreground\":\"#4d667b\"}},{\"name\":\"TypeScript[React] Import/Export Punctuations\",\"scope\":[\"meta.import.ts punctuation.definition.block\",\"meta.import.tsx punctuation.definition.block\",\"meta.export.ts punctuation.definition.block\",\"meta.export.tsx punctuation.definition.block\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"TypeScript[React] Punctuation Decorators\",\"scope\":[\"meta.decorator punctuation.decorator.ts\",\"meta.decorator punctuation.decorator.tsx\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"TypeScript[React] Punctuation Decorators\",\"scope\":[\"meta.tag.js meta.jsx.children.tsx\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"YAML Entity Name Tags\",\"scope\":[\"entity.name.tag.yaml\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"JavaScript Variable Other ReadWrite\",\"scope\":[\"variable.other.readwrite.js\",\"variable.parameter\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"Support Class Component\",\"scope\":[\"support.class.component.js\",\"support.class.component.tsx\"],\"settings\":{\"foreground\":\"#aa0982\",\"fontStyle\":\"\"}},{\"name\":\"Text nested in React tags\",\"scope\":[\"meta.jsx.children\",\"meta.jsx.children.js\",\"meta.jsx.children.tsx\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"TypeScript Classes\",\"scope\":[\"meta.class entity.name.type.class.tsx\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"TypeScript Entity Name Type\",\"scope\":[\"entity.name.type.tsx\",\"entity.name.type.module.tsx\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"TypeScript Class Variable Keyword\",\"scope\":[\"meta.class.ts meta.var.expr.ts storage.type.ts\",\"meta.class.tsx meta.var.expr.tsx storage.type.tsx\"],\"settings\":{\"foreground\":\"#76578b\"}},{\"name\":\"TypeScript Method Declaration e.g. `constructor`\",\"scope\":[\"meta.method.declaration storage.type.ts\",\"meta.method.declaration storage.type.tsx\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"normalize font style of certain components\",\"scope\":[\"meta.property-list.css meta.property-value.css variable.other.less\",\"meta.property-list.scss variable.scss\",\"meta.property-list.sass variable.sass\",\"meta.brace\",\"keyword.operator.operator\",\"keyword.operator.or.regexp\",\"keyword.operator.expression.in\",\"keyword.operator.relational\",\"keyword.operator.assignment\",\"keyword.operator.comparison\",\"keyword.operator.type\",\"keyword.operator\",\"keyword\",\"punctuation.definintion.string\",\"punctuation\",\"variable.other.readwrite.js\",\"storage.type\",\"source.css\",\"string.quoted\"],\"settings\":{\"fontStyle\":\"\"}}],\"styleOverrides\":{\"frames\":{\"editorBackground\":\"var(--sl-color-gray-7)\",\"terminalBackground\":\"var(--sl-color-gray-7)\",\"editorActiveTabBackground\":\"var(--sl-color-gray-7)\",\"terminalTitlebarDotsForeground\":\"color-mix(in srgb, var(--sl-color-gray-5), transparent 25%)\",\"terminalTitlebarDotsOpacity\":\"0.75\",\"inlineButtonForeground\":\"var(--sl-color-text)\",\"frameBoxShadowCssValue\":\"none\"},\"textMarkers\":{\"markBackground\":\"#0000001a\",\"markBorderColor\":\"#00000055\"}}}],\"defaultLocale\":\"en\",\"cascadeLayer\":\"starlight.components\",\"styleOverrides\":{\"borderRadius\":\"0px\",\"borderWidth\":\"1px\",\"codePaddingBlock\":\"0.75rem\",\"codePaddingInline\":\"1rem\",\"codeFontFamily\":\"var(--__sl-font-mono)\",\"codeFontSize\":\"var(--sl-text-code)\",\"codeLineHeight\":\"var(--sl-line-height)\",\"uiFontFamily\":\"var(--__sl-font)\",\"textMarkers\":{\"lineDiffIndicatorMarginLeft\":\"0.25rem\",\"defaultChroma\":\"45\",\"backgroundOpacity\":\"60%\"}},\"plugins\":[{\"name\":\"Starlight Plugin\",\"hooks\":{}},{\"name\":\"astro-expressive-code\",\"hooks\":{}}]}]],\"remarkRehype\":{},\"gfm\":true,\"smartypants\":true},\"security\":{\"checkOrigin\":true,\"allowedDomains\":[]},\"env\":{\"schema\":{},\"validateSecrets\":false},\"experimental\":{\"clientPrerender\":false,\"contentIntellisense\":false,\"headingIdCompat\":false,\"preserveScriptOrder\":false,\"liveContentCollections\":false,\"csp\":false,\"staticImportMetaEnv\":false,\"chromeDevtoolsWorkspace\":false,\"failOnPrerenderConflict\":false,\"svgo\":false},\"legacy\":{\"collections\":false},\"prefetch\":{\"prefetchAll\":true},\"i18n\":{\"defaultLocale\":\"en\",\"locales\":[\"en\"],\"routing\":{\"prefixDefaultLocale\":false,\"redirectToDefaultLocale\":false,\"fallbackType\":\"redirect\"}}}","docs",["Map",11,12,25,26,36,37,47,48,58,59,85,86,96,97,107,108,118,119,129,130,140,141,151,152,162,163,173,174,184,185,195,196,206,207,217,218,228,229,239,240,250,251,261,262,272,273,283,284,294,295,305,306,316,317,327,328,338,339,349,350,360,361,371,372,382,383,393,394,404,405,415,416,426,427,437,438,448,449,459,460,470,471],"contributing",{"id":11,"data":13,"body":22,"filePath":23,"digest":24,"deferredRender":16},{"title":14,"description":15,"editUrl":16,"head":17,"template":18,"sidebar":19,"pagefind":16,"draft":20},"Contributing","How to contribute to the Runtime Environment Protocol project.",true,[],"doc",{"hidden":20,"attrs":21},false,{},"import { Aside } from '@astrojs/starlight/components';\n\n## Getting started\n\n### Prerequisites\n\n- **Node.js** >= 20.0.0\n- **pnpm** >= 9.0.0 — `npm install -g pnpm`\n- **Go** >= 1.24.5 (for gateway development only)\n\n### Setup\n\n```bash\ngit clone https://github.com/ruachtech/rep.git\ncd rep\npnpm install\npnpm run build\npnpm run test\n```\n\nFor gateway:\n```bash\ncd gateway\ngo test -race ./...\n```\n\n## Project structure\n\n```\nrep/\n├── spec/ # Protocol specification documents\n├── schema/ # JSON schemas for payload and manifest\n├── gateway/ # Go reference implementation (stdlib only)\n├── sdk/ # @rep-protocol/sdk (zero runtime deps)\n├── cli/ # @rep-protocol/cli\n├── adapters/ # React, Vue, Svelte adapters\n├── codemod/ # Migration tool\n├── docs/ # This documentation site (Astro/Starlight)\n└── examples/ # Example applications\n```\n\n## Commit conventions\n\nThis project uses [Conventional Commits](https://www.conventionalcommits.org/). Every commit to `main` must follow this format:\n\n```\n\u003Ctype>(\u003Cscope>): \u003Cdescription>\n\n[optional body]\n```\n\n### Types\n\n| Type | Effect | Example |\n|---|---|---|\n| `fix` | Patch release | `fix(sdk): handle missing meta field` |\n| `feat` | Minor release | `feat(gateway): add poll mode for hot reload` |\n| `feat!` | Major release | `feat!(sdk)!: rename getSecure to decrypt` |\n| `docs` | No release | `docs(spec): clarify SRI verification` |\n| `chore` | No release | `chore: update dev dependencies` |\n| `refactor` | No release | `refactor(gateway): extract inject middleware` |\n| `test` | No release | `test(sdk): add hot reload tests` |\n| `perf` | No release | `perf(gateway): reduce allocation in inject` |\n\n### Scopes\n\n`sdk`, `gateway`, `cli`, `react`, `vue`, `svelte`, `codemod`, `spec`, `docs`\n\n## Code style\n\n### Go (Gateway)\n\n- **Standard library only.** No third-party dependencies.\n- Structured logging via `log/slog`\n- Error wrapping: `fmt.Errorf(\"context: %w\", err)`\n- No `init()` functions\n- Tests use stdlib only (`testing`, `net/http/httptest`)\n- Use `t.Setenv()` for env var tests (never `os.Setenv` directly)\n- Run with `-race` flag\n\n### TypeScript (SDK, CLI, Adapters)\n\n- Zero runtime dependencies for the SDK\n- Vitest + jsdom for testing\n- `vi.resetModules()` before each SDK test (because `_init()` runs on module load)\n- DOM cleanup in `beforeEach`\n\n## Testing\n\n```bash\n# All TypeScript packages\npnpm run test\n\n# Gateway (from gateway/)\ngo test -race ./...\n\n# Specific package\npnpm --filter @rep-protocol/sdk run test\n```\n\n## Release process\n\nReleases are automated via [release-please](https://github.com/googleapis/release-please):\n\n1. Push conventional commits to `main`\n2. Release-please creates/updates a Release PR with version bumps and changelogs\n3. Merging the Release PR triggers npm publishing for all packages\n4. The gateway is versioned independently via `gateway/VERSION` and released through GoReleaser\n\n\u003CAside type=\"caution\">\n Do not manually bump versions in `package.json` or create release tags. The automation handles this.\n\u003C/Aside>\n\n## PR guidelines\n\n- Branch from `main`\n- Keep PRs focused on a single change\n- Include tests for new functionality\n- Use squash-merge with a conventional commit message","src/content/docs/contributing.mdx","bdae584b684babbb","concepts/how-it-works",{"id":25,"data":27,"body":33,"filePath":34,"digest":35,"deferredRender":16},{"title":28,"description":29,"editUrl":16,"head":30,"template":18,"sidebar":31,"pagefind":16,"draft":20},"How REP Works","Architecture overview — gateway modes, startup sequence, and HTML injection.",[],{"hidden":20,"attrs":32},{},"import { Aside } from '@astrojs/starlight/components';\n\n## Architecture\n\nREP introduces a lightweight gateway process between the browser and your static file server. The gateway reads `REP_*` environment variables at startup, classifies them, and injects a `\u003Cscript>` tag into every HTML response.\n\n```\nContainer boot:\n 1. Gateway reads all REP_* environment variables (+ optional .env file)\n 2. Classifies into PUBLIC / SENSITIVE / SERVER tiers (by prefix)\n 3. Runs guardrails (entropy scan, known format detection) on PUBLIC vars\n 4. Generates ephemeral AES-256 key + HMAC secret (in-memory only)\n 5. Encrypts SENSITIVE vars → base64 blob\n 6. Computes HMAC integrity token\n 7. Pre-renders \u003Cscript id=\"__rep__\" type=\"application/json\"> tag\n```\n\n## Gateway modes\n\n### Proxy mode (recommended)\n\nThe gateway sits in front of an existing web server (nginx, Caddy, etc.) and intercepts HTML responses:\n\n```\nBrowser → [REP Gateway :8080] → [nginx / Caddy :80]\n```\n\nFor `text/html` responses, the gateway injects the payload before `\u003C/head>`. All other responses pass through unmodified.\n\n### Embedded mode\n\nThe gateway serves static files directly — no upstream server needed:\n\n```\nBrowser → [REP Gateway :8080] (serves files from --static-dir)\n```\n\nThis enables `FROM scratch` Docker containers: just the gateway binary and your `dist/` folder. No nginx, no Node.js, no shell.\n\n## Startup sequence\n\nThe gateway performs these steps in order at process start:\n\n1. Load `.env` file if `--env-file` is specified (existing env vars take precedence)\n2. Read all `REP_*` environment variables\n3. Classify each into PUBLIC, SENSITIVE, or SERVER tier\n4. Validate name uniqueness after prefix stripping\n5. Load and validate `.rep.yaml` manifest if `--manifest` is specified\n6. Run secret detection guardrails on PUBLIC variables\n7. Exit with error if `--strict` and guardrails triggered\n8. Generate ephemeral master key, derive AES-256 key via HKDF-SHA256\n9. Encrypt all SENSITIVE values with AES-256-GCM\n10. Compute HMAC-SHA256 integrity token\n11. Construct the payload JSON\n12. Register HTTP handlers (injection, session key, health, hot reload)\n13. Start accepting connections\n14. Log startup summary\n\n\u003CAside type=\"tip\">\n Ephemeral keys are regenerated on every restart. A gateway restart invalidates all previously issued session keys and re-encrypts the sensitive blob. This is by design — key compromise requires process compromise.\n\u003C/Aside>\n\n## HTML injection\n\nWhen the gateway intercepts an HTML response, it injects a `\u003Cscript>` block:\n\n```html\n\u003Cscript id=\"__rep__\" type=\"application/json\"\n data-rep-version=\"0.1.0\"\n data-rep-integrity=\"sha256-{base64_hash}\">\n{\n \"public\": {\n \"API_URL\": \"https://api.example.com\",\n \"FEATURE_FLAGS\": \"dark-mode,beta\"\n },\n \"sensitive\": \"{base64_aes_gcm_blob}\",\n \"_meta\": {\n \"version\": \"0.1.0\",\n \"injected_at\": \"2026-02-18T14:30:00.000Z\",\n \"integrity\": \"hmac-sha256:{base64_signature}\",\n \"key_endpoint\": \"/rep/session-key\",\n \"hot_reload\": \"/rep/changes\",\n \"ttl\": 0\n }\n}\n\u003C/script>\n```\n\n**Injection rules:**\n\n1. Insert before `\u003C/head>` (preferred)\n2. If no `\u003C/head>`, insert after `\u003Chead>`\n3. If neither exists, prepend to the response body\n\n\u003CAside type=\"caution\">\n `type=\"application/json\"` is critical — it prevents the browser from executing the tag. This is inert data, not executable JavaScript. Never change this to `text/javascript`.\n\u003C/Aside>\n\n## SDK initialization\n\nThe SDK reads the injected payload **synchronously** on import:\n\n1. Locate `\u003Cscript id=\"__rep__\">` in the DOM\n2. Parse the JSON content\n3. Verify `data-rep-integrity` against the content (async, non-blocking)\n4. Freeze the `public` object\n5. Set internal state flags (`_available`, `_tampered`)\n\nNo network calls happen during initialization. `rep.get()` is available immediately — before your first component renders.\n\n## Gateway endpoints\n\nThe gateway exposes three endpoints alongside HTML injection:\n\n| Endpoint | Purpose |\n|---|---|\n| `GET /rep/health` | Health check — variable counts, guardrail status, uptime |\n| `GET /rep/session-key` | Short-lived AES decryption key for SENSITIVE variables |\n| `GET /rep/changes` | SSE stream for hot reload (if enabled) |\n\nSee the [Gateway Endpoints reference](/reference/gateway-endpoints/) for full details.","src/content/docs/concepts/how-it-works.mdx","f91489b3baf50987","concepts/variable-classification",{"id":36,"data":38,"body":44,"filePath":45,"digest":46,"deferredRender":16},{"title":39,"description":40,"editUrl":16,"head":41,"template":18,"sidebar":42,"pagefind":16,"draft":20},"Variable Classification","The three-tier security model — PUBLIC, SENSITIVE, and SERVER variables.",[],{"hidden":20,"attrs":43},{},"import { Aside } from '@astrojs/starlight/components';\n\nREP classifies every environment variable into one of three security tiers based on its prefix. This is the foundational design decision — it forces an explicit security choice for every variable.\n\n## The three tiers\n\n| Prefix | Tier | Behaviour | SDK Access |\n|---|---|---|---|\n| `REP_PUBLIC_*` | **PUBLIC** | Plaintext JSON in page source | `rep.get('KEY')` (sync) |\n| `REP_SENSITIVE_*` | **SENSITIVE** | AES-256-GCM encrypted blob | `await rep.getSecure('KEY')` |\n| `REP_SERVER_*` | **SERVER** | Never sent to client | N/A |\n| `REP_GATEWAY_*` | *(config)* | Gateway configuration, not app vars | N/A |\n\nVariables without a `REP_` prefix are ignored by the gateway entirely. This prevents accidental exposure of system variables like `PATH`, `HOME`, or database credentials.\n\n## Classification rules\n\n1. Classification is determined **exclusively by prefix**. There is no override mechanism.\n2. The gateway will not inject any variable without a `REP_` prefix.\n3. Prefixes are stripped before injection: `REP_PUBLIC_API_URL` becomes `API_URL` in the payload.\n4. Names must be unique after stripping. If `REP_PUBLIC_API_URL` and `REP_SENSITIVE_API_URL` both exist, the gateway refuses to start.\n\n## Decision tree\n\nUse this guide to classify each variable:\n\n```\nDoes the value contain credentials, tokens, or keys?\n├── Yes → Does it need to reach the browser at all?\n│ ├── No → REP_SERVER_*\n│ └── Yes → REP_SENSITIVE_*\n└── No → Is it configuration the app needs at runtime?\n ├── Yes → REP_PUBLIC_*\n └── No → REP_SERVER_* or don't use REP_ prefix\n```\n\n## Common misclassifications\n\n| Variable | Wrong Tier | Correct Tier | Reason |\n|---|---|---|---|\n| `DATABASE_URL` | PUBLIC | **SERVER** | Database credentials must never reach the browser |\n| `STRIPE_SECRET_KEY` | SENSITIVE | **SERVER** | Secret keys should never be decryptable client-side |\n| `STRIPE_PUBLISHABLE_KEY` | SERVER | **PUBLIC** | Publishable keys are designed to be public |\n| `API_URL` | SENSITIVE | **PUBLIC** | API endpoints are visible in network requests anyway |\n| `JWT_SECRET` | SENSITIVE | **SERVER** | Signing secrets must stay server-side |\n| `OAUTH_CLIENT_ID` | SERVER | **SENSITIVE** | Client IDs are needed browser-side but not public |\n| `ANALYTICS_WRITE_KEY` | PUBLIC | **SENSITIVE** | Write keys allow data ingestion — encrypt them |\n| `FEATURE_FLAGS` | SENSITIVE | **PUBLIC** | Feature flag names have no security value |\n| `SENTRY_DSN` | PUBLIC | **SENSITIVE** | DSNs contain project-specific ingestion endpoints |\n| `APP_VERSION` | SENSITIVE | **PUBLIC** | Version strings are informational, not secret |\n| `INTERNAL_SERVICE_TOKEN` | SENSITIVE | **SERVER** | Service-to-service tokens must not reach the browser |\n| `CDN_BASE_URL` | SENSITIVE | **PUBLIC** | CDN URLs are visible in every asset request |\n\n\u003CAside type=\"tip\">\n When in doubt, start with the most restrictive tier (SERVER) and relax only when you can articulate why the browser needs the value.\n\u003C/Aside>\n\n## Automatic secret detection (guardrails)\n\nAt startup, the gateway scans all `REP_PUBLIC_*` values for patterns indicating potential misclassification:\n\n| Detection | Description |\n|---|---|\n| **Shannon entropy > 4.5** | Random-looking strings typical of API keys and tokens |\n| **Known key formats** | AWS keys (`AKIA...`), JWTs (`eyJ...`), GitHub tokens (`ghp_...`), Stripe keys (`sk_live_...`), private keys (`-----BEGIN`) |\n| **Length anomalies** | Strings > 64 characters that may be encoded secrets |\n\nWhen a potential misclassification is detected:\n\n- The gateway logs a **WARNING** with the variable name (never the value)\n- In `--strict` mode, the gateway refuses to start\n- The gateway never silently changes classification — you must fix the prefix\n\n\u003CAside type=\"caution\">\n Guardrails use heuristics, not certainty. A low-entropy secret (like a short password) may not trigger detection. Use `--strict` mode in production and review your `.rep.yaml` manifest in code review.\n\u003C/Aside>\n\n## Manifest validation\n\nWhen a `.rep.yaml` manifest is present, the gateway can validate at startup that:\n\n- All required variables are present in the environment\n- Variable values match declared types (url, number, enum, etc.)\n- Variables are in the correct tier\n\nSee the [Manifest guide](/guides/manifest/) for details.","src/content/docs/concepts/variable-classification.mdx","f2021196e99b810e","quick-start",{"id":47,"data":49,"body":55,"filePath":56,"digest":57,"deferredRender":16},{"title":50,"description":51,"editUrl":16,"head":52,"template":18,"sidebar":53,"pagefind":16,"draft":20},"Quick Start","Get REP running in under 5 minutes — no manifest file, no configuration step.",[],{"hidden":20,"attrs":54},{},"import { Steps, Tabs, TabItem, Aside } from '@astrojs/starlight/components';\n\nThe `.rep.yaml` manifest is entirely optional. The gateway works with just environment variables — the naming convention **is** the configuration.\n\n\u003CSteps>\n\n1. **Rename your environment variables**\n\n Add the `REP_PUBLIC_`, `REP_SENSITIVE_`, or `REP_SERVER_` prefix to classify each variable:\n\n ```bash\n # Before (Vite) → After (REP)\n VITE_API_URL → REP_PUBLIC_API_URL\n VITE_FEATURE_FLAGS → REP_PUBLIC_FEATURE_FLAGS\n\n # Before (CRA) → After (REP)\n REACT_APP_API_URL → REP_PUBLIC_API_URL\n\n # Should be encrypted in the browser\n REACT_APP_ANALYTICS_KEY → REP_SENSITIVE_ANALYTICS_KEY\n\n # Should never reach the browser\n DB_PASSWORD → REP_SERVER_DB_PASSWORD\n ```\n\n2. **Install the SDK and update your code**\n\n ```bash\n npm install @rep-protocol/sdk\n ```\n\n Replace your `import.meta.env.*` / `process.env.*` reads:\n\n ```typescript\n import { rep } from '@rep-protocol/sdk';\n\n // Was: import.meta.env.VITE_API_URL\n const apiUrl = rep.get('API_URL');\n\n // With a default value for local development\n const apiUrl = rep.get('API_URL', 'http://localhost:3001');\n\n // Sensitive variable — encrypted, decrypted on demand\n const key = await rep.getSecure('ANALYTICS_KEY');\n ```\n\n `rep.get()` is **synchronous** — the SDK reads the payload from the DOM on import, before your first component renders. No loading state needed.\n\n3. **Build your app (nothing changes)**\n\n ```bash\n npm run build\n ```\n\n The output is now environment-agnostic. The same `dist/` folder goes to every environment.\n\n4. **Run the gateway**\n\n \u003CTabs>\n \u003CTabItem label=\"Binary\">\n ```bash\n REP_PUBLIC_API_URL=https://api.example.com \\\n REP_PUBLIC_FEATURE_FLAGS=dark-mode,new-checkout \\\n REP_SENSITIVE_ANALYTICS_KEY=ak_live_abc123 \\\n ./rep-gateway --mode embedded --static-dir ./dist\n ```\n \u003C/TabItem>\n \u003CTabItem label=\"Docker\">\n ```bash\n docker run --rm -p 8080:8080 \\\n -e REP_PUBLIC_API_URL=https://api.example.com \\\n -e REP_PUBLIC_FEATURE_FLAGS=dark-mode,new-checkout \\\n -e REP_SENSITIVE_ANALYTICS_KEY=ak_live_abc123 \\\n -v \"$(pwd)/dist:/static:ro\" \\\n ghcr.io/ruachtech/rep/gateway:latest \\\n --mode embedded --static-dir /static\n ```\n \u003C/TabItem>\n \u003C/Tabs>\n\n Open `http://localhost:8080` — the gateway injected your variables into every HTML response.\n\n\u003C/Steps>\n\n## Changing config without rebuilding\n\nStop the gateway. Restart with different values. Same `dist/` folder, different runtime config:\n\n```bash\nREP_PUBLIC_API_URL=https://api.prod.example.com \\\nREP_PUBLIC_FEATURE_FLAGS=dark-mode \\\nREP_SENSITIVE_ANALYTICS_KEY=ak_live_prod_xyz \\\n./rep-gateway --mode embedded --static-dir ./dist\n```\n\nNo rebuild. No new container image. This is the core proposition.\n\n## Proxy mode\n\nIf you already have nginx, Caddy, or another static file server, run the gateway in front of it instead:\n\n```bash\nREP_PUBLIC_API_URL=https://api.example.com \\\n./rep-gateway --mode proxy --upstream localhost:80\n```\n\nThe gateway intercepts `text/html` responses, injects the `\u003Cscript>` tag, and passes everything else through unmodified.\n\n## What's next?\n\n- [Add a manifest file](/guides/manifest/) for startup validation and TypeScript type generation\n- [Framework-specific guides](/frameworks/react/) for React, Vue, and Svelte adapters\n- [Deploy with Docker](/deployment/docker-embedded/) for production containers\n- [Variable classification](/concepts/variable-classification/) to understand the three-tier security model","src/content/docs/quick-start.mdx","9ef19fc715dfa8e5","index",{"id":58,"data":60,"body":82,"filePath":83,"digest":84,"deferredRender":16},{"title":61,"description":62,"editUrl":16,"head":63,"template":64,"hero":65,"sidebar":80,"pagefind":16,"draft":20},"REP — Runtime Environment Protocol","Build once. Deploy anywhere. Securely. The missing security layer for environment variables in browser applications.",[],"splash",{"tagline":66,"actions":67},"The missing security layer for environment variables in browser applications. Build once, deploy anywhere — with encryption, integrity verification, and secret detection built in.",[68,74],{"text":50,"link":69,"variant":70,"icon":71},"/quick-start/","primary",{"type":72,"name":73},"icon","right-arrow",{"text":75,"link":76,"variant":77,"icon":78},"View on GitHub","https://github.com/ruachtech/rep","minimal",{"type":72,"name":79},"external",{"hidden":20,"attrs":81},{},"import { Card, CardGrid, Tabs, TabItem } from '@astrojs/starlight/components';\n\n\u003Cdiv style=\"max-width: 720px; margin: 0 auto 2rem;\">\n \u003Cvideo controls playsinline preload=\"metadata\" style=\"width: 100%; border-radius: 8px; border: 1px solid var(--sl-color-gray-5);\">\n \u003Csource src=\"https://github.com/RuachTech/rep/releases/download/v0.1.3/rep-gateway-demo.mp4\" type=\"video/mp4\" />\n \u003C/video>\n \u003Cp style=\"text-align: center; font-size: 0.85rem; color: var(--sl-color-gray-3); margin-top: 0.5rem;\">Hot reload and feature flags — no rebuild, no redeploy.\u003C/p>\n\u003C/div>\n\n## The Problem\n\nEvery frontend framework resolves environment variables at **build time** — `process.env.API_URL` becomes a hardcoded string in your JavaScript bundle. This creates problems that compound in production:\n\n\u003CCardGrid>\n \u003CCard title=\"One build per environment\" icon=\"warning\">\n Your staging bundle can't be promoted to production. You rebuild for every environment, breaking the container promise of \"build once, run anywhere.\"\n \u003C/Card>\n \u003CCard title=\"No security model\" icon=\"error\">\n All variables are treated equally. API keys, analytics tokens, and public URLs all end up as plaintext strings in your bundle — visible to anyone who opens View Source.\n \u003C/Card>\n \u003CCard title=\"Config changes require redeployment\" icon=\"close\">\n Need to rotate an API key or flip a feature flag? Rebuild, re-test, redeploy. Even if your backend can hot-swap config, your frontend can't.\n \u003C/Card>\n \u003CCard title=\"Secrets leak into build logs\" icon=\"error\">\n CI/CD pipelines pass secrets as build args. They appear in Docker layer history, build logs, and cached artifacts — creating supply chain risk.\n \u003C/Card>\n\u003C/CardGrid>\n\n## What REP Does\n\nREP is an open protocol and reference implementation that **decouples environment variables from the build process entirely**. A lightweight gateway reads variables at startup, classifies them by security tier, encrypts sensitive values, and injects them into HTML responses — whether you're running containers, static builds, or local development.\n\n\u003CCardGrid>\n \u003CCard title=\"Three Security Tiers\" icon=\"approve-check\">\n **PUBLIC** — plaintext, synchronous access. **SENSITIVE** — AES-256-GCM encrypted, decrypted on demand. **SERVER** — never sent to the browser. Classification by naming convention eliminates ambiguity.\n \u003C/Card>\n \u003CCard title=\"Encryption + Integrity\" icon=\"lock\">\n Sensitive variables are encrypted with ephemeral keys generated at startup. Every payload carries an HMAC-SHA256 integrity token and SRI hash to detect tampering in transit.\n \u003C/Card>\n \u003CCard title=\"Secret Detection Guardrails\" icon=\"shield\">\n Entropy analysis and known-format matching (AWS keys, JWTs, Stripe keys, GitHub tokens) catch misclassified secrets before they reach the browser. Strict mode makes warnings into hard failures.\n \u003C/Card>\n \u003CCard title=\"Hot Reload via SSE\" icon=\"refresh\">\n Config changes push to every connected browser via Server-Sent Events. No page reload, no redeployment. Edit an env file or rotate a ConfigMap — the UI updates live.\n \u003C/Card>\n\u003C/CardGrid>\n\n## Works Everywhere\n\nREP operates at the **infrastructure layer** — no build-tool plugins, no framework coupling. It works with any frontend stack that produces HTML.\n\n\u003CCardGrid>\n \u003CCard title=\"Containers\" icon=\"rocket\">\n Reverse proxy mode sits in front of nginx, caddy, or any upstream. Embedded mode serves static files directly from a `FROM scratch` image (~3MB).\n \u003C/Card>\n \u003CCard title=\"Static Builds\" icon=\"document\">\n Build your app once with `npm run build`. The gateway injects config into the static HTML at serve time — same artifact for every environment.\n \u003C/Card>\n \u003CCard title=\"Local Development\" icon=\"terminal\">\n The CLI wraps the gateway for local dev. Proxy your Vite/webpack dev server with hot reload, or serve a production build with live config changes.\n \u003C/Card>\n \u003CCard title=\"Any Framework\" icon=\"puzzle\">\n First-party adapters for React, Vue, and Svelte. A zero-dependency TypeScript SDK works with anything — Angular, vanilla JS, or your custom setup.\n \u003C/Card>\n\u003C/CardGrid>\n\n## Compared to Existing Solutions\n\n| Approach | Security Tiers | Encrypted Vars | Integrity Check | Hot Reload | Standalone Binary |\n|---|:---:|:---:|:---:|:---:|:---:|\n| `envsubst` / `sed` on bundles | -- | -- | -- | -- | -- |\n| Fetch `/config.json` at runtime | -- | -- | -- | -- | -- |\n| `window.__ENV__` via shell script | -- | -- | -- | -- | -- |\n| Build-tool plugins (dotenv, etc.) | -- | -- | -- | -- | -- |\n| **REP** | **3-tier** | **AES-256-GCM** | **HMAC + SRI** | **SSE** | **~3MB Go** |\n\n## Quick Example\n\n\u003CTabs>\n \u003CTabItem label=\"SDK Usage\">\n```typescript\nimport { rep } from '@rep-protocol/sdk';\n\n// Synchronous — no loading state needed\nconst apiUrl = rep.get('API_URL');\nconst flags = rep.get('FEATURE_FLAGS');\n\n// Encrypted — decrypted on demand via session key\nconst key = await rep.getSecure('ANALYTICS_KEY');\n\n// Hot reload — react to config changes live\nrep.onChange('FEATURE_FLAGS', (newValue) => {\n console.log('Flags updated:', newValue);\n});\n```\n \u003C/TabItem>\n \u003CTabItem label=\"Docker Compose\">\n```yaml\n# Same image, different config — true build-once, deploy-anywhere\nservices:\n frontend-staging:\n image: myapp:latest\n environment:\n REP_PUBLIC_API_URL: \"https://api.staging.example.com\"\n REP_SENSITIVE_ANALYTICS_KEY: \"UA-XXXXX-staging\"\n REP_SERVER_INTERNAL_SECRET: \"never-reaches-browser\"\n\n frontend-prod:\n image: myapp:latest # SAME IMAGE\n environment:\n REP_PUBLIC_API_URL: \"https://api.example.com\"\n REP_SENSITIVE_ANALYTICS_KEY: \"UA-XXXXX-prod\"\n REP_SERVER_INTERNAL_SECRET: \"also-never-reaches-browser\"\n```\n \u003C/TabItem>\n \u003CTabItem label=\"Variable Tiers\">\n```bash\n# PUBLIC — plaintext in page source, rep.get()\nREP_PUBLIC_API_URL=https://api.example.com\n\n# SENSITIVE — AES-256-GCM encrypted, await rep.getSecure()\nREP_SENSITIVE_ANALYTICS_KEY=UA-12345-1\n\n# SERVER — never leaves the gateway process\nREP_SERVER_DB_PASSWORD=never-reaches-browser\n```\n \u003C/TabItem>\n\u003C/Tabs>\n\n## Project Components\n\n\u003CCardGrid>\n \u003CCard title=\"Gateway\" icon=\"rocket\">\n Go binary (~3MB). Zero dependencies. `FROM scratch` compatible. Proxy or embedded mode.\n \u003C/Card>\n \u003CCard title=\"SDK\" icon=\"document\">\n TypeScript. Zero runtime deps. ~1.5KB gzipped. Synchronous `get()`, async `getSecure()`.\n \u003C/Card>\n \u003CCard title=\"CLI\" icon=\"terminal\">\n `rep validate`, `rep typegen`, `rep lint`, `rep dev`. Full development workflow.\n \u003C/Card>\n \u003CCard title=\"Adapters\" icon=\"puzzle\">\n First-party React, Vue, and Svelte adapters with hot-reload-aware hooks and stores.\n \u003C/Card>\n\u003C/CardGrid>\n\n## Specification Status\n\n| Document | Status | Version |\n|---|---|---|\n| [REP-RFC-0001](/spec/rfc-0001/) | Active | 0.1.0 |\n| [Security Model](/spec/security-model/) | Active | 0.1.0 |\n| [Conformance](/spec/conformance/) | Active | 0.1.0 |\n\nSpecification documents are licensed under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/). Code is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0).","src/content/docs/index.mdx","9b4fd6f8ac0e05e7","concepts/security-model",{"id":85,"data":87,"body":93,"filePath":94,"digest":95,"deferredRender":16},{"title":88,"description":89,"editUrl":16,"head":90,"template":18,"sidebar":91,"pagefind":16,"draft":20},"Security Model","Threat analysis, trust boundaries, and what REP protects against (and what it doesn't).",[],{"hidden":20,"attrs":92},{},"import { Aside } from '@astrojs/starlight/components';\n\nREP does not claim to make browser-side configuration \"secure\" in an absolute sense. It makes it **significantly more secure than the status quo** while making security trade-offs explicit and auditable.\n\n## Fundamental axiom\n\n> **Anything that reaches the browser is ultimately accessible to the user and to any code running in the browser context.**\n\nREP cannot change this axiom. What it does is:\n\n1. **Prevent accidental exposure** through classification and guardrails\n2. **Raise the bar for casual extraction** through encryption of sensitive values\n3. **Make intentional access auditable** through session key logging and rate limiting\n4. **Eliminate unnecessary exposure** through the SERVER tier\n5. **Detect tampering** through integrity verification\n\n## Trust boundaries\n\n```\n┌────────────────────────────────────────────────────────────────┐\n│ TRUSTED ZONE │\n│ │\n│ Orchestrator (K8s, ECS) │\n│ ↓ │\n│ REP Gateway (Go binary) → Static File Server (nginx) │\n│ │\n│ REP_SERVER_* vars NEVER cross this boundary │\n├────────────────────────────────────────────────────────────────┤\n│ TRANSIT (HTTPS/TLS) │\n├────────────────────────────────────────────────────────────────┤\n│ UNTRUSTED ZONE │\n│ │\n│ Browser: Application Code, REP SDK, Extensions, DevTools │\n│ Everything here is visible to the user │\n└────────────────────────────────────────────────────────────────┘\n```\n\n## Threat analysis\n\n### T1: Accidental secret exposure (HIGH)\n\nA developer prefixes a database password with `REP_PUBLIC_` instead of `REP_SERVER_`.\n\n**Mitigations:**\n- Naming convention forces an explicit classification decision\n- Guardrail scanning detects secret-like patterns in PUBLIC values\n- `--strict` mode makes guardrail warnings into hard failures\n- Manifest validation confirms variables match their declared tier\n\n**Residual risk:** Low-entropy secrets may not trigger heuristic detection.\n\n### T2: XSS exfiltration of public variables (MEDIUM)\n\nAn attacker achieves XSS and reads public config values.\n\n**Mitigations:** Largely out of scope — PUBLIC variables are by definition visible to browser code. REP helps indirectly by forcing classification (so truly sensitive values aren't in PUBLIC) and providing the SERVER tier for values that don't belong in the browser at all.\n\n### T3: XSS exfiltration of sensitive variables (MEDIUM-HIGH)\n\nAn attacker achieves XSS and attempts to read encrypted SENSITIVE values.\n\n**Mitigations:**\n- Values are AES-256-GCM encrypted at rest in the HTML\n- Decryption requires fetching a session key from `/rep/session-key`\n- Session keys are single-use (prevents replay)\n- Session keys expire in 30 seconds\n- Endpoint is rate-limited (10 req/min per IP)\n- CORS validates the requesting origin\n- All key issuances are audit-logged\n\n**Residual risk:** A sophisticated same-origin XSS attack could fetch a session key and decrypt values. REP raises the bar from \"read the DOM\" to \"make an authenticated, rate-limited, logged API call.\"\n\n### T4: MITM payload tampering (HIGH)\n\nAn attacker modifies the injected `\u003Cscript>` tag in transit.\n\n**Mitigations:**\n- HMAC-SHA256 integrity token computed over the canonical payload\n- SRI hash on the `data-rep-integrity` attribute\n- SDK sets `_tampered` flag if integrity check fails\n- `verify()` function exposes tamper state to the application\n\n**Limitation:** If the attacker can rewrite the entire script block (including the integrity attribute), verification cannot detect this. HTTPS is the primary defense against MITM.\n\n### T5: Environment variable leakage via gateway (CRITICAL)\n\nThe gateway process itself is compromised, leaking SERVER-tier variables.\n\n**Mitigations:**\n- Strict prefix filtering — only `REP_*` variables are processed\n- No shell execution within the gateway\n- No filesystem writes\n- Minimal dependencies (zero external Go deps)\n- Compatible with read-only filesystems\n- Static binary, `FROM scratch` compatible\n- Non-root user execution (UID 65534)\n\n### T6: DoS via session key endpoint (LOW)\n\nAn attacker floods `/rep/session-key` to exhaust resources.\n\n**Mitigations:** Rate limiting (10 req/min/IP), minimal computation per request, automatic key expiry cleanup, separate health port for monitoring.\n\n### T7: Supply chain attack on SDK (HIGH)\n\nThe SDK package is compromised to exfiltrate variables.\n\n**Mitigations:** Minimal surface (<2KB, ~150 lines), zero runtime dependencies, lockfile pinning, npm provenance, self-hostable (vendor the file).\n\n## Hardening recommendations\n\n### Production gateway configuration\n\n```bash\nREP_GATEWAY_STRICT=true # Fail on guardrail warnings\nREP_GATEWAY_ALLOWED_ORIGINS=https://app.example.com\nREP_GATEWAY_LOG_FORMAT=json # Structured logging for SIEM\n```\n\n### Minimal Docker image\n\n```dockerfile\nFROM scratch\nCOPY rep-gateway /rep-gateway\nCOPY dist/ /static/\nUSER 65534:65534\nENTRYPOINT [\"/rep-gateway\"]\nCMD [\"--mode\", \"embedded\", \"--static-dir\", \"/static\", \"--strict\"]\n```\n\n### Content Security Policy\n\n```\nContent-Security-Policy:\n default-src 'self';\n script-src 'self';\n connect-src 'self';\n style-src 'self' 'unsafe-inline';\n```\n\nThe `\u003Cscript id=\"__rep__\" type=\"application/json\">` tag is inert data — it does not execute. No `script-src` exception or nonce is needed for the REP payload.\n\n### Monitoring\n\n| Log Event | Level | Alert On |\n|---|---|---|\n| `rep.guardrail.warning` | WARN | Any occurrence in production |\n| `rep.session_key.issued` | INFO | Rate exceeding baseline |\n| `rep.session_key.rejected` | WARN | Any occurrence |\n| `rep.session_key.rate_limited` | WARN | Sustained bursts |\n| `rep.config.changed` | INFO | Unexpected changes |\n| `rep.inject.html` | DEBUG | N/A |\n\n## Known limitations\n\n1. **No client-side HMAC verification.** The HMAC secret never leaves the gateway. The SDK verifies via SRI hash only.\n2. **Sensitive tier is defense-in-depth, not absolute.** A determined attacker with XSS can eventually decrypt sensitive values.\n3. **No key rotation without restart.** Ephemeral keys are generated once at startup.\n4. **Guardrails are heuristic.** They catch common patterns but cannot detect all secrets.\n5. **Hot reload has an eventual consistency window.** Between config change and SSE delivery, clients see stale values.\n\nFor the full formal analysis, see the [Security Model specification](/spec/security-model/).","src/content/docs/concepts/security-model.mdx","2f14d5039615f826","deployment/ci-cd",{"id":96,"data":98,"body":104,"filePath":105,"digest":106,"deferredRender":16},{"title":99,"description":100,"editUrl":16,"head":101,"template":18,"sidebar":102,"pagefind":16,"draft":20},"CI/CD Pipeline","Build once, deploy everywhere — same image across staging and production.",[],{"hidden":20,"attrs":103},{},"import { Aside } from '@astrojs/starlight/components';\n\n## The fundamental shift\n\nWith REP, your CI/CD pipeline changes from \"build per environment\" to \"build once, promote everywhere\":\n\n**Before REP:**\n```\nBuild (staging) → Test → Deploy to staging\nBuild (prod) → Deploy to prod ← DIFFERENT BINARY\n```\n\n**After REP:**\n```\nBuild (once) → Test → Deploy to staging (with staging env vars)\n → Promote SAME IMAGE to prod (with prod env vars)\n```\n\nThe image that passed your tests is the **exact same binary** that goes to production.\n\n## GitHub Actions example\n\n```yaml\nname: Build and Deploy\n\non:\n push:\n branches: [main]\n\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n\n - name: Build frontend (environment-agnostic)\n run: |\n docker build -t myapp:${{ github.sha }} .\n # No --build-arg for API_URL, no .env files\n # The image is environment-agnostic\n\n - name: Push to registry\n run: docker push ghcr.io/myorg/myapp:${{ github.sha }}\n\n test:\n needs: build\n runs-on: ubuntu-latest\n steps:\n - name: Run E2E tests\n run: |\n docker run -d --name test-app \\\n -e REP_PUBLIC_API_URL=https://api.test.example.com \\\n -e REP_PUBLIC_FEATURE_FLAGS=all \\\n -p 8080:8080 \\\n ghcr.io/myorg/myapp:${{ github.sha }}\n\n npx playwright test --base-url http://localhost:8080\n\n deploy-staging:\n needs: test\n runs-on: ubuntu-latest\n steps:\n - name: Deploy to staging\n run: |\n kubectl set image deployment/frontend \\\n frontend=ghcr.io/myorg/myapp:${{ github.sha }}\n # ConfigMap provides staging REP_PUBLIC_* and REP_SENSITIVE_* vars\n\n deploy-prod:\n needs: deploy-staging\n runs-on: ubuntu-latest\n environment: production # Requires manual approval\n steps:\n - name: Promote SAME IMAGE to production\n run: |\n # SAME SHA — exact same binary that was tested\n kubectl set image deployment/frontend \\\n frontend=ghcr.io/myorg/myapp:${{ github.sha }}\n # Different ConfigMap provides prod REP_* vars\n```\n\n## Manifest validation in CI\n\nAdd a validation step to catch configuration errors early:\n\n```yaml\n validate:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - name: Validate REP manifest\n run: npx @rep-protocol/cli validate --manifest .rep.yaml\n```\n\nThis checks that:\n- The manifest schema is valid\n- No naming collisions after prefix stripping\n- All type constraints are properly declared\n\n## Bundle scanning in CI\n\nScan built bundles for accidentally leaked secrets:\n\n```yaml\n lint:\n needs: build\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - name: Build\n run: npm ci && npm run build\n - name: Scan for secrets\n run: npx @rep-protocol/cli lint --dir ./dist --strict\n```\n\n\u003CAside type=\"tip\">\n Combine `rep validate` and `rep lint` as required CI checks. Validation catches schema issues at commit time; lint catches leaked secrets at build time.\n\u003C/Aside>","src/content/docs/deployment/ci-cd.mdx","2a9fefbc20b16899","concepts/hot-reload",{"id":107,"data":109,"body":115,"filePath":116,"digest":117,"deferredRender":16},{"title":110,"description":111,"editUrl":16,"head":112,"template":18,"sidebar":113,"pagefind":16,"draft":20},"Hot Reload","Live config updates via Server-Sent Events — no page reload, no redeployment.",[],{"hidden":20,"attrs":114},{},"import { Aside } from '@astrojs/starlight/components';\n\nHot reload is an optional feature that pushes configuration changes to the browser via Server-Sent Events (SSE). When enabled, the gateway monitors for environment variable changes and broadcasts updates to connected clients.\n\n## Enabling hot reload\n\n```bash\nrep-gateway --hot-reload --mode embedded --static-dir ./dist\n```\n\nOr via environment variable:\n\n```bash\nREP_GATEWAY_HOT_RELOAD=true\n```\n\n## SSE event format\n\nThe gateway exposes `GET /rep/changes` as an SSE endpoint:\n\n```\nevent: rep:config:update\ndata: {\"key\": \"FEATURE_FLAGS\", \"tier\": \"public\", \"value\": \"dark-mode,ai-assist\"}\nid: 1708267830000\n\nevent: rep:config:delete\ndata: {\"key\": \"DEPRECATED_FLAG\", \"tier\": \"public\"}\nid: 1708267831000\n```\n\n### Event types\n\n| Event | Description |\n|---|---|\n| `rep:config:update` | A variable's value changed or a new variable was added |\n| `rep:config:delete` | A variable was removed |\n\n## Change detection modes\n\nThe gateway supports three modes for detecting environment variable changes:\n\n### File watch (recommended for Kubernetes)\n\nWatches a mounted ConfigMap or secrets volume for file changes:\n\n```bash\nrep-gateway --hot-reload --hot-reload-mode file_watch\n```\n\nIdeal for Kubernetes deployments where ConfigMaps are mounted as volumes. Changes are detected within seconds of a ConfigMap update.\n\n### Signal mode\n\nRe-reads the environment on receipt of `SIGHUP`:\n\n```bash\n# In another terminal or from a process manager:\nkill -HUP $(pidof rep-gateway)\n```\n\nUseful for traditional deployments where an orchestrator can signal the gateway.\n\n### Poll mode\n\nPeriodically re-reads the config source:\n\n```bash\nrep-gateway --hot-reload --hot-reload-mode poll --hot-reload-poll-interval 30s\n```\n\nSimplest mode, but introduces a polling interval delay.\n\n## SDK integration\n\n### Lazy connection\n\nThe SDK does **not** establish an SSE connection on import. It connects lazily when `onChange()` or `onAnyChange()` is first called:\n\n```typescript\nimport { rep } from '@rep-protocol/sdk';\n\n// No SSE connection yet\n\nconst unsub = rep.onChange('FEATURE_FLAGS', (newValue, oldValue) => {\n console.log(`Flags changed: ${oldValue} → ${newValue}`);\n});\n// SSE connection established now\n\nunsub();\n// If no other listeners remain, SSE connection is closed\n```\n\nThis is a deliberate design choice — applications that don't use hot reload pay zero network cost.\n\n### Framework adapters\n\nAll framework adapters automatically subscribe to hot reload:\n\n- **React:** `useRep()` subscribes in `useEffect`, unsubscribes on unmount\n- **Vue:** `useRep()` subscribes in `setup()`, unsubscribes via `onUnmounted`\n- **Svelte:** `repStore()` subscribes when the store has subscribers, unsubscribes when the last subscriber leaves\n\n\u003CAside>\n `useRepSecure()`, `useRepSecure()` (Vue), and `repSecureStore()` do **not** subscribe to hot reload. Sensitive variables require re-fetching a session key, which is too expensive for automatic updates.\n\u003C/Aside>\n\n### Handling reconnection\n\nSSE has built-in reconnection. If the connection drops, the browser automatically reconnects after a brief delay. The `id` field in SSE events allows the gateway to replay missed events.\n\n## Kubernetes hot reload\n\nIn Kubernetes, combine ConfigMap volumes with file watch mode:\n\n```yaml\napiVersion: apps/v1\nkind: Deployment\nspec:\n template:\n spec:\n containers:\n - name: app\n image: myapp:latest\n args:\n - \"--hot-reload\"\n - \"--hot-reload-mode=file_watch\"\n volumeMounts:\n - name: config\n mountPath: /config\n volumes:\n - name: config\n configMap:\n name: app-config\n```\n\nWhen the ConfigMap is updated (`kubectl apply`), Kubernetes refreshes the mounted volume, the gateway detects the change, and connected browsers receive the update — all without a pod restart.\n\n\u003CAside type=\"caution\">\n Hot reload has an eventual consistency window. Between the config change and SSE delivery, clients see stale values. This window is typically sub-second for file watch mode but can be up to the poll interval for poll mode.\n\u003C/Aside>","src/content/docs/concepts/hot-reload.mdx","d5654cdd39f1b4e4","concepts/wire-format",{"id":118,"data":120,"body":126,"filePath":127,"digest":128,"deferredRender":16},{"title":121,"description":122,"editUrl":16,"head":123,"template":18,"sidebar":124,"pagefind":16,"draft":20},"Wire Format","Payload JSON structure, encrypted blob format, and integrity verification.",[],{"hidden":20,"attrs":125},{},"import { Aside } from '@astrojs/starlight/components';\n\n## Payload structure\n\nThe gateway injects a `\u003Cscript>` tag into HTML responses containing the REP payload as JSON:\n\n```html\n\u003Cscript id=\"__rep__\" type=\"application/json\"\n data-rep-version=\"0.1.0\"\n data-rep-integrity=\"sha256-{base64_hash}\">\n{\n \"public\": { ... },\n \"sensitive\": \"...\",\n \"_meta\": { ... }\n}\n\u003C/script>\n```\n\n### Fields\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `public` | `object` | Yes | Key-value map of PUBLIC tier variables (strings only) |\n| `sensitive` | `string` | No | Base64-encoded AES-256-GCM encrypted blob |\n| `_meta` | `object` | Yes | Payload metadata |\n\n### `_meta` fields\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `version` | `string` | Yes | Protocol version (semver) |\n| `injected_at` | `string` | Yes | RFC 3339 timestamp of injection |\n| `integrity` | `string` | Yes | `hmac-sha256:{base64_signature}` |\n| `key_endpoint` | `string` | No | Path to session key endpoint (`/rep/session-key`) |\n| `hot_reload` | `string` | No | Path to SSE endpoint (`/rep/changes`) |\n| `ttl` | `integer` | No | Cache TTL in seconds (0 = no cache) |\n\n### SRI attribute\n\nThe `data-rep-integrity` attribute contains a SHA-256 hash of the raw JSON content:\n\n```\ndata-rep-integrity=\"sha256-{base64_of_sha256_digest}\"\n```\n\nThe SDK verifies this using the Web Crypto API, comparing the hash against the actual `textContent` of the `\u003Cscript>` element (byte-for-byte matching the gateway's computation).\n\n## Encrypted blob format\n\nWhen SENSITIVE variables are present, they are encrypted into a single binary blob:\n\n```\n[12 bytes nonce][ciphertext][16 bytes GCM auth tag]\n```\n\n| Segment | Size | Description |\n|---|---|---|\n| Nonce | 12 bytes | Random IV for AES-256-GCM |\n| Ciphertext | Variable | Encrypted JSON of all sensitive key-value pairs |\n| Auth tag | 16 bytes | GCM authentication tag |\n\nThe entire blob is base64-encoded in the `sensitive` field.\n\n### Key derivation (HKDF-SHA256)\n\nThe encryption key is derived from an ephemeral master key using HKDF (RFC 5869):\n\n1. Gateway generates a 32-byte random master key at startup\n2. Extract: `PRK = HMAC-SHA256(salt=\"rep-v1\", IKM=master_key)`\n3. Expand: `derived_key = HKDF-Expand(PRK, info=\"rep-session-key\", L=32)`\n4. The derived key (not the master key) is issued via `/rep/session-key`\n5. Both master and derived keys exist only in memory — never stored to disk\n\n### Decryption (client-side)\n\nThe SDK decrypts sensitive variables in `getSecure()`:\n\n1. Fetch the session key from `/rep/session-key`\n2. Base64-decode the session key\n3. Base64-decode the `sensitive` blob\n4. Extract: first 12 bytes = nonce, last 16 bytes = auth tag, middle = ciphertext\n5. Decrypt with AES-256-GCM using `_meta.integrity` as Additional Authenticated Data (AAD)\n6. Parse the resulting JSON to get all sensitive key-value pairs\n7. Cache all decrypted values in memory for the page lifetime\n\n\u003CAside type=\"tip\">\n All sensitive variables are decrypted together on the first `getSecure()` call. Subsequent calls for different keys return from the in-memory cache without additional network requests.\n\u003C/Aside>\n\n## Integrity verification\n\n### HMAC-SHA256\n\nThe integrity token is computed over a canonicalized representation of the payload:\n\n1. Construct a JSON object with sorted keys, no whitespace\n2. Include both `public` and `sensitive` fields\n3. Compute: `HMAC-SHA256(secret, canonical_json)`\n4. Encode as: `hmac-sha256:{base64_signature}`\n\nThe HMAC secret exists only in the gateway's memory and is never transmitted. The SDK cannot verify the HMAC — this is by design. The HMAC enables server-side verification by other infrastructure components.\n\n### SRI verification (client-side)\n\nThe SDK verifies payload integrity using the `data-rep-integrity` attribute:\n\n1. Read the raw `textContent` of the `\u003Cscript>` element\n2. Compute SHA-256 using the Web Crypto API\n3. Compare with the `data-rep-integrity` attribute value\n4. Set `_tampered` flag if mismatch\n\nThis detects modifications to the payload content after injection (e.g., by a browser extension or CDN).\n\n## JSON schemas\n\nThe payload and manifest schemas are available as JSON Schema (Draft 2020-12):\n\n- [Payload schema](/schema/rep-payload.schema.json)\n- [Manifest schema](/schema/rep-manifest.schema.json)","src/content/docs/concepts/wire-format.mdx","b39643b664dea4e3","deployment/docker-compose",{"id":129,"data":131,"body":137,"filePath":138,"digest":139,"deferredRender":16},{"title":132,"description":133,"editUrl":16,"head":134,"template":18,"sidebar":135,"pagefind":16,"draft":20},"Docker Compose","Local multi-service setup with Docker Compose — same image, different config.",[],{"hidden":20,"attrs":136},{},"## Basic setup\n\n```yaml\n# docker-compose.yml\nservices:\n frontend:\n build: .\n ports:\n - \"8080:8080\"\n environment:\n REP_PUBLIC_API_URL: \"http://localhost:3000\"\n REP_PUBLIC_FEATURE_FLAGS: \"dark-mode,debug\"\n REP_SENSITIVE_ANALYTICS_KEY: \"test-key\"\n```\n\n## Same image, multiple environments\n\nThe core value proposition — one image, different config per environment:\n\n```yaml\nservices:\n frontend-staging:\n image: myapp:latest\n ports:\n - \"8080:8080\"\n environment:\n REP_PUBLIC_API_URL: \"https://api.staging.example.com\"\n REP_PUBLIC_FEATURE_FLAGS: \"dark-mode,beta-checkout\"\n REP_PUBLIC_ENV_NAME: \"staging\"\n REP_SENSITIVE_ANALYTICS_KEY: \"UA-XXXXX-staging\"\n REP_SERVER_INTERNAL_SECRET: \"staging-secret\"\n\n frontend-prod:\n image: myapp:latest # SAME IMAGE\n ports:\n - \"8081:8080\"\n environment:\n REP_PUBLIC_API_URL: \"https://api.example.com\"\n REP_PUBLIC_FEATURE_FLAGS: \"dark-mode\"\n REP_PUBLIC_ENV_NAME: \"production\"\n REP_SENSITIVE_ANALYTICS_KEY: \"UA-XXXXX-prod\"\n REP_SERVER_INTERNAL_SECRET: \"prod-secret\"\n REP_GATEWAY_STRICT: \"true\"\n```\n\n## With .env files\n\n```yaml\nservices:\n frontend:\n build: .\n ports:\n - \"8080:8080\"\n env_file:\n - .env.local\n```\n\n`.env.local`:\n```bash\nREP_PUBLIC_API_URL=http://localhost:3000\nREP_PUBLIC_FEATURE_FLAGS=dark-mode,debug\nREP_SENSITIVE_ANALYTICS_KEY=test-key-123\n```\n\n## Development with proxy mode\n\nRun the gateway as a proxy to your Vite dev server:\n\n```yaml\nservices:\n vite:\n build:\n context: .\n target: dev\n command: npm run dev -- --host\n ports:\n - \"5173:5173\"\n volumes:\n - .:/app\n - /app/node_modules\n\n gateway:\n image: ghcr.io/ruachtech/rep/gateway:latest\n ports:\n - \"8080:8080\"\n environment:\n REP_PUBLIC_API_URL: \"http://localhost:3000\"\n REP_GATEWAY_MODE: \"proxy\"\n REP_GATEWAY_UPSTREAM: \"vite:5173\"\n REP_GATEWAY_HOT_RELOAD: \"true\"\n depends_on:\n - vite\n```\n\nAccess the app at `http://localhost:8080` to see REP-injected variables.\n\n## Full stack example\n\n```yaml\nservices:\n frontend:\n build: .\n ports:\n - \"8080:8080\"\n environment:\n REP_PUBLIC_API_URL: \"http://localhost:3000\"\n REP_PUBLIC_FEATURE_FLAGS: \"all\"\n REP_SENSITIVE_ANALYTICS_KEY: \"test-key\"\n depends_on:\n - api\n\n api:\n image: your-api:latest\n ports:\n - \"3000:3000\"\n environment:\n DATABASE_URL: \"postgres://user:pass@db:5432/app\"\n depends_on:\n - db\n\n db:\n image: postgres:16-alpine\n environment:\n POSTGRES_USER: user\n POSTGRES_PASSWORD: pass\n POSTGRES_DB: app\n```","src/content/docs/deployment/docker-compose.mdx","d2a6b719e4b5d6f7","examples/quick-no-manifest",{"id":140,"data":142,"body":148,"filePath":149,"digest":150,"deferredRender":16},{"title":143,"description":144,"editUrl":16,"head":145,"template":18,"sidebar":146,"pagefind":16,"draft":20},"Zero-Config Quick Start","Use REP with just naming conventions — no manifest, no CLI, no configuration file.",[],{"hidden":20,"attrs":147},{},"import { Aside } from '@astrojs/starlight/components';\n\nThe `.rep.yaml` manifest is entirely optional. The gateway works with nothing but environment variables — the naming convention **is** the configuration.\n\n## How it works\n\n| Env var prefix | Tier | In the browser |\n|---|---|---|\n| `REP_PUBLIC_*` | PUBLIC | Plaintext in `\u003Cscript id=\"__rep__\">`. Read with `rep.get()`. |\n| `REP_SENSITIVE_*` | SENSITIVE | AES-256-GCM encrypted. Decrypt with `await rep.getSecure()`. |\n| `REP_SERVER_*` | SERVER | Never leaves the gateway process. |\n| `REP_GATEWAY_*` | Config | Gateway settings. Not injected into the app. |\n\nThat's the entire protocol.\n\n## Step 1 — Rename your env vars\n\n```bash\n# Before (Vite) → After (REP)\nVITE_API_URL → REP_PUBLIC_API_URL\nVITE_FEATURE_FLAGS → REP_PUBLIC_FEATURE_FLAGS\n\n# Before (CRA) → After (REP)\nREACT_APP_API_URL → REP_PUBLIC_API_URL\n\n# Should be encrypted\nREACT_APP_ANALYTICS_KEY → REP_SENSITIVE_ANALYTICS_KEY\n\n# Should never reach the browser\nDB_PASSWORD → REP_SERVER_DB_PASSWORD\n```\n\n## Step 2 — Install the SDK and update reads\n\n```bash\nnpm install @rep-protocol/sdk\n```\n\n```typescript\nimport { rep } from '@rep-protocol/sdk';\n\n// Was: import.meta.env.VITE_API_URL\nconst apiUrl = rep.get('API_URL');\n\n// With a default for local development\nconst apiUrl = rep.get('API_URL', 'http://localhost:3001');\n\n// Sensitive — encrypted, decrypted on demand\nconst key = await rep.getSecure('ANALYTICS_KEY');\n```\n\n## Step 3 — Build your app (nothing changes)\n\n```bash\nnpm run build\n```\n\nThe output is now environment-agnostic.\n\n## Step 4 — Run the gateway\n\n```bash\nREP_PUBLIC_API_URL=https://api.example.com \\\nREP_PUBLIC_FEATURE_FLAGS=dark-mode,new-checkout \\\nREP_SENSITIVE_ANALYTICS_KEY=ak_live_abc123 \\\n./rep-gateway --mode embedded --static-dir ./dist\n```\n\nOpen `http://localhost:8080` — done.\n\n## Changing config without rebuilding\n\n```bash\n# Stop. Change values. Restart.\nREP_PUBLIC_API_URL=https://api.prod.example.com \\\nREP_PUBLIC_FEATURE_FLAGS=dark-mode \\\n./rep-gateway --mode embedded --static-dir ./dist\n```\n\nSame `dist/` folder. Different runtime config.\n\n### Dev mode — file watch hot reload\n\nFor local development, point the gateway at a `.env.local` file and let it watch for changes automatically — no signals, no restarts:\n\n```bash\n# .env.local\nREP_PUBLIC_API_URL=http://localhost:3001\nREP_PUBLIC_FEATURE_FLAGS=dark-mode\nREP_SENSITIVE_ANALYTICS_KEY=ak_dev_abc123\n```\n\n```bash\n./rep-gateway --mode embedded --static-dir ./dist \\\n --hot-reload \\\n --hot-reload-mode=file_watch \\\n --env-file=.env.local \\\n --watch-path=.env.local\n```\n\nEdit `.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.\n\n\u003CAside type=\"tip\">\n The CLI dev command handles this automatically: `npx @rep-protocol/cli dev --proxy http://localhost:5173` starts the gateway with file watch mode already enabled. See the [Local Development guide](/guides/development/).\n\u003C/Aside>\n\n## When to add a manifest\n\nThe manifest is additive. Add it when you need:\n\n- **Startup validation** — fail fast if a required variable is missing\n- **Type constraints** — enforce `url`, `number`, `enum` shapes\n- **TypeScript types** — `rep typegen` generates typed overloads\n- **Documentation** — single source of truth for all variables\n\n\u003CAside type=\"tip\">\n Start without a manifest. Add one later when you want validation and type generation. See the [Manifest guide](/guides/manifest/).\n\u003C/Aside>","src/content/docs/examples/quick-no-manifest.mdx","907101e185bb976d","examples/todo-react",{"id":151,"data":153,"body":159,"filePath":160,"digest":161,"deferredRender":16},{"title":154,"description":155,"editUrl":16,"head":156,"template":18,"sidebar":157,"pagefind":16,"draft":20},"Todo App (React)","Full worked example — React app with useRep, useRepSecure, hot reload, and Docker deployment.",[],{"hidden":20,"attrs":158},{},"import { Aside } from '@astrojs/starlight/components';\n\nA complete React todo app demonstrating all REP features. Source code at [`examples/todo-react/`](https://github.com/ruachtech/rep/tree/main/examples/todo-react).\n\n## Features demonstrated\n\n| Feature | Component/File | REP API |\n|---|---|---|\n| Public variable access | `App.tsx` | `useRep('APP_TITLE')` |\n| Enum validation | `Header.tsx` | `useRep('ENV_NAME')` |\n| URL variable | `TodoList.tsx` | `useRep('API_URL')` |\n| Number constraint | `TodoList.tsx` | `useRep('MAX_TODOS')` |\n| Sensitive variable | `Analytics.tsx` | `useRepSecure('ANALYTICS_KEY')` |\n| Payload metadata | `Footer.tsx` | `rep.meta()` |\n\n## Environment variables\n\n| Variable | Tier | Type | Default | Description |\n|---|---|---|---|---|\n| `APP_TITLE` | public | string | `\"Todo App\"` | Page title |\n| `ENV_NAME` | public | enum | — | `development`, `staging`, `production` |\n| `API_URL` | public | url | — | Backend API endpoint |\n| `MAX_TODOS` | public | number | `100` | Maximum todo items |\n| `ANALYTICS_KEY` | sensitive | string | — | Analytics tracking key |\n\n## Running locally\n\n### With the CLI\n\n```bash\n# From the repo root\npnpm install\n\n# Validate the manifest\ncd examples/todo-react\nnpx @rep-protocol/cli validate\n\n# Generate TypeScript types\nnpx @rep-protocol/cli typegen\n\n# Start Vite dev server\npnpm dev\n\n# In another terminal: start REP gateway proxy\nnpx @rep-protocol/cli dev --proxy http://localhost:5173\n```\n\nOpen `http://localhost:8080` to see the app with REP-injected variables.\n\n### With Docker\n\n```bash\ncd examples/todo-react\ndocker build -t rep-todo .\n\n# Run with staging config\ndocker run -p 8080:8080 \\\n -e REP_PUBLIC_APP_TITLE=\"Todo - Staging\" \\\n -e REP_PUBLIC_ENV_NAME=staging \\\n -e REP_PUBLIC_API_URL=https://api.staging.example.com \\\n -e REP_PUBLIC_MAX_TODOS=50 \\\n -e REP_SENSITIVE_ANALYTICS_KEY=UA-XXXXX-staging \\\n rep-todo\n\n# Same image, production config\ndocker run -p 8080:8080 \\\n -e REP_PUBLIC_APP_TITLE=\"Todo\" \\\n -e REP_PUBLIC_ENV_NAME=production \\\n -e REP_PUBLIC_API_URL=https://api.example.com \\\n -e REP_SENSITIVE_ANALYTICS_KEY=UA-XXXXX-prod \\\n rep-todo\n```\n\n## Hot reload\n\nWith the CLI dev server running, edit `.env.local` and send SIGHUP to the gateway:\n\n```bash\n# Edit .env.local, then:\nkill -HUP $(pidof rep-gateway)\n```\n\nComponents using `useRep()` re-render automatically.\n\n## Dockerfile\n\nThe example uses a 3-stage multi-stage build:\n\n1. **Download gateway:** Alpine + curl fetches the pre-built binary from GitHub Releases\n2. **Build app:** Node + pnpm builds SDK, React adapter, and the app in dependency order\n3. **Final image:** `FROM scratch` with just the gateway binary and static files\n\n\u003CAside type=\"tip\">\n The `FROM scratch` final image contains no OS, no shell, and no package manager. Total size is approximately 5MB (3MB gateway + 2MB static assets).\n\u003C/Aside>","src/content/docs/examples/todo-react.mdx","cefb6912670abd37","deployment/kubernetes",{"id":162,"data":164,"body":170,"filePath":171,"digest":172,"deferredRender":16},{"title":165,"description":166,"editUrl":16,"head":167,"template":18,"sidebar":168,"pagefind":16,"draft":20},"Kubernetes","Deploy REP with ConfigMaps, Secrets, sidecars, and hot reload in Kubernetes.",[],{"hidden":20,"attrs":169},{},"import { Aside } from '@astrojs/starlight/components';\n\n## Embedded deployment\n\nThe simplest Kubernetes deployment — gateway serves files directly:\n\n```yaml\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: frontend\nspec:\n replicas: 3\n selector:\n matchLabels:\n app: frontend\n template:\n metadata:\n labels:\n app: frontend\n spec:\n containers:\n - name: app\n image: myapp:latest\n ports:\n - containerPort: 8080\n envFrom:\n - configMapRef:\n name: frontend-public-config\n - secretRef:\n name: frontend-sensitive-config\n livenessProbe:\n httpGet:\n path: /rep/health\n port: 8080\n initialDelaySeconds: 5\n readinessProbe:\n httpGet:\n path: /rep/health\n port: 8080\n initialDelaySeconds: 2\n\n---\napiVersion: v1\nkind: ConfigMap\nmetadata:\n name: frontend-public-config\ndata:\n REP_PUBLIC_API_URL: \"https://api.example.com\"\n REP_PUBLIC_FEATURE_FLAGS: \"dark-mode\"\n REP_PUBLIC_ENV_NAME: \"production\"\n REP_GATEWAY_STRICT: \"true\"\n\n---\napiVersion: v1\nkind: Secret\nmetadata:\n name: frontend-sensitive-config\ntype: Opaque\nstringData:\n REP_SENSITIVE_ANALYTICS_KEY: \"UA-XXXXX-prod\"\n REP_SENSITIVE_SENTRY_DSN: \"https://abc@sentry.io/123\"\n```\n\n## Sidecar pattern (with nginx)\n\nWhen you want nginx serving files with the gateway as a sidecar:\n\n```yaml\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: frontend\nspec:\n template:\n spec:\n containers:\n - name: nginx\n image: nginx:alpine\n volumeMounts:\n - name: static-files\n mountPath: /usr/share/nginx/html\n readOnly: true\n ports:\n - containerPort: 80\n\n - name: rep-gateway\n image: ghcr.io/ruachtech/rep/gateway:latest\n args:\n - \"--upstream=localhost:80\"\n - \"--port=8080\"\n - \"--strict\"\n - \"--hot-reload\"\n - \"--hot-reload-mode=file_watch\"\n - \"--watch-path=/config\"\n envFrom:\n - configMapRef:\n name: frontend-public-config\n - secretRef:\n name: frontend-sensitive-config\n volumeMounts:\n - name: config-volume\n mountPath: /config\n readOnly: true\n ports:\n - containerPort: 8080\n livenessProbe:\n httpGet:\n path: /rep/health\n port: 8080\n\n initContainers:\n - name: copy-static\n image: myapp:latest\n command: ['cp', '-r', '/app/dist/.', '/static/']\n volumeMounts:\n - name: static-files\n mountPath: /static\n\n volumes:\n - name: static-files\n emptyDir: {}\n - name: config-volume\n configMap:\n name: frontend-dynamic-config\n```\n\n## Hot reload with ConfigMaps\n\nUse file watch mode to detect ConfigMap changes without pod restarts:\n\n1. Mount the ConfigMap as a volume\n2. Enable `--hot-reload --hot-reload-mode=file_watch --watch-path=/config`\n3. Update the ConfigMap: `kubectl apply -f configmap.yaml`\n4. Kubernetes refreshes the mounted volume\n5. The gateway detects the change and broadcasts via SSE\n6. Connected browsers receive the update\n\n```bash\n# Update a config value\nkubectl patch configmap frontend-dynamic-config \\\n -p '{\"data\":{\"REP_PUBLIC_FEATURE_FLAGS\":\"dark-mode,ai-assist\"}}'\n```\n\n\u003CAside type=\"tip\">\n Use `--health-port 9090` to serve health checks on a separate port. This keeps the health endpoint accessible only within the cluster while the main port faces the load balancer.\n\u003C/Aside>\n\n## Service\n\n```yaml\napiVersion: v1\nkind: Service\nmetadata:\n name: frontend\nspec:\n selector:\n app: frontend\n ports:\n - port: 80\n targetPort: 8080\n type: ClusterIP\n```","src/content/docs/deployment/kubernetes.mdx","53259bc9fa4f21d7","deployment/docker-proxy",{"id":173,"data":175,"body":181,"filePath":182,"digest":183,"deferredRender":16},{"title":176,"description":177,"editUrl":16,"head":178,"template":18,"sidebar":179,"pagefind":16,"draft":20},"Docker — Proxy Mode","Run the REP gateway as a reverse proxy in front of nginx or Caddy.",[],{"hidden":20,"attrs":180},{},"import { Aside } from '@astrojs/starlight/components';\n\nIn proxy mode, the gateway sits in front of your existing web server and injects variables into HTML responses.\n\n```\nBrowser → [REP Gateway :8080] → [nginx :80]\n```\n\n## Dockerfile\n\n```dockerfile\n# Stage 1: Build the frontend\nFROM node:22-alpine AS build\nWORKDIR /app\nCOPY package*.json ./\nRUN npm ci\nCOPY . .\nRUN npm run build\n\n# Stage 2: nginx + REP gateway\nFROM nginx:alpine\n\n# Copy built assets to nginx\nCOPY --from=build /app/dist /usr/share/nginx/html\n\n# Add the REP gateway binary\nCOPY --from=ghcr.io/ruachtech/rep/gateway:latest \\\n /usr/local/bin/rep-gateway /usr/local/bin/rep-gateway\n\nEXPOSE 8080\n\nENTRYPOINT [\"rep-gateway\"]\nCMD [\"--mode\", \"proxy\", \"--upstream\", \"localhost:80\", \"--port\", \"8080\"]\n```\n\n## Running\n\n```bash\ndocker build -t myapp .\n\n# Staging\ndocker run -p 8080:8080 \\\n -e REP_PUBLIC_API_URL=https://api.staging.example.com \\\n -e REP_PUBLIC_FEATURE_FLAGS=dark-mode,beta \\\n -e REP_SENSITIVE_ANALYTICS_KEY=UA-XXXXX-staging \\\n myapp\n\n# Production — SAME IMAGE\ndocker run -p 8080:8080 \\\n -e REP_PUBLIC_API_URL=https://api.example.com \\\n -e REP_PUBLIC_FEATURE_FLAGS=dark-mode \\\n -e REP_SENSITIVE_ANALYTICS_KEY=UA-XXXXX-prod \\\n -e REP_GATEWAY_STRICT=true \\\n myapp\n```\n\n## How it works\n\n1. nginx starts and serves static files on port 80 (inside the container)\n2. The gateway starts and proxies all requests to `localhost:80`\n3. For `text/html` responses, the gateway intercepts and injects the REP payload\n4. All other responses (JS, CSS, images) pass through unmodified\n\n\u003CAside>\n The gateway strips `Accept-Encoding` from proxied requests so upstreams respond with identity encoding. This avoids decompress/recompress overhead. The gateway handles gzip compression for non-compliant upstreams via stdlib.\n\u003C/Aside>\n\n## When to use proxy mode\n\n- You need nginx features (gzip, caching headers, URL rewriting, basic auth)\n- You're adding REP to an existing deployment with minimal changes\n- Your infrastructure team prefers nginx/Caddy for static file serving","src/content/docs/deployment/docker-proxy.mdx","bc743b18d2af9c3d","deployment/docker-embedded",{"id":184,"data":186,"body":192,"filePath":193,"digest":194,"deferredRender":16},{"title":187,"description":188,"editUrl":16,"head":189,"template":18,"sidebar":190,"pagefind":16,"draft":20},"Docker — Embedded Mode","Minimal FROM scratch containers with the gateway serving files directly.",[],{"hidden":20,"attrs":191},{},"import { Aside } from '@astrojs/starlight/components';\n\nIn embedded mode, the gateway serves static files directly — no nginx, no Caddy, no Node.js. This produces the smallest possible production image.\n\n## Dockerfile\n\n```dockerfile\n# Stage 1: Build the frontend\nFROM node:22-alpine AS build\nWORKDIR /app\nCOPY package*.json ./\nRUN npm ci\nCOPY . .\nRUN npm run build\n\n# Stage 2: FROM scratch — nothing but the binary and static files\nFROM scratch\n\nCOPY --from=build /app/dist /static\nCOPY --from=ghcr.io/ruachtech/rep/gateway:latest \\\n /usr/local/bin/rep-gateway /rep-gateway\n\nEXPOSE 8080\nUSER 65534:65534\n\nENTRYPOINT [\"/rep-gateway\"]\nCMD [\"--mode\", \"embedded\", \"--static-dir\", \"/static\", \"--port\", \"8080\", \"--strict\"]\n```\n\n## What's in the image\n\nExactly two things:\n- Your built static files (`dist/`)\n- The REP gateway binary (~3MB)\n\nNo OS, no shell, no utilities, no package manager. Attack surface: near zero.\n\n## Running\n\n```bash\ndocker build -t myapp .\n\ndocker run -p 8080:8080 \\\n -e REP_PUBLIC_API_URL=https://api.example.com \\\n -e REP_SENSITIVE_ANALYTICS_KEY=UA-XXXXX \\\n -e REP_GATEWAY_STRICT=true \\\n -e REP_GATEWAY_ALLOWED_ORIGINS=https://app.example.com \\\n myapp\n```\n\n## Multi-architecture builds\n\n```dockerfile\n# In the gateway download stage\nARG TARGETARCH\n# The gateway image is multi-arch — Docker selects the correct binary\nCOPY --from=ghcr.io/ruachtech/rep/gateway:latest \\\n /usr/local/bin/rep-gateway /rep-gateway\n```\n\n## Security hardening\n\nThe `FROM scratch` + non-root pattern provides:\n\n- **No shell** — `docker exec` attacks are impossible\n- **No package manager** — no malware installation vector\n- **Read-only filesystem** — compatible with `readOnlyRootFilesystem: true`\n- **Non-root user** — UID 65534 (`nobody`)\n- **Static binary** — no shared libraries, no dynamic linker\n\n\u003CAside type=\"tip\">\n Embedded mode is recommended for production deployments where you don't need nginx-specific features. The gateway handles HTTP/2, compression, and caching headers natively.\n\u003C/Aside>\n\n## When to use embedded mode\n\n- You want the smallest possible container image\n- You're deploying a pure SPA with no server-side rendering\n- Security is a priority (minimal attack surface)\n- You don't need nginx-specific features (URL rewriting, basic auth, etc.)","src/content/docs/deployment/docker-embedded.mdx","a8dc24a47a3d5aea","guides/development",{"id":195,"data":197,"body":203,"filePath":204,"digest":205,"deferredRender":16},{"title":198,"description":199,"editUrl":16,"head":200,"template":18,"sidebar":201,"pagefind":16,"draft":20},"Local Development","Three approaches for developing with REP locally — defaults, mock payload, or the CLI dev server.",[],{"hidden":20,"attrs":202},{},"import { Tabs, TabItem, Aside } from '@astrojs/starlight/components';\n\nDuring local development you typically don't have the REP gateway running. The SDK handles this gracefully — `rep.get()` returns `undefined` when no payload is present.\n\n## Option A: Default values (simplest)\n\nUse the second argument to `rep.get()`:\n\n```typescript\nconst apiUrl = rep.get('API_URL', 'http://localhost:3000');\n// In dev: returns 'http://localhost:3000'\n// In prod: returns the injected value\n```\n\nThis is the simplest approach and works with any framework. No extra configuration needed.\n\n## Option B: Mock payload in HTML\n\nAdd a `\u003Cscript id=\"__rep__\">` tag to your `index.html`:\n\n```html\n\u003C!-- Only in development — the gateway replaces this in production -->\n\u003Cscript id=\"__rep__\" type=\"application/json\">\n{\n \"public\": {\n \"API_URL\": \"http://localhost:3000\",\n \"FEATURE_FLAGS\": \"dark-mode,debug\"\n },\n \"_meta\": {\n \"version\": \"0.1.0\",\n \"injected_at\": \"2026-01-01T00:00:00Z\",\n \"integrity\": \"hmac-sha256:dev-mode-no-verification\",\n \"ttl\": 0\n }\n}\n\u003C/script>\n```\n\nThis gives you the full SDK experience (including `rep.verify()` and `rep.meta()`) without the gateway.\n\n\u003CAside type=\"caution\">\n Don't forget to remove this tag from your production HTML. In production, the gateway injects it automatically.\n\u003C/Aside>\n\n## Option C: CLI dev server (full fidelity)\n\nThe `rep dev` command runs a local gateway that reads your `.env` file and proxies to your dev server:\n\n\u003CTabs>\n \u003CTabItem label=\"With Vite\">\n ```bash\n # Terminal 1: Start Vite dev server\n npm run dev\n # → Vite running at http://localhost:5173\n\n # Terminal 2: Start REP gateway proxy\n rep dev --env .env.local --proxy http://localhost:5173\n # → Gateway at http://localhost:8080 → proxies to Vite\n ```\n\n Open `http://localhost:8080` (the gateway port), not `:5173`. The gateway injects variables into Vite's HTML responses.\n \u003C/TabItem>\n \u003CTabItem label=\"With static files\">\n ```bash\n # Build first\n npm run build\n\n # Serve from dist/ with REP injection\n rep dev --env .env.local --static ./dist\n ```\n \u003C/TabItem>\n\u003C/Tabs>\n\n### `.env.local` example\n\n```bash\nREP_PUBLIC_API_URL=http://localhost:3000\nREP_PUBLIC_FEATURE_FLAGS=dark-mode,debug\nREP_SENSITIVE_ANALYTICS_KEY=test-key-123\n```\n\n### CLI dev server options\n\n| Flag | Default | Description |\n|---|---|---|\n| `-e, --env \u003Cpath>` | `.env.local` | Path to .env file |\n| `-p, --port \u003Cnumber>` | `8080` | Gateway port |\n| `--proxy \u003Curl>` | — | Upstream proxy URL |\n| `--static \u003Cpath>` | — | Serve static files (embedded mode) |\n| `--hot-reload` | `false` | Enable hot reload |\n| `--gateway-bin \u003Cpath>` | auto-detected | Path to gateway binary |\n\n\u003CAside>\n When using proxy mode with Vite, access the site through the gateway port (8080), not Vite's port (5173). Vite's HMR WebSocket continues to work through the proxy for CSS and module updates.\n\u003C/Aside>\n\n## Using all CLI commands in development\n\nThe CLI provides a complete development workflow:\n\n```bash\n# 1. Validate your manifest\nrep validate --manifest .rep.yaml\n# ✓ Manifest is valid — 6 variables, 4 settings\n\n# 2. Generate TypeScript types\nrep typegen --manifest .rep.yaml --output src/rep.d.ts\n# ✓ Generated types for 3 public + 2 sensitive variables\n\n# 3. Start the dev server\nrep dev --env .env.local --proxy http://localhost:5173\n\n# 4. Before deployment: scan bundles for leaked secrets\nrep lint --dir ./dist\n# ✓ No secrets detected in 12 files\n```","src/content/docs/guides/development.mdx","d043d5b91dcc4045","guides/installation",{"id":206,"data":208,"body":214,"filePath":215,"digest":216,"deferredRender":16},{"title":209,"description":210,"editUrl":16,"head":211,"template":18,"sidebar":212,"pagefind":16,"draft":20},"Installation","Install the REP SDK, CLI, and gateway binary.",[],{"hidden":20,"attrs":213},{},"import { Tabs, TabItem, Aside } from '@astrojs/starlight/components';\n\n## SDK\n\nThe SDK is the only package required for your application code. Zero runtime dependencies, ~1.5KB gzipped.\n\n```bash\nnpm install @rep-protocol/sdk\n```\n\n## Framework adapters (optional)\n\nIf you're using React, Vue, or Svelte, install the corresponding adapter for hot-reload-aware hooks and stores:\n\n\u003CTabs>\n \u003CTabItem label=\"React\">\n ```bash\n npm install @rep-protocol/react @rep-protocol/sdk\n ```\n \u003C/TabItem>\n \u003CTabItem label=\"Vue\">\n ```bash\n npm install @rep-protocol/vue @rep-protocol/sdk\n ```\n \u003C/TabItem>\n \u003CTabItem label=\"Svelte\">\n ```bash\n npm install @rep-protocol/svelte @rep-protocol/sdk\n ```\n \u003C/TabItem>\n\u003C/Tabs>\n\n## CLI\n\nThe CLI provides `rep validate`, `rep typegen`, `rep lint`, and `rep dev` commands. It automatically downloads the correct gateway binary for your platform during installation.\n\n```bash\nnpm install -g @rep-protocol/cli\n```\n\nOr use without installing:\n\n```bash\nnpx @rep-protocol/cli validate\nnpx @rep-protocol/cli dev --proxy http://localhost:5173\n```\n\n## Gateway binary\n\nThe gateway is a standalone Go binary (~3MB). There are several ways to get it:\n\n### Via the CLI (recommended)\n\nThe `@rep-protocol/cli` package downloads the gateway binary automatically during `npm install`.\n\n### Docker image\n\n```bash\ndocker pull ghcr.io/ruachtech/rep/gateway:latest\n```\n\nOr use in a multi-stage build:\n\n```dockerfile\nCOPY --from=ghcr.io/ruachtech/rep/gateway:latest /usr/local/bin/rep-gateway /usr/local/bin/rep-gateway\n```\n\n### Direct download\n\nDownload from [GitHub Releases](https://github.com/ruachtech/rep/releases) for your platform:\n\n```bash\n# Linux amd64\ncurl -fsSL https://github.com/RuachTech/rep/releases/download/gateway/v0.1.2/rep-gateway_0.1.2_linux_amd64.tar.gz | tar -xz\nmv rep-gateway /usr/local/bin/\n\n# macOS arm64\ncurl -fsSL https://github.com/RuachTech/rep/releases/download/gateway/v0.1.2/rep-gateway_0.1.2_darwin_arm64.tar.gz | tar -xz\nmv rep-gateway /usr/local/bin/\n```\n\n### Build from source\n\nRequires Go >= 1.24.5:\n\n```bash\ncd gateway\nmake build\n# Binary at gateway/bin/rep-gateway\n```\n\n## Development prerequisites\n\nFor contributing to REP itself:\n\n| Tool | Version | Purpose |\n|---|---|---|\n| Node.js | >= 20.0.0 | TypeScript packages |\n| pnpm | >= 9.0.0 | Workspace management |\n| Go | >= 1.24.5 | Gateway development |\n\n```bash\ngit clone https://github.com/ruachtech/rep.git\ncd rep\npnpm install\npnpm run build\n```","src/content/docs/guides/installation.mdx","02d0a7dc2ffe61f0","guides/testing",{"id":217,"data":219,"body":225,"filePath":226,"digest":227,"deferredRender":16},{"title":220,"description":221,"editUrl":16,"head":222,"template":18,"sidebar":223,"pagefind":16,"draft":20},"Testing","Unit testing with mock payloads, integration testing with Docker, and E2E testing patterns.",[],{"hidden":20,"attrs":224},{},"import { Aside } from '@astrojs/starlight/components';\n\n## Unit testing\n\nCreate a helper that mocks the REP payload for your test environment:\n\n```typescript\n// test/helpers/mock-rep.ts\nexport function mockRepPayload(vars: Record\u003Cstring, string>) {\n // Remove any existing mock\n document.getElementById('__rep__')?.remove();\n\n const script = document.createElement('script');\n script.id = '__rep__';\n script.type = 'application/json';\n\n const payload = {\n public: vars,\n _meta: {\n version: '0.1.0',\n injected_at: new Date().toISOString(),\n integrity: 'hmac-sha256:test-mode',\n ttl: 0,\n },\n };\n\n script.textContent = JSON.stringify(payload);\n document.head.appendChild(script);\n}\n```\n\n### Using with Vitest\n\n```typescript\nimport { describe, it, expect, beforeEach, vi } from 'vitest';\nimport { mockRepPayload } from '../helpers/mock-rep';\n\ndescribe('Config-dependent component', () => {\n beforeEach(() => {\n // Reset module cache — SDK's _init() runs on import\n vi.resetModules();\n document.head.innerHTML = '';\n document.body.innerHTML = '';\n });\n\n it('reads API_URL from REP payload', async () => {\n mockRepPayload({ API_URL: 'https://api.test.com' });\n\n // Dynamic import gets a fresh SDK instance\n const { rep } = await import('@rep-protocol/sdk');\n expect(rep.get('API_URL')).toBe('https://api.test.com');\n });\n\n it('returns default when payload is absent', async () => {\n const { rep } = await import('@rep-protocol/sdk');\n expect(rep.get('API_URL', 'fallback')).toBe('fallback');\n });\n});\n```\n\n\u003CAside type=\"tip\">\n The SDK's `_init()` function runs on module load. Use `vi.resetModules()` and dynamic `import()` in each test to get a fresh SDK instance that reads the current DOM state.\n\u003C/Aside>\n\n### Vitest configuration\n\n```typescript\n// vitest.config.ts\nimport { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n test: {\n environment: 'jsdom',\n },\n});\n```\n\n## Integration testing\n\nUse Docker Compose to test with a real gateway:\n\n```yaml\n# docker-compose.test.yml\nservices:\n app:\n build: .\n environment:\n REP_PUBLIC_API_URL: \"http://api:3000\"\n REP_PUBLIC_FEATURE_FLAGS: \"all\"\n REP_SENSITIVE_ANALYTICS_KEY: \"test-key\"\n ports:\n - \"8080:8080\"\n\n api:\n image: your-api:test\n ports:\n - \"3000:3000\"\n```\n\n```bash\ndocker compose -f docker-compose.test.yml up -d\nnpx playwright test --base-url http://localhost:8080\ndocker compose -f docker-compose.test.yml down\n```\n\n## Health check testing\n\nVerify the gateway is running and configured correctly:\n\n```bash\ncurl -s http://localhost:8080/rep/health | jq\n```\n\nExpected output:\n```json\n{\n \"status\": \"healthy\",\n \"version\": \"0.1.0\",\n \"variables\": {\n \"public\": 3,\n \"sensitive\": 1,\n \"server\": 2\n },\n \"guardrails\": {\n \"warnings\": 0,\n \"blocked\": 0\n },\n \"uptime_seconds\": 42\n}\n```\n\n## Bundle scanning\n\nUse `rep lint` in CI to catch accidentally leaked secrets in build output:\n\n```bash\nrep lint --dir ./dist --strict\n```\n\nThis runs the same entropy and pattern detection as the gateway guardrails, but against your compiled JavaScript bundles. Add it as a CI step to prevent deployment of bundles containing secrets.","src/content/docs/guides/testing.mdx","3c6643b70a6cbc7f","guides/manifest",{"id":228,"data":230,"body":236,"filePath":237,"digest":238,"deferredRender":16},{"title":231,"description":232,"editUrl":16,"head":233,"template":18,"sidebar":234,"pagefind":16,"draft":20},"Manifest File","Declare variables, types, and settings in .rep.yaml for validation and type generation.",[],{"hidden":20,"attrs":235},{},"import { Aside } from '@astrojs/starlight/components';\n\nThe `.rep.yaml` manifest is optional but powerful. It enables:\n\n- **Startup validation** — fail fast if a required variable is missing\n- **Type constraints** — enforce `url`, `number`, `enum`, `csv` shapes\n- **TypeScript types** — `rep typegen` generates typed `get()` / `getSecure()` overloads\n- **Documentation** — a single source of truth for every variable the app uses\n\n## Example manifest\n\n```yaml\nversion: \"0.1.0\"\n\nvariables:\n API_URL:\n tier: public\n type: url\n required: true\n description: \"Base URL for the backend REST API\"\n example: \"https://api.example.com\"\n\n FEATURE_FLAGS:\n tier: public\n type: csv\n required: false\n default: \"\"\n description: \"Comma-separated feature flags\"\n example: \"dark-mode,new-checkout\"\n\n ENV_NAME:\n tier: public\n type: enum\n required: true\n values: [\"development\", \"staging\", \"production\"]\n description: \"Current deployment environment\"\n\n ANALYTICS_WRITE_KEY:\n tier: sensitive\n type: string\n required: true\n description: \"Analytics service write key\"\n\n OAUTH_CLIENT_ID:\n tier: sensitive\n type: string\n required: true\n pattern: \"^[a-zA-Z0-9]{20,}$\"\n description: \"OAuth 2.0 client identifier\"\n\n UPSTREAM_AUTH_TOKEN:\n tier: server\n type: string\n required: false\n description: \"Bearer token for upstream proxying\"\n\nsettings:\n strict_guardrails: true\n hot_reload: true\n session_key_ttl: \"30s\"\n session_key_max_rate: 10\n allowed_origins:\n - \"https://app.example.com\"\n```\n\n## Variable fields\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `tier` | `public` / `sensitive` / `server` | Yes | Security classification |\n| `type` | see below | Yes | Value type constraint |\n| `required` | boolean | No | Whether the variable must be present at startup |\n| `default` | string | No | Default value if not provided |\n| `description` | string | No | Human-readable description |\n| `example` | string | No | Example value |\n| `pattern` | string | No | Regex pattern the value must match |\n| `values` | string[] | No | Allowed values (for `enum` type) |\n| `deprecated` | boolean | No | Mark as deprecated |\n| `deprecated_message` | string | No | Migration guidance for deprecated vars |\n\n## Supported types\n\n| Type | Validation |\n|---|---|\n| `string` | Any string value |\n| `url` | Must be a valid URL |\n| `number` | Must parse as a number |\n| `boolean` | Must be `true`, `false`, `1`, or `0` |\n| `csv` | Comma-separated values |\n| `json` | Must be valid JSON |\n| `enum` | Must match one of the `values` array entries |\n\n## Settings\n\n| Setting | Type | Default | Description |\n|---|---|---|---|\n| `strict_guardrails` | boolean | `false` | Exit on guardrail warnings |\n| `hot_reload` | boolean | `false` | Enable hot reload SSE |\n| `hot_reload_mode` | string | `signal` | `file_watch`, `signal`, or `poll` |\n| `hot_reload_poll_interval` | string | `30s` | Poll interval (Go duration) |\n| `session_key_ttl` | string | `30s` | Session key expiry |\n| `session_key_max_rate` | number | `10` | Max session key requests per minute per IP |\n| `allowed_origins` | string[] | `[]` | CORS allowed origins for session key endpoint |\n\n## Validating\n\n```bash\nrep validate --manifest .rep.yaml\n```\n\nOutput:\n```\n✓ Manifest is valid\n Version: 0.1.0\n Variables: 6 total\n - PUBLIC: 3\n - SENSITIVE: 2\n - SERVER: 1\n Settings configured: 4\n```\n\nUse in CI to catch configuration errors before deployment:\n\n```yaml\n- name: Validate REP manifest\n run: npx @rep-protocol/cli validate --manifest .rep.yaml\n```\n\n## Type generation\n\nGenerate TypeScript type definitions from your manifest:\n\n```bash\nrep typegen --manifest .rep.yaml --output src/rep.d.ts\n```\n\nThis creates typed overloads for `get()` and `getSecure()`:\n\n```typescript\ndeclare module \"@rep-protocol/sdk\" {\n export interface REP {\n get(key: \"API_URL\" | \"FEATURE_FLAGS\" | \"ENV_NAME\"): string | undefined;\n getSecure(key: \"ANALYTICS_WRITE_KEY\" | \"OAUTH_CLIENT_ID\"): Promise\u003Cstring>;\n }\n}\n```\n\n\u003CAside type=\"tip\">\n Run `rep typegen` as part of your build script or as a pre-commit hook to keep types in sync with the manifest.\n\u003C/Aside>\n\nFor the full schema reference, see [Manifest Schema Reference](/reference/manifest-schema/).","src/content/docs/guides/manifest.mdx","1677b8ba99702048","frameworks/angular",{"id":239,"data":241,"body":247,"filePath":248,"digest":249,"deferredRender":16},{"title":242,"description":243,"editUrl":16,"head":244,"template":18,"sidebar":245,"pagefind":16,"draft":20},"Angular","Use REP with Angular — Injectable RepService with Observable support.",[],{"hidden":20,"attrs":246},{},"import { Aside } from '@astrojs/starlight/components';\n\n\u003CAside>\n There is no published `@rep-protocol/angular` package. Angular integration uses the core SDK directly via a service pattern shown below.\n\u003C/Aside>\n\n## Installation\n\n```bash\nnpm install @rep-protocol/sdk\n```\n\n## Create a RepService\n\n```typescript\n// src/app/services/rep.service.ts\nimport { Injectable } from '@angular/core';\nimport { rep } from '@rep-protocol/sdk';\nimport { BehaviorSubject, Observable } from 'rxjs';\n\n@Injectable({ providedIn: 'root' })\nexport class RepService {\n get(key: string, defaultValue?: string): string | undefined {\n return rep.get(key, defaultValue);\n }\n\n getSecure(key: string): Promise\u003Cstring> {\n return rep.getSecure(key);\n }\n\n watch(key: string): Observable\u003Cstring | undefined> {\n const subject = new BehaviorSubject(rep.get(key));\n rep.onChange(key, (newVal) => subject.next(newVal));\n return subject.asObservable();\n }\n}\n```\n\n## Usage in components\n\n```typescript\n// src/app/components/config-display.component.ts\nimport { Component, OnInit } from '@angular/core';\nimport { RepService } from '../services/rep.service';\nimport { Observable } from 'rxjs';\n\n@Component({\n selector: 'app-config-display',\n template: `\n \u003Cdiv>\n \u003Cp>API: {{ apiUrl }}\u003C/p>\n \u003Cp>Flags: {{ flags$ | async }}\u003C/p>\n \u003Cp>Analytics: {{ analyticsKey ?? 'loading...' }}\u003C/p>\n \u003C/div>\n `,\n})\nexport class ConfigDisplayComponent implements OnInit {\n apiUrl: string | undefined;\n flags$: Observable\u003Cstring | undefined>;\n analyticsKey: string | null = null;\n\n constructor(private rep: RepService) {\n // Synchronous — available immediately\n this.apiUrl = this.rep.get('API_URL', 'http://localhost:3000');\n\n // Observable — updates on hot reload\n this.flags$ = this.rep.watch('FEATURE_FLAGS');\n }\n\n async ngOnInit() {\n // Async — encrypted, decrypted on demand\n this.analyticsKey = await this.rep.getSecure('ANALYTICS_KEY');\n }\n}\n```\n\n## How it works\n\n- `get()` calls `rep.get()` from the core SDK — synchronous, no loading state\n- `getSecure()` calls `rep.getSecure()` — fetches a session key, decrypts, caches\n- `watch()` wraps `rep.onChange()` into a `BehaviorSubject` for Angular's `async` pipe\n\n## Development mode\n\nWithout the gateway, `rep.get()` returns `undefined`. Use default values:\n\n```typescript\nthis.apiUrl = this.rep.get('API_URL', 'http://localhost:3000');\n```\n\nOr add a mock payload to your `index.html` during development:\n\n```html\n\u003Cscript id=\"__rep__\" type=\"application/json\">\n{\"public\":{\"API_URL\":\"http://localhost:3000\"},\"_meta\":{\"version\":\"0.1.0\",\"injected_at\":\"2026-01-01T00:00:00Z\",\"integrity\":\"hmac-sha256:dev\",\"ttl\":0}}\n\u003C/script>\n```","src/content/docs/frameworks/angular.mdx","12cc1a605389df2e","frameworks/react",{"id":250,"data":252,"body":258,"filePath":259,"digest":260,"deferredRender":16},{"title":253,"description":254,"editUrl":16,"head":255,"template":18,"sidebar":256,"pagefind":16,"draft":20},"React","Use REP with React — useRep() and useRepSecure() hooks with automatic hot reload.",[],{"hidden":20,"attrs":257},{},"import { Tabs, TabItem, Aside } from '@astrojs/starlight/components';\n\n## Installation\n\n```bash\nnpm install @rep-protocol/react @rep-protocol/sdk\n```\n\n## Basic usage\n\n```tsx\nimport { useRep, useRepSecure } from '@rep-protocol/react';\n\nfunction App() {\n // PUBLIC tier — synchronous, no loading state\n const apiUrl = useRep('API_URL', 'http://localhost:3000');\n const flags = useRep('FEATURE_FLAGS', '').split(',');\n\n // SENSITIVE tier — async, renders null until resolved\n const { value: analyticsKey, loading, error } = useRepSecure('ANALYTICS_KEY');\n\n if (loading) return \u003Cspan>Loading...\u003C/span>;\n if (error) return \u003Cspan>Config error: {error.message}\u003C/span>;\n\n return (\n \u003Cdiv>\n \u003Cp>API: {apiUrl}\u003C/p>\n \u003Cp>Analytics: {analyticsKey}\u003C/p>\n \u003C/div>\n );\n}\n```\n\n## Migration from Vite / CRA\n\n**Before:**\n```typescript\n// src/config.ts\nexport const API_URL = import.meta.env.VITE_API_URL;\nexport const FEATURE_FLAGS = import.meta.env.VITE_FEATURE_FLAGS?.split(',') ?? [];\n```\n\n**After:**\n```typescript\n// src/config.ts\nimport { rep } from '@rep-protocol/sdk';\n\nexport const API_URL = rep.get('API_URL', 'http://localhost:3000');\nexport const FEATURE_FLAGS = rep.get('FEATURE_FLAGS', '')?.split(',').filter(Boolean) ?? [];\n```\n\nOr use the codemod for automated migration:\n\n```bash\nnpx @rep-protocol/codemod --framework vite src/\n```\n\n## `useRep(key, defaultValue?)`\n\nReads a **PUBLIC** tier variable. Synchronous — no loading state, no Suspense.\n\n```tsx\nconst value = useRep('API_URL'); // string | undefined\nconst value = useRep('API_URL', 'fallback'); // string (never undefined)\n```\n\n- Returns the value from the injected payload immediately\n- Returns `defaultValue` (or `undefined`) if the variable is not present\n- Automatically re-renders when the variable changes via hot reload\n- Unsubscribes on unmount\n\n## `useRepSecure(key)`\n\nReads a **SENSITIVE** tier variable. Async — fetches a session key on first call.\n\n```tsx\nconst { value, loading, error } = useRepSecure('ANALYTICS_KEY');\n// value: string | null — null until resolved\n// loading: boolean — true while fetching\n// error: Error | null — set if fetch or decryption fails\n```\n\n- Starts with `{ value: null, loading: true, error: null }`\n- The decrypted value is cached by the SDK for the page lifetime\n- Re-fetches if the `key` prop changes\n\n## Hot reload\n\nBoth hooks subscribe to the gateway's SSE stream when `--hot-reload` is enabled. Components re-render automatically when config changes. If hot reload is not available, hooks still work — they just won't update after initial render.\n\n\u003CAside>\n `useRepSecure` subscribes to hot reload for re-rendering, but sensitive variable decryption requires a new session key — which means a full component remount for updated sensitive values.\n\u003C/Aside>\n\n## Development mode\n\nWithout the gateway running, `useRep()` returns `undefined`. Two approaches:\n\n\u003CTabs>\n \u003CTabItem label=\"Default values\">\n ```tsx\n const apiUrl = useRep('API_URL', 'http://localhost:3000');\n ```\n \u003C/TabItem>\n \u003CTabItem label=\"Mock payload\">\n Add to your `index.html` during development:\n ```html\n \u003Cscript id=\"__rep__\" type=\"application/json\">\n {\"public\":{\"API_URL\":\"http://localhost:3000\",\"FEATURE_FLAGS\":\"dark-mode\"},\"_meta\":{\"version\":\"0.1.0\",\"injected_at\":\"2026-01-01T00:00:00Z\",\"integrity\":\"hmac-sha256:dev\",\"ttl\":0}}\n \u003C/script>\n ```\n \u003C/TabItem>\n \u003CTabItem label=\"CLI dev server\">\n ```bash\n # Terminal 1: Vite dev server\n npm run dev\n\n # Terminal 2: REP gateway proxy\n npx @rep-protocol/cli dev --proxy http://localhost:5173\n ```\n \u003C/TabItem>\n\u003C/Tabs>\n\n## Requirements\n\n- React >= 16.8 (hooks support)\n- `@rep-protocol/sdk` as a peer dependency\n\nFor the full API reference, see [React Adapter Reference](/reference/adapters/react/).","src/content/docs/frameworks/react.mdx","d127b4157c710b2d","frameworks/vue",{"id":261,"data":263,"body":269,"filePath":270,"digest":271,"deferredRender":16},{"title":264,"description":265,"editUrl":16,"head":266,"template":18,"sidebar":267,"pagefind":16,"draft":20},"Vue","Use REP with Vue 3 — useRep() and useRepSecure() composables with reactive refs.",[],{"hidden":20,"attrs":268},{},"import { Tabs, TabItem, Aside } from '@astrojs/starlight/components';\n\n## Installation\n\n```bash\nnpm install @rep-protocol/vue @rep-protocol/sdk\n```\n\n## Basic usage\n\n```vue\n\u003Cscript setup lang=\"ts\">\nimport { useRep, useRepSecure } from '@rep-protocol/vue';\n\n// PUBLIC tier — synchronous, reactive Ref\nconst apiUrl = useRep('API_URL', 'http://localhost:3000');\nconst flags = useRep('FEATURE_FLAGS', '');\n\n// SENSITIVE tier — async, resolves after session key fetch\nconst analyticsKey = useRepSecure('ANALYTICS_KEY');\n\u003C/script>\n\n\u003Ctemplate>\n \u003Cdiv>\n \u003Cp>API: {{ apiUrl }}\u003C/p>\n \u003Cp>Analytics: {{ analyticsKey ?? 'loading...' }}\u003C/p>\n \u003C/div>\n\u003C/template>\n```\n\n## `useRep(key, defaultValue?)`\n\nReads a **PUBLIC** tier variable as a reactive `Ref`.\n\n```typescript\nconst value: Ref\u003Cstring | undefined> = useRep('API_URL');\nconst value: Ref\u003Cstring | undefined> = useRep('API_URL', 'fallback');\n```\n\n- Returns a `Ref` set immediately from the injected payload\n- Automatically updates when the variable changes via hot reload\n- Unsubscribes via `onUnmounted` — must be called inside `setup()`\n\n## `useRepSecure(key)`\n\nReads a **SENSITIVE** tier variable as a reactive `Ref`.\n\n```typescript\nconst analyticsKey: Ref\u003Cstring | null> = useRepSecure('ANALYTICS_KEY');\n```\n\n- Starts as `null`\n- Resolves once the session key fetch and decryption complete\n- Errors are swallowed (the SDK logs them); the ref stays `null`\n- The decrypted value is cached for the page lifetime\n\n\u003CAside type=\"caution\">\n `useRepSecure` does **not** subscribe to hot reload. Sensitive variable changes require a page reload to obtain a new session key.\n\u003C/Aside>\n\n## Hot reload\n\n`useRep` subscribes to the SSE stream on mount and updates the ref automatically. The subscription is cleaned up when the component unmounts.\n\n## Development mode\n\n\u003CTabs>\n \u003CTabItem label=\"Default values\">\n ```typescript\n const apiUrl = useRep('API_URL', 'http://localhost:3000');\n ```\n \u003C/TabItem>\n \u003CTabItem label=\"Mock payload\">\n Add to your `index.html`:\n ```html\n \u003Cscript id=\"__rep__\" type=\"application/json\">\n {\"public\":{\"API_URL\":\"http://localhost:3000\"},\"_meta\":{\"version\":\"0.1.0\",\"injected_at\":\"2026-01-01T00:00:00Z\",\"integrity\":\"hmac-sha256:dev\",\"ttl\":0}}\n \u003C/script>\n ```\n \u003C/TabItem>\n\u003C/Tabs>\n\n## Requirements\n\n- Vue >= 3.0\n- `@rep-protocol/sdk` as a peer dependency\n- Composables must be called from `setup()` for proper `onUnmounted` cleanup\n\nFor the full API reference, see [Vue Adapter Reference](/reference/adapters/vue/).","src/content/docs/frameworks/vue.mdx","b44bad1f5af5708c","frameworks/svelte",{"id":272,"data":274,"body":280,"filePath":281,"digest":282,"deferredRender":16},{"title":275,"description":276,"editUrl":16,"head":277,"template":18,"sidebar":278,"pagefind":16,"draft":20},"Svelte","Use REP with Svelte — repStore() and repSecureStore() as Svelte readable stores.",[],{"hidden":20,"attrs":279},{},"import { Tabs, TabItem, Aside } from '@astrojs/starlight/components';\n\n## Installation\n\n```bash\nnpm install @rep-protocol/svelte @rep-protocol/sdk\n```\n\n## Basic usage\n\n```svelte\n\u003Cscript lang=\"ts\">\n import { repStore, repSecureStore } from '@rep-protocol/svelte';\n\n // PUBLIC tier — synchronous, updates on hot reload\n const apiUrl = repStore('API_URL', 'http://localhost:3000');\n const flags = repStore('FEATURE_FLAGS', '');\n\n // SENSITIVE tier — starts as null, resolves after decryption\n const analyticsKey = repSecureStore('ANALYTICS_KEY');\n\u003C/script>\n\n\u003Cp>API: {$apiUrl}\u003C/p>\n\u003Cp>Analytics: {$analyticsKey ?? 'loading...'}\u003C/p>\n```\n\n## `repStore(key, defaultValue?)`\n\nReads a **PUBLIC** tier variable as a Svelte `Readable\u003Cstring | undefined>`.\n\n```typescript\nconst value: Readable\u003Cstring | undefined> = repStore('API_URL');\nconst value: Readable\u003Cstring | undefined> = repStore('API_URL', 'fallback');\n```\n\n- Synchronous initial value from the REP payload\n- Automatically updates when the variable changes via hot reload\n- **Lazy SSE:** the connection is established only when there is at least one subscriber, and closed when all subscribers unsubscribe\n\n## `repSecureStore(key)`\n\nReads a **SENSITIVE** tier variable as a `Readable\u003Cstring | null>`.\n\n```typescript\nconst value: Readable\u003Cstring | null> = repSecureStore('ANALYTICS_KEY');\n```\n\n- Starts as `null`\n- Resolves to the decrypted value once the session key fetch completes\n- Errors are swallowed (the SDK logs them); the store stays `null`\n\n\u003CAside type=\"caution\">\n `repSecureStore` does **not** support hot reload. Changes to sensitive variables require a page reload.\n\u003C/Aside>\n\n## Hot reload\n\n`repStore` subscribes to the SSE stream lazily — only when there's at least one subscriber. The store value updates automatically. When the last subscriber unsubscribes, the SSE connection is closed.\n\n## Development mode\n\n\u003CTabs>\n \u003CTabItem label=\"Default values\">\n ```typescript\n const apiUrl = repStore('API_URL', 'http://localhost:3000');\n ```\n \u003C/TabItem>\n \u003CTabItem label=\"Mock payload\">\n Add to your `index.html`:\n ```html\n \u003Cscript id=\"__rep__\" type=\"application/json\">\n {\"public\":{\"API_URL\":\"http://localhost:3000\"},\"_meta\":{\"version\":\"0.1.0\",\"injected_at\":\"2026-01-01T00:00:00Z\",\"integrity\":\"hmac-sha256:dev\",\"ttl\":0}}\n \u003C/script>\n ```\n \u003C/TabItem>\n\u003C/Tabs>\n\n## Requirements\n\n- Svelte >= 4 or Svelte 5\n- `@rep-protocol/sdk` as a peer dependency\n\nFor the full API reference, see [Svelte Adapter Reference](/reference/adapters/svelte/).","src/content/docs/frameworks/svelte.mdx","2af3ad44dd245c53","frameworks/vanilla",{"id":283,"data":285,"body":291,"filePath":292,"digest":293,"deferredRender":16},{"title":286,"description":287,"editUrl":16,"head":288,"template":18,"sidebar":289,"pagefind":16,"draft":20},"Vanilla JS","Use REP without a framework — plain JavaScript, ESM import, no build tool required.",[],{"hidden":20,"attrs":290},{},"## Installation\n\n```bash\nnpm install @rep-protocol/sdk\n```\n\nOr use directly from your bundled assets without npm.\n\n## Basic usage\n\n```html\n\u003Cscript type=\"module\">\n import { rep } from '@rep-protocol/sdk';\n\n // PUBLIC tier — synchronous\n const apiUrl = rep.get('API_URL');\n document.getElementById('api-url').textContent = apiUrl;\n\n // SENSITIVE tier — async\n const key = await rep.getSecure('ANALYTICS_KEY');\n initAnalytics(key);\n\u003C/script>\n```\n\n## With hot reload\n\n```html\n\u003Cscript type=\"module\">\n import { rep } from '@rep-protocol/sdk';\n\n const el = document.getElementById('feature-flags');\n el.textContent = rep.get('FEATURE_FLAGS');\n\n // Update the DOM when config changes\n rep.onChange('FEATURE_FLAGS', (newValue) => {\n el.textContent = newValue;\n });\n\u003C/script>\n```\n\n## Integrity verification\n\n```html\n\u003Cscript type=\"module\">\n import { rep } from '@rep-protocol/sdk';\n\n if (!rep.verify()) {\n console.error('REP payload missing or tampered with');\n // Handle gracefully — show fallback UI, disable sensitive features\n }\n\n const meta = rep.meta();\n if (meta) {\n console.log('REP version:', meta.version);\n console.log('Injected at:', meta.injectedAt);\n console.log('Integrity valid:', meta.integrityValid);\n }\n\u003C/script>\n```\n\n## Development mode\n\nWithout the gateway, `rep.get()` returns `undefined`. Two options:\n\n**Option A: Check and use fallbacks**\n\n```javascript\nconst apiUrl = rep.get('API_URL') ?? 'http://localhost:3000';\n```\n\n**Option B: Mock payload in HTML**\n\n```html\n\u003Cscript id=\"__rep__\" type=\"application/json\">\n{\n \"public\": {\n \"API_URL\": \"http://localhost:3000\",\n \"FEATURE_FLAGS\": \"dark-mode,debug\"\n },\n \"_meta\": {\n \"version\": \"0.1.0\",\n \"injected_at\": \"2026-01-01T00:00:00Z\",\n \"integrity\": \"hmac-sha256:dev-mode-no-verification\",\n \"ttl\": 0\n }\n}\n\u003C/script>\n```\n\n## No build tool required\n\nREP works without any build tool. If you have a static HTML site with inline `\u003Cscript type=\"module\">` tags, just import the SDK from a CDN or self-hosted path:\n\n```html\n\u003Cscript type=\"module\">\n import { rep } from '/assets/rep-sdk.esm.js';\n // Use rep.get(), rep.getSecure(), etc.\n\u003C/script>\n```\n\nThe gateway injects the `\u003Cscript id=\"__rep__\">` payload into your HTML regardless of how your JavaScript is loaded.","src/content/docs/frameworks/vanilla.mdx","4c01f5eb4764edf4","reference/codemod",{"id":294,"data":296,"body":302,"filePath":303,"digest":304,"deferredRender":16},{"title":297,"description":298,"editUrl":16,"head":299,"template":18,"sidebar":300,"pagefind":16,"draft":20},"Codemod","Reference for @rep-protocol/codemod — automated migration from Vite, CRA, and Next.js.",[],{"hidden":20,"attrs":301},{},"```bash\nnpm install -D @rep-protocol/codemod\n# or\nnpx @rep-protocol/codemod [options] [files...]\n```\n\n## Usage\n\n```bash\nrep-codemod [options] [files or directories...]\n```\n\n## Options\n\n| Flag | Default | Description |\n|---|---|---|\n| `-f, --framework \u003Cname>` | `vite` | Framework preset: `vite`, `cra`, `next` |\n| `--dry-run` | `false` | Preview changes without writing files |\n| `--extensions \u003Clist>` | `ts,tsx,js,jsx` | Comma-separated file extensions to process |\n\n## Framework presets\n\n### `--framework vite`\n\nTransforms `import.meta.env.VITE_*` to `rep.get('*')`:\n\n```typescript\n// Before\nconst apiUrl = import.meta.env.VITE_API_URL;\n\n// After\nimport { rep } from '@rep-protocol/sdk';\nconst apiUrl = rep.get('API_URL');\n```\n\nVite built-ins (`MODE`, `DEV`, `PROD`, `SSR`, `BASE_URL`) are left untouched.\n\n### `--framework cra`\n\nTransforms `process.env.REACT_APP_*` to `rep.get('*')`:\n\n```typescript\n// Before\nconst apiUrl = process.env.REACT_APP_API_URL;\n\n// After\nimport { rep } from '@rep-protocol/sdk';\nconst apiUrl = rep.get('API_URL');\n```\n\n### `--framework next`\n\nTransforms `process.env.NEXT_PUBLIC_*` to `rep.get('*')`:\n\n```typescript\n// Before\nconst apiUrl = process.env.NEXT_PUBLIC_API_URL;\n\n// After\nimport { rep } from '@rep-protocol/sdk';\nconst apiUrl = rep.get('API_URL');\n```\n\n## Examples\n\n```bash\n# Transform Vite project\nrep-codemod --framework vite src/\n\n# Dry run — preview changes\nrep-codemod --framework cra --dry-run src/components/\n\n# Specific files\nrep-codemod --framework next src/app/page.tsx src/lib/api.ts\n\n# JavaScript files only\nrep-codemod --framework vite --extensions js,jsx src/\n```\n\n## Behavior\n\n- **Idempotent** — running twice produces the same result\n- **Import management** — adds `import { rep } from '@rep-protocol/sdk'` if absent\n- **Non-destructive** — only prefixed variables are transformed\n- **Format-preserving** — original formatting and comments are preserved (via jscodeshift/recast)\n\n## Post-migration steps\n\n1. Remove framework-specific type augmentations (e.g., `vite-env.d.ts`)\n2. Run `rep typegen` to generate typed overloads\n3. Update container config to set `REP_PUBLIC_*` environment variables","src/content/docs/reference/codemod.mdx","7342cb325938aa8d","reference/cli",{"id":305,"data":307,"body":313,"filePath":314,"digest":315,"deferredRender":16},{"title":308,"description":309,"editUrl":16,"head":310,"template":18,"sidebar":311,"pagefind":16,"draft":20},"CLI Commands","Complete reference for the @rep-protocol/cli tool — validate, typegen, lint, dev.",[],{"hidden":20,"attrs":312},{},"```bash\nnpm install -g @rep-protocol/cli\n# or\nnpx @rep-protocol/cli [command]\n```\n\n## `rep validate`\n\nValidate a `.rep.yaml` manifest against the JSON schema.\n\n```bash\nrep validate [--manifest \u003Cpath>]\n```\n\n| Flag | Default | Description |\n|---|---|---|\n| `-m, --manifest \u003Cpath>` | `.rep.yaml` | Path to manifest file |\n\n**Example:**\n```bash\n$ rep validate --manifest .rep.yaml\n✓ Manifest is valid\n Version: 0.1.0\n Variables: 11 total\n - PUBLIC: 6\n - SENSITIVE: 3\n - SERVER: 2\n Settings configured: 6\n```\n\n## `rep typegen`\n\nGenerate TypeScript type definitions from a manifest. Creates strongly-typed overloads for `rep.get()` and `rep.getSecure()`.\n\n```bash\nrep typegen [--manifest \u003Cpath>] [--output \u003Cpath>]\n```\n\n| Flag | Default | Description |\n|---|---|---|\n| `-m, --manifest \u003Cpath>` | `.rep.yaml` | Path to manifest file |\n| `-o, --output \u003Cpath>` | `src/rep.d.ts` | Output path for generated types |\n\n**Generated output:**\n```typescript\ndeclare module \"@rep-protocol/sdk\" {\n export interface REP {\n get(key: \"API_URL\" | \"FEATURE_FLAGS\"): string | undefined;\n getSecure(key: \"ANALYTICS_KEY\"): Promise\u003Cstring>;\n // ... other methods\n }\n}\n```\n\n## `rep lint`\n\nScan built JavaScript bundles for accidentally leaked secrets. Uses the same guardrail detection as the gateway (Shannon entropy, known secret formats).\n\n```bash\nrep lint [--dir \u003Cpath>] [--pattern \u003Cglob>] [--strict]\n```\n\n| Flag | Default | Description |\n|---|---|---|\n| `-d, --dir \u003Cpath>` | `./dist` | Directory to scan |\n| `--pattern \u003Cglob>` | `**/*.{js,mjs,cjs}` | File pattern to scan |\n| `--strict` | `false` | Exit with error code if warnings found |\n\n**Example:**\n```bash\n$ rep lint --dir ./dist\n⚠ dist/main.js\n high_entropy:42: value has high entropy (5.23 bits/char) — may be a secret\n const key = \"sk_live_abc123...\"\n\n⚠ Found 1 potential secret(s) in 1 file(s)\n```\n\n**Use cases:**\n- CI/CD pipeline step before deployment\n- Pre-commit hook\n- Regular audits of production bundles\n\n## `rep dev`\n\nRun a local development server with the REP gateway. Loads env vars from a file and starts the gateway.\n\n```bash\nrep dev [options]\n```\n\n| Flag | Default | Description |\n|---|---|---|\n| `-e, --env \u003Cpath>` | `.env.local` | Path to .env file |\n| `-p, --port \u003Cnumber>` | `8080` | Gateway port |\n| `--proxy \u003Curl>` | — | Upstream proxy URL (e.g., `http://localhost:5173`) |\n| `--static \u003Cpath>` | — | Serve static files (embedded mode) |\n| `--hot-reload` | `false` | Enable hot reload |\n| `--gateway-bin \u003Cpath>` | auto | Path to gateway binary |\n\n**Example workflows:**\n\n```bash\n# Proxy mode with Vite\nrep dev --env .env.local --proxy http://localhost:5173\n\n# Embedded mode with static files\nrep dev --env .env.local --static ./dist --port 8080\n```\n\n## Binary resolution\n\nThe CLI looks for the gateway binary in this order:\n\n1. Bundled binary (downloaded during `npm install`)\n2. Custom path via `--gateway-bin`\n3. `rep-gateway` in system `PATH`","src/content/docs/reference/cli.mdx","7960b686fb5e5300","reference/gateway-endpoints",{"id":316,"data":318,"body":324,"filePath":325,"digest":326,"deferredRender":16},{"title":319,"description":320,"editUrl":16,"head":321,"template":18,"sidebar":322,"pagefind":16,"draft":20},"Gateway Endpoints","Reference for /rep/health, /rep/session-key, and /rep/changes endpoints.",[],{"hidden":20,"attrs":323},{},"import { Aside } from '@astrojs/starlight/components';\n\n## `GET /rep/health`\n\nReturns gateway health status including variable counts and guardrail status.\n\n**Response:**\n```json\n{\n \"status\": \"healthy\",\n \"version\": \"0.1.0\",\n \"variables\": {\n \"public\": 3,\n \"sensitive\": 1,\n \"server\": 2\n },\n \"guardrails\": {\n \"warnings\": 0,\n \"blocked\": 0\n },\n \"uptime_seconds\": 3421\n}\n```\n\n**Use cases:**\n- Kubernetes liveness/readiness probes\n- Load balancer health checks\n- Monitoring dashboards\n\n**Kubernetes probe example:**\n```yaml\nlivenessProbe:\n httpGet:\n path: /rep/health\n port: 8080\n initialDelaySeconds: 5\nreadinessProbe:\n httpGet:\n path: /rep/health\n port: 8080\n initialDelaySeconds: 2\n```\n\nUse `--health-port` to serve the health endpoint on a separate port (e.g., `9090`) to keep it internal to the cluster.\n\n## `GET /rep/session-key`\n\nIssues a short-lived decryption key for SENSITIVE tier variables. Called by the SDK's `getSecure()` method.\n\n**Request requirements:**\n- Must include an `Origin` header matching configured allowed origins (if origins are configured)\n- If no allowed origins are configured, same-origin requests are permitted\n\n**Response:**\n```json\n{\n \"key\": \"{base64_encoded_derived_aes_key}\",\n \"expires_at\": \"2026-02-18T14:30:30.000Z\"\n}\n```\n\n| Field | Description |\n|---|---|\n| `key` | HKDF-derived AES-256 encryption key, base64-encoded |\n| `expires_at` | RFC 3339 timestamp — key expires 30 seconds after issuance |\n\n**Security constraints:**\n- Keys expire within 30 seconds\n- Rate-limited to 10 requests per minute per client IP\n- Not cacheable (`Cache-Control: no-store, no-cache, must-revalidate`)\n- CORS restricted to configured origins\n- All issuances are audit-logged (`rep.session_key.issued`)\n\n**Error responses:**\n- `429 Too Many Requests` — rate limit exceeded\n- `403 Forbidden` — origin not allowed\n- `404 Not Found` — no SENSITIVE variables configured\n\n\u003CAside type=\"caution\">\n The session key is the derived key, not the master key material. Even if intercepted, it cannot be used to derive the master key or generate new session keys.\n\u003C/Aside>\n\n## `GET /rep/changes`\n\nServer-Sent Events (SSE) stream that pushes configuration updates to connected clients. Only available when `--hot-reload` is enabled.\n\n**Event format:**\n\n```\nevent: rep:config:update\ndata: {\"key\": \"FEATURE_FLAGS\", \"tier\": \"public\", \"value\": \"dark-mode,ai-assist\"}\nid: 1708267830000\n\nevent: rep:config:delete\ndata: {\"key\": \"DEPRECATED_FLAG\", \"tier\": \"public\"}\nid: 1708267831000\n```\n\n**Event types:**\n\n| Event | Description |\n|---|---|\n| `rep:config:update` | A variable's value changed or a new variable was added |\n| `rep:config:delete` | A variable was removed |\n\n**Behavior:**\n- SSE has built-in reconnection — the browser automatically reconnects on disconnect\n- The `id` field allows replay of missed events\n- Returns `404 Not Found` if hot reload is not enabled\n- Only PUBLIC tier changes are broadcast (SENSITIVE changes require a page reload)","src/content/docs/reference/gateway-endpoints.mdx","164f5b359e1b3e23","reference/manifest-schema",{"id":327,"data":329,"body":335,"filePath":336,"digest":337,"deferredRender":16},{"title":330,"description":331,"editUrl":16,"head":332,"template":18,"sidebar":333,"pagefind":16,"draft":20},"Manifest Schema","Complete reference for the .rep.yaml manifest file format.",[],{"hidden":20,"attrs":334},{},"The manifest schema is published as JSON Schema at [`/schema/rep-manifest.schema.json`](/schema/rep-manifest.schema.json).\n\n## Top-level fields\n\n```yaml\nversion: \"0.1.0\" # Required — protocol version\nvariables: { ... } # Required — variable declarations\nsettings: { ... } # Optional — gateway settings\n```\n\n## Variable declaration\n\nEach variable is declared under the `variables` map using its **stripped** name (e.g., `API_URL`, not `REP_PUBLIC_API_URL`):\n\n```yaml\nvariables:\n API_URL:\n tier: public # Required: public, sensitive, or server\n type: url # Required: string, url, number, boolean, csv, json, enum\n required: true # Optional (default: false)\n default: \"\" # Optional — default value if not provided\n description: \"...\" # Optional — human-readable description\n example: \"...\" # Optional — example value\n pattern: \"^...\" # Optional — regex pattern the value must match\n values: [...] # Optional — allowed values (enum type only)\n deprecated: false # Optional — mark as deprecated\n deprecated_message: \"Use NEW_VAR instead\" # Optional\n```\n\n### Field reference\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `tier` | `public` \\| `sensitive` \\| `server` | Yes | Security classification tier |\n| `type` | see types table | Yes | Value type constraint |\n| `required` | `boolean` | No | Must be present at startup (default: `false`) |\n| `default` | `string` | No | Default value when variable is absent |\n| `description` | `string` | No | Human-readable purpose |\n| `example` | `string` | No | Example value for documentation |\n| `pattern` | `string` | No | Regex the value must match |\n| `values` | `string[]` | No | Allowed values (for `enum` type) |\n| `deprecated` | `boolean` | No | Mark as deprecated |\n| `deprecated_message` | `string` | No | Migration guidance |\n\n### Supported types\n\n| Type | Validation | Example |\n|---|---|---|\n| `string` | Any string | `\"hello\"` |\n| `url` | Valid URL (RFC 3986) | `\"https://api.example.com\"` |\n| `number` | Parses as finite number | `\"42\"`, `\"3.14\"` |\n| `boolean` | `\"true\"`, `\"false\"`, `\"1\"`, `\"0\"` | `\"true\"` |\n| `csv` | Comma-separated string | `\"a,b,c\"` |\n| `json` | Valid JSON | `'{\"key\":\"val\"}'` |\n| `enum` | Matches `values` array | `\"production\"` |\n\n## Settings\n\n```yaml\nsettings:\n strict_guardrails: true\n hot_reload: true\n hot_reload_mode: \"signal\"\n hot_reload_poll_interval: \"30s\"\n session_key_ttl: \"30s\"\n session_key_max_rate: 10\n allowed_origins:\n - \"https://app.example.com\"\n```\n\n| Setting | Type | Default | Description |\n|---|---|---|---|\n| `strict_guardrails` | `boolean` | `false` | Fail on guardrail warnings |\n| `hot_reload` | `boolean` | `false` | Enable hot reload SSE |\n| `hot_reload_mode` | `string` | `signal` | `file_watch`, `signal`, or `poll` |\n| `hot_reload_poll_interval` | `string` | `30s` | Poll interval (Go duration format) |\n| `session_key_ttl` | `string` | `30s` | Session key expiry duration |\n| `session_key_max_rate` | `integer` | `10` | Max session key requests/min/IP |\n| `allowed_origins` | `string[]` | `[]` | CORS origins for session key endpoint |\n\n## Full example\n\nSee [`examples/.rep.yaml`](https://github.com/ruachtech/rep/blob/main/examples/.rep.yaml) for an annotated manifest with all tiers and types.","src/content/docs/reference/manifest-schema.mdx","5c443a4c90639bfb","reference/sdk",{"id":338,"data":340,"body":346,"filePath":347,"digest":348,"deferredRender":16},{"title":341,"description":342,"editUrl":16,"head":343,"template":18,"sidebar":344,"pagefind":16,"draft":20},"SDK API","Complete API reference for @rep-protocol/sdk.",[],{"hidden":20,"attrs":345},{},"import { Aside } from '@astrojs/starlight/components';\n\n`@rep-protocol/sdk` — Zero-dependency, framework-agnostic TypeScript SDK for reading REP-injected environment variables.\n\n```bash\nnpm install @rep-protocol/sdk\n```\n\n## `get(key)`\n\nRetrieve a PUBLIC tier variable. Synchronous — no network call, no promise.\n\n```typescript\nfunction get(key: string): string | undefined;\nfunction get(key: string, defaultValue: string): string;\n```\n\n| Parameter | Type | Description |\n|---|---|---|\n| `key` | `string` | Variable name (after prefix stripping, e.g. `'API_URL'`) |\n| `defaultValue` | `string` | Optional fallback if the variable is not present |\n\n**Returns:** The variable value, `defaultValue`, or `undefined`.\n\n```typescript\nimport { rep } from '@rep-protocol/sdk';\n\nconst apiUrl = rep.get('API_URL'); // string | undefined\nconst apiUrl = rep.get('API_URL', 'http://localhost'); // string (never undefined)\n```\n\n## `getSecure(key)`\n\nRetrieve a SENSITIVE tier variable. Fetches a session key, decrypts the blob, and caches all sensitive values.\n\n```typescript\nfunction getSecure(key: string): Promise\u003Cstring>;\n```\n\n| Parameter | Type | Description |\n|---|---|---|\n| `key` | `string` | Variable name (e.g. `'ANALYTICS_KEY'`) |\n\n**Returns:** `Promise\u003Cstring>` — the decrypted value.\n\n**Throws:** `REPError` if the session key endpoint is unreachable, the key has expired, or decryption fails.\n\n```typescript\nconst key = await rep.getSecure('ANALYTICS_KEY');\n```\n\n\u003CAside>\n The first `getSecure()` call fetches a session key and decrypts **all** sensitive variables at once. Subsequent calls for different keys return from the in-memory cache without network requests.\n\u003C/Aside>\n\n## `getAll()`\n\nRetrieve all PUBLIC tier variables as a frozen object.\n\n```typescript\nfunction getAll(): Readonly\u003CRecord\u003Cstring, string>>;\n```\n\n**Returns:** A frozen `Record\u003Cstring, string>` of all public variables. Empty object if no payload is present.\n\n```typescript\nconst allVars = rep.getAll();\nconsole.log(allVars.API_URL);\n```\n\n## `verify()`\n\nCheck whether the REP payload is present and its integrity is valid.\n\n```typescript\nfunction verify(): boolean;\n```\n\n**Returns:** `true` if the payload is present, parseable, and the SRI hash matches. `false` if missing, malformed, or tampered.\n\n```typescript\nif (!rep.verify()) {\n console.error('REP payload missing or tampered');\n}\n```\n\n## `meta()`\n\nReturns metadata about the current REP payload.\n\n```typescript\nfunction meta(): REPMeta | null;\n\ninterface REPMeta {\n version: string;\n injectedAt: Date;\n integrityValid: boolean;\n publicCount: number;\n sensitiveAvailable: boolean;\n hotReloadAvailable: boolean;\n}\n```\n\n**Returns:** `REPMeta` object, or `null` if no payload is present.\n\n```typescript\nconst m = rep.meta();\nif (m) {\n console.log('REP version:', m.version);\n console.log('Injected at:', m.injectedAt);\n console.log('Public vars:', m.publicCount);\n}\n```\n\n## `onChange(key, callback)`\n\nRegister a callback for when a specific variable changes via hot reload.\n\n```typescript\nfunction onChange(\n key: string,\n callback: (newValue: string, oldValue: string | undefined) => void\n): () => void;\n```\n\n**Returns:** An unsubscribe function. Call it to stop listening.\n\nThe SSE connection is established lazily on the first `onChange()` or `onAnyChange()` call. It is closed when all listeners have been removed.\n\n```typescript\nconst unsub = rep.onChange('FEATURE_FLAGS', (newValue, oldValue) => {\n console.log(`Changed: ${oldValue} → ${newValue}`);\n});\n\n// Later:\nunsub();\n```\n\n## `onAnyChange(callback)`\n\nRegister a callback for any variable change.\n\n```typescript\nfunction onAnyChange(\n callback: (key: string, newValue: string, oldValue: string | undefined) => void\n): () => void;\n```\n\n**Returns:** An unsubscribe function.\n\n```typescript\nconst unsub = rep.onAnyChange((key, newValue) => {\n console.log(`${key} updated to ${newValue}`);\n});\n```\n\n## `REPError`\n\nCustom error class thrown by SDK operations.\n\n```typescript\nclass REPError extends Error {\n name: 'REPError';\n}\n```\n\nThrown by `getSecure()` when the session key endpoint is unreachable, the key has expired, or decryption fails.\n\n## Import styles\n\nBoth named exports and a namespace object are available:\n\n```typescript\n// Named imports\nimport { get, getSecure, verify, onChange } from '@rep-protocol/sdk';\n\n// Namespace import (recommended)\nimport { rep } from '@rep-protocol/sdk';\nrep.get('API_URL');\n```\n\n## Initialization behavior\n\nOn import, the SDK synchronously:\n\n1. Locates `\u003Cscript id=\"__rep__\">` in the DOM\n2. Parses the JSON content\n3. Triggers async SRI verification (non-blocking)\n4. Freezes the `public` object\n5. Sets `_available` and `_tampered` internal flags\n\nNo network calls are made during initialization.","src/content/docs/reference/sdk.mdx","f26ece21c35cf013","reference/gateway-flags",{"id":349,"data":351,"body":357,"filePath":358,"digest":359,"deferredRender":16},{"title":352,"description":353,"editUrl":16,"head":354,"template":18,"sidebar":355,"pagefind":16,"draft":20},"Gateway Flags","All CLI flags and environment variables for configuring the REP gateway.",[],{"hidden":20,"attrs":356},{},"The gateway is configured via command-line flags or environment variables. Flags take precedence over env vars.\n\n## Command-line flags\n\n```\nrep-gateway [flags]\n```\n\n| Flag | Default | Description |\n|---|---|---|\n| `--mode` | `proxy` | Operating mode: `proxy` or `embedded` |\n| `--upstream` | `localhost:80` | Upstream server address (proxy mode only) |\n| `--port` | `8080` | Listen port |\n| `--static-dir` | `/usr/share/nginx/html` | Static file directory (embedded mode only) |\n| `--manifest` | — | Path to `.rep.yaml` manifest file |\n| `--env-file` | — | Path to `.env` file (env vars take precedence) |\n| `--strict` | `false` | Exit on guardrail warnings |\n| `--hot-reload` | `false` | Enable hot reload SSE endpoint |\n| `--hot-reload-mode` | `signal` | Detection mode: `file_watch`, `signal`, `poll` |\n| `--watch-path` | — | Path to watch for changes (file_watch mode) |\n| `--poll-interval` | `30s` | Config poll interval (poll mode) |\n| `--log-format` | `json` | Log format: `json` or `text` |\n| `--log-level` | `info` | Log level: `debug`, `info`, `warn`, `error` |\n| `--allowed-origins` | — | Comma-separated CORS origins for `/rep/session-key` |\n| `--tls-cert` | — | Path to TLS certificate |\n| `--tls-key` | — | Path to TLS private key |\n| `--health-port` | — | Separate port for health check endpoint |\n\n## Environment variables\n\nEvery flag can be set via environment variable with the `REP_GATEWAY_` prefix:\n\n```bash\nREP_GATEWAY_MODE=proxy\nREP_GATEWAY_UPSTREAM=localhost:80\nREP_GATEWAY_PORT=8080\nREP_GATEWAY_STRICT=true\nREP_GATEWAY_HOT_RELOAD=true\nREP_GATEWAY_HOT_RELOAD_MODE=signal\nREP_GATEWAY_LOG_FORMAT=json\nREP_GATEWAY_LOG_LEVEL=info\nREP_GATEWAY_ALLOWED_ORIGINS=https://app.example.com,https://staging.example.com\n```\n\n## Precedence order\n\n1. Command-line flags (highest)\n2. Environment variables (`REP_GATEWAY_*`)\n3. Manifest file settings (lowest)\n\n## Common configurations\n\n### Proxy mode (development)\n\n```bash\nrep-gateway \\\n --mode proxy \\\n --upstream localhost:5173 \\\n --port 8080 \\\n --hot-reload\n```\n\n### Embedded mode (production)\n\n```bash\nrep-gateway \\\n --mode embedded \\\n --static-dir /static \\\n --port 8080 \\\n --strict \\\n --log-format json \\\n --allowed-origins https://app.example.com\n```\n\n### Kubernetes sidecar\n\n```bash\nrep-gateway \\\n --mode proxy \\\n --upstream localhost:80 \\\n --port 8080 \\\n --strict \\\n --hot-reload \\\n --hot-reload-mode file_watch \\\n --watch-path /config \\\n --health-port 9090\n```","src/content/docs/reference/gateway-flags.mdx","9140bbf8b7a715f2","spec/conformance",{"id":360,"data":362,"body":368,"filePath":369,"digest":370,"deferredRender":16},{"title":363,"description":364,"editUrl":16,"head":365,"template":18,"sidebar":366,"pagefind":16,"draft":20},"Conformance","Requirements for REP-conformant gateway and SDK implementations.",[],{"hidden":20,"attrs":367},{},"An implementation is **REP-conformant** if it satisfies the requirements below. This page is extracted from REP-RFC-0001 Section 11.\n\n## Gateway conformance (MUST)\n\nA conformant gateway implementation MUST:\n\n1. Read only `REP_*` prefixed environment variables\n2. Classify variables into exactly three tiers based on prefix (`PUBLIC`, `SENSITIVE`, `SERVER`)\n3. Strip the classification prefix from variable names in the payload\n4. Reject startup if variable names collide after prefix stripping\n5. Run secret detection guardrails on PUBLIC tier variables\n6. Inject a `\u003Cscript id=\"__rep__\" type=\"application/json\">` block into HTML responses\n7. Compute and include an HMAC-SHA256 integrity token\n8. Encrypt SENSITIVE tier variables using AES-256-GCM\n9. Issue single-use, time-limited session keys via `/rep/session-key`\n10. Never transmit SERVER tier variables to the client under any circumstances\n\n## Client SDK conformance (MUST)\n\nA conformant SDK implementation MUST:\n\n1. Read from `\u003Cscript id=\"__rep__\">` synchronously on import\n2. Verify payload integrity on initialization (SRI hash)\n3. Expose `get()` as a synchronous function\n4. Expose `getSecure()` as an async function\n5. Make no network calls during initialization\n6. Freeze the public variable object to prevent mutation\n\n## Optional features (MAY)\n\nConformant implementations MAY implement:\n\n1. Hot reload via Server-Sent Events\n2. Manifest file validation at startup\n3. TypeScript type generation from manifest\n4. Framework-specific adapters (React hooks, Vue composables, Svelte stores)\n5. Codemod tooling for migration\n\n## Notes\n\n- \"MUST\", \"SHOULD\", and \"MAY\" follow [RFC 2119](https://tools.ietf.org/html/rfc2119) conventions\n- The reference implementation (gateway in Go, SDK in TypeScript) satisfies all MUST requirements and implements all optional features\n- Alternative implementations need only satisfy the MUST requirements to be conformant","src/content/docs/spec/conformance.mdx","a3553c0b066f5a7a","spec/rfc-0001",{"id":371,"data":373,"body":379,"filePath":380,"digest":381,"deferredRender":16},{"title":374,"description":375,"editUrl":16,"head":376,"template":18,"sidebar":377,"pagefind":16,"draft":20},"REP-RFC-0001","Core protocol specification — Runtime Environment Protocol v0.1.0.",[],{"hidden":20,"attrs":378},{},"import { Aside, LinkCard } from '@astrojs/starlight/components';\n\n```\nTitle: Runtime Environment Protocol (REP)\nVersion: 0.1.0\nStatus: Active\nAuthors: Olamide Adebayo (Ruach Tech)\nCreated: 2026-02-18\nLicense: CC BY 4.0\n```\n\n\u003CAside>\n This is the formal specification. For a practical introduction, see [How REP Works](/concepts/how-it-works/) and the [Quick Start](/quick-start/).\n\u003C/Aside>\n\n## Abstract\n\nThis document specifies the **Runtime Environment Protocol (REP)**, a standardised method for injecting environment variables into browser-hosted applications at container startup rather than at build time. REP introduces a three-tier security classification system, cryptographic integrity verification, and an optional hot-reload mechanism.\n\nREP operates at the infrastructure layer. It requires no build-tool plugins, no framework-specific adapters, and no changes to the application's build process.\n\n## Sections\n\nThe full specification covers 14 sections. Key topics are documented separately in the docs site:\n\n\u003CLinkCard title=\"Variable Classification\" href=\"/concepts/variable-classification/\" description=\"§3 — Three-tier system, classification rules, guardrails\" />\n\u003CLinkCard title=\"How REP Works\" href=\"/concepts/how-it-works/\" description=\"§4 — Gateway architecture, startup sequence, HTML injection\" />\n\u003CLinkCard title=\"SDK API Reference\" href=\"/reference/sdk/\" description=\"§5 — Core API, initialization behavior, type generation\" />\n\u003CLinkCard title=\"Manifest File\" href=\"/guides/manifest/\" description=\"§6 — .rep.yaml schema, supported types, settings\" />\n\u003CLinkCard title=\"Gateway Flags\" href=\"/reference/gateway-flags/\" description=\"§7 — CLI flags and environment variable configuration\" />\n\u003CLinkCard title=\"Wire Format\" href=\"/concepts/wire-format/\" description=\"§8 — Payload JSON, encrypted blob, HMAC integrity\" />\n\u003CLinkCard title=\"Deployment Patterns\" href=\"/deployment/docker-embedded/\" description=\"§9 — Docker, Kubernetes, sidecar patterns\" />\n\u003CLinkCard title=\"Migration\" href=\"/guides/migration/overview/\" description=\"§10 — Incremental adoption, codemod tool\" />\n\u003CLinkCard title=\"Conformance\" href=\"/spec/conformance/\" description=\"§11 — Gateway and SDK conformance requirements\" />\n\n## Design requirements\n\n| ID | Requirement |\n|---|---|\n| R1 | **Build-tool agnostic.** Must work with any frontend framework or bundler without build-time plugins. |\n| R2 | **Security-classified.** Must distinguish between public, sensitive, and server-only variables. |\n| R3 | **Integrity-verified.** The injected configuration must be verifiable by the client SDK. |\n| R4 | **Synchronously accessible.** Public variables must be available immediately on page load. |\n| R5 | **Zero application dependencies.** The client SDK must have zero runtime dependencies. |\n| R6 | **Minimal footprint.** Gateway under 5MB, SDK under 2KB gzipped. |\n| R7 | **Container-native.** Must integrate with Docker and Kubernetes via standard env vars. |\n| R8 | **Incrementally adoptable.** Must not require all-or-nothing migration. |\n| R9 | **Observable.** Must emit structured logs and metrics for injection events. |\n| R10 | **Hot-reloadable (optional).** Must support live config updates without page reload. |\n\n## Comparison with existing solutions\n\n| Feature | `envsubst` | `runtime-env-cra` | `@import-meta-env` | `react-env` | **REP** |\n|---|:---:|:---:|:---:|:---:|:---:|\n| Framework agnostic | Yes | No | Partial | No | **Yes** |\n| No build tool plugin | Yes | No | No | No | **Yes** |\n| Security classification | -- | -- | -- | -- | **Yes** |\n| Encrypted sensitive vars | -- | -- | -- | -- | **Yes** |\n| Integrity verification | -- | -- | -- | -- | **Yes** |\n| Secret leak detection | -- | -- | -- | -- | **Yes** |\n| Hot reload | -- | -- | -- | -- | **Yes** |\n| No Node.js in prod | Partial | No | No | No | **Yes** |\n| Formal specification | -- | -- | -- | -- | **Yes** |\n| `FROM scratch` compatible | -- | -- | -- | -- | **Yes** |\n\n## FAQ\n\n**Q: Why not use a service mesh / API gateway?**\nService meshes operate at L4/L7 for service-to-service communication. They don't inject configuration into HTML. REP is complementary.\n\n**Q: Why not use SSR frameworks that support runtime env vars?**\nSSR solves this for supported frameworks, but not all apps need SSR, it couples you to a specific framework, and many organisations have existing SPAs. REP works with any SPA.\n\n**Q: Isn't the SENSITIVE tier just security through obscurity?**\nPartially — see the [Security Model](/spec/security-model/) for an honest assessment. SENSITIVE raises the bar against casual exposure while making intentional access auditable. For true secrets, use the SERVER tier.\n\n---\n\nThe full source of REP-RFC-0001 is available at [`spec/REP-RFC-0001.md`](https://github.com/ruachtech/rep/blob/main/spec/REP-RFC-0001.md).","src/content/docs/spec/rfc-0001.mdx","f234ea27c39cfccb","spec",{"id":382,"data":384,"body":390,"filePath":391,"digest":392,"deferredRender":16},{"title":385,"description":386,"editUrl":16,"head":387,"template":18,"sidebar":388,"pagefind":16,"draft":20},"Specification Overview","REP formal specification documents — RFC, Security Model, and Conformance.",[],{"hidden":20,"attrs":389},{},"REP is defined by three specification documents. They are the authoritative reference for the protocol, its security properties, and its conformance requirements.\n\n## Documents\n\n| Document | Status | Version | Description |\n|---|---|---|---|\n| [REP-RFC-0001](/spec/rfc-0001/) | Active | 0.1.0 | Core protocol specification — variable classification, gateway architecture, SDK API, wire format, deployment patterns |\n| [Security Model](/spec/security-model/) | Active | 0.1.0 | Threat model, 7 threat analyses, hardening recommendations, known limitations |\n| [Conformance](/spec/conformance/) | Active | 0.1.0 | Requirements for conformant gateway and SDK implementations |\n\n## Versioning policy\n\nThe specification uses semantic versioning:\n\n- **Patch** (0.1.x): Clarifications, typo fixes, non-normative additions\n- **Minor** (0.x.0): New optional features, backwards-compatible extensions\n- **Major** (x.0.0): Breaking changes to the wire format, API surface, or security model\n\nThe current version (0.1.0) indicates the specification is active and subject to refinement based on implementation experience. Breaking changes are possible before 1.0.\n\n## License\n\nSpecification documents are licensed under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/). Reference implementations (gateway, SDK, CLI, adapters) are licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0).\n\n## JSON schemas\n\nMachine-readable schemas are published for integration and validation:\n\n- [Payload schema](/schema/rep-payload.schema.json) — validates the injected `\u003Cscript>` JSON\n- [Manifest schema](/schema/rep-manifest.schema.json) — validates `.rep.yaml` files\n\n## References\n\n- [The Twelve-Factor App — Factor III: Config](https://12factor.net/config)\n- [OCI Image Specification](https://github.com/opencontainers/image-spec)\n- [RFC 5869 — HKDF](https://tools.ietf.org/html/rfc5869)\n- [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto)\n- [Subresource Integrity (SRI)](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity)\n- [Server-Sent Events](https://html.spec.whatwg.org/multipage/server-sent-events.html)\n- [Content Security Policy Level 3](https://www.w3.org/TR/CSP3/)","src/content/docs/spec/index.mdx","10b24beb25918f6e","spec/security-model",{"id":393,"data":395,"body":401,"filePath":402,"digest":403,"deferredRender":16},{"title":396,"description":397,"editUrl":16,"head":398,"template":18,"sidebar":399,"pagefind":16,"draft":20},"Security Model Specification","Formal threat model and security analysis for the Runtime Environment Protocol.",[],{"hidden":20,"attrs":400},{},"import { Aside, LinkCard } from '@astrojs/starlight/components';\n\n```\nDocument: REP Security Model\nVersion: 0.1.0\nStatus: Active\nAuthors: Olamide Adebayo (Ruach Tech)\nLicense: CC BY 4.0\n```\n\n\u003CAside>\n For a practical guide to REP's security properties, see [Security Model (Concepts)](/concepts/security-model/). This page is the formal specification document.\n\u003C/Aside>\n\n\u003CLinkCard title=\"Security Model (Concepts)\" href=\"/concepts/security-model/\" description=\"Practical guide — threat analysis, hardening, monitoring recommendations\" />\n\nThe concepts page contains the full content of this specification, reformatted for easier navigation. It covers:\n\n- Fundamental axiom and trust boundaries\n- All 7 threat analyses (T1-T7) with severity, mitigations, and residual risk\n- Variable classification decision tree with common misclassifications\n- Production hardening recommendations (gateway config, FROM scratch Dockerfile, CSP headers)\n- Monitoring and alerting setup\n- Known limitations\n\n---\n\nThe full source document is at [`spec/SECURITY-MODEL.md`](https://github.com/ruachtech/rep/blob/main/spec/SECURITY-MODEL.md).","src/content/docs/spec/security-model.mdx","3da28bb9be80115e","guides/migration/from-cra",{"id":404,"data":406,"body":412,"filePath":413,"digest":414,"deferredRender":16},{"title":407,"description":408,"editUrl":16,"head":409,"template":18,"sidebar":410,"pagefind":16,"draft":20},"From Create React App","Migrate from CRA's process.env.REACT_APP_* to REP.",[],{"hidden":20,"attrs":411},{},"## Automated migration\n\n```bash\nnpx @rep-protocol/codemod --framework cra src/\n```\n\n### What it transforms\n\n```typescript\n// Before\nconst apiUrl = process.env.REACT_APP_API_URL;\nconst flags = process.env.REACT_APP_FEATURE_FLAGS;\n\n// After\nimport { rep } from '@rep-protocol/sdk';\nconst apiUrl = rep.get('API_URL');\nconst flags = rep.get('FEATURE_FLAGS');\n```\n\nOnly `REACT_APP_*` prefixed variables are transformed. Other `process.env.*` access is left unchanged.\n\n### Preview first\n\n```bash\nnpx @rep-protocol/codemod --framework cra --dry-run src/\n```\n\n## Manual migration\n\n1. **Rename environment variables:**\n ```bash\n REACT_APP_API_URL → REP_PUBLIC_API_URL\n REACT_APP_ANALYTICS_KEY → REP_SENSITIVE_ANALYTICS_KEY\n ```\n\n2. **Update code:**\n ```typescript\n import { rep } from '@rep-protocol/sdk';\n const apiUrl = rep.get('API_URL', 'http://localhost:3000');\n ```\n\n3. **Install the SDK:**\n ```bash\n npm install @rep-protocol/sdk\n ```\n\n## Post-migration cleanup\n\n1. Remove `react-app-env.d.ts` (CRA's auto-generated type declarations)\n2. Remove `.env.production` and `.env.staging` files\n3. Run `rep typegen` for typed access\n4. Update your Dockerfile to include the REP gateway","src/content/docs/guides/migration/from-cra.mdx","e449d4ecb8e99f91","guides/migration/from-next",{"id":415,"data":417,"body":423,"filePath":424,"digest":425,"deferredRender":16},{"title":418,"description":419,"editUrl":16,"head":420,"template":18,"sidebar":421,"pagefind":16,"draft":20},"From Next.js","Migrate from Next.js NEXT_PUBLIC_* variables to REP.",[],{"hidden":20,"attrs":422},{},"import { Aside } from '@astrojs/starlight/components';\n\n\u003CAside type=\"caution\">\n REP is designed for **client-side** environment variables. Next.js server-side `process.env.*` (without `NEXT_PUBLIC_` prefix) should remain as-is — they're already server-only and don't need REP.\n\u003C/Aside>\n\n## Automated migration\n\n```bash\nnpx @rep-protocol/codemod --framework next src/\n```\n\n### What it transforms\n\n```typescript\n// Before\nconst apiUrl = process.env.NEXT_PUBLIC_API_URL;\nconst flags = process.env.NEXT_PUBLIC_FEATURE_FLAGS;\n\n// After\nimport { rep } from '@rep-protocol/sdk';\nconst apiUrl = rep.get('API_URL');\nconst flags = rep.get('FEATURE_FLAGS');\n```\n\nOnly `NEXT_PUBLIC_*` prefixed variables are transformed. Server-side `process.env.*` access is left unchanged.\n\n### Preview first\n\n```bash\nnpx @rep-protocol/codemod --framework next --dry-run src/\n```\n\n## Manual migration\n\n1. **Rename environment variables:**\n ```bash\n NEXT_PUBLIC_API_URL → REP_PUBLIC_API_URL\n NEXT_PUBLIC_ANALYTICS_KEY → REP_SENSITIVE_ANALYTICS_KEY\n ```\n\n2. **Update client-side code:**\n ```typescript\n import { rep } from '@rep-protocol/sdk';\n const apiUrl = rep.get('API_URL', 'http://localhost:3000');\n ```\n\n3. **Install the SDK:**\n ```bash\n npm install @rep-protocol/sdk\n ```\n\n## Post-migration cleanup\n\n1. Remove `NEXT_PUBLIC_*` entries from `.env.local`, `.env.production`, etc.\n2. Keep server-side `process.env.*` as-is (these are already server-only)\n3. Run `rep typegen` for typed access\n4. Update your Dockerfile to include the REP gateway\n\n\u003CAside>\n For Next.js static export (`next export` or `output: 'export'`), REP works like any other SPA. For SSR deployments, REP handles only the client-side variables — server-side config continues to use standard Node.js `process.env`.\n\u003C/Aside>","src/content/docs/guides/migration/from-next.mdx","1b5d96b155bfe5f1","guides/migration/from-vite",{"id":426,"data":428,"body":434,"filePath":435,"digest":436,"deferredRender":16},{"title":429,"description":430,"editUrl":16,"head":431,"template":18,"sidebar":432,"pagefind":16,"draft":20},"From Vite","Migrate from Vite's import.meta.env to REP with the automated codemod.",[],{"hidden":20,"attrs":433},{},"import { Aside } from '@astrojs/starlight/components';\n\n## Automated migration\n\n```bash\nnpx @rep-protocol/codemod --framework vite src/\n```\n\n### What it transforms\n\n```typescript\n// Before\nconst apiUrl = import.meta.env.VITE_API_URL;\nconst flags = import.meta.env.VITE_FEATURE_FLAGS;\n\n// After\nimport { rep } from '@rep-protocol/sdk';\nconst apiUrl = rep.get('API_URL');\nconst flags = rep.get('FEATURE_FLAGS');\n```\n\n### What it leaves alone\n\nVite built-in variables are **not** transformed:\n\n- `import.meta.env.MODE`\n- `import.meta.env.DEV`\n- `import.meta.env.PROD`\n- `import.meta.env.SSR`\n- `import.meta.env.BASE_URL`\n\n### Preview first\n\n```bash\nnpx @rep-protocol/codemod --framework vite --dry-run src/\n```\n\n## Manual migration\n\nIf you prefer to migrate manually:\n\n1. **Rename environment variables:**\n ```bash\n VITE_API_URL → REP_PUBLIC_API_URL\n VITE_FEATURE_FLAGS → REP_PUBLIC_FEATURE_FLAGS\n VITE_ANALYTICS_KEY → REP_SENSITIVE_ANALYTICS_KEY\n ```\n\n2. **Update code:**\n ```typescript\n // Before\n const apiUrl = import.meta.env.VITE_API_URL;\n\n // After\n import { rep } from '@rep-protocol/sdk';\n const apiUrl = rep.get('API_URL', 'http://localhost:3000');\n ```\n\n3. **Install the SDK:**\n ```bash\n npm install @rep-protocol/sdk\n ```\n\n## Post-migration cleanup\n\n1. Remove `vite-env.d.ts` `ImportMeta` type augmentations (if you had custom ones)\n2. Remove `.env.production` and `.env.staging` files from the project\n3. Remove `envPrefix` configuration from `vite.config.ts` (if customized)\n4. Run `rep typegen --manifest .rep.yaml --output src/rep.d.ts` for typed access\n5. Update your Dockerfile to include the REP gateway\n\n\u003CAside type=\"tip\">\n The codemod is idempotent — running it twice produces the same result. It's safe to re-run after making manual changes.\n\u003C/Aside>","src/content/docs/guides/migration/from-vite.mdx","8f5b5620a48c0aa9","reference/adapters/react",{"id":437,"data":439,"body":445,"filePath":446,"digest":447,"deferredRender":16},{"title":440,"description":441,"editUrl":16,"head":442,"template":18,"sidebar":443,"pagefind":16,"draft":20},"React Adapter API","API reference for @rep-protocol/react hooks.",[],{"hidden":20,"attrs":444},{},"```bash\nnpm install @rep-protocol/react @rep-protocol/sdk\n```\n\n## `useRep(key, defaultValue?)`\n\n```typescript\nfunction useRep(key: string): string | undefined;\nfunction useRep(key: string, defaultValue: string): string;\n```\n\nReads a PUBLIC tier variable. Synchronous, hot-reload-aware.\n\n| Parameter | Type | Description |\n|---|---|---|\n| `key` | `string` | Variable name (e.g., `'API_URL'`) |\n| `defaultValue` | `string` | Optional fallback value |\n\n**Returns:** `string | undefined` (or `string` if `defaultValue` provided).\n\n**Behavior:**\n- Reads from the injected payload immediately (no loading state)\n- Subscribes to hot reload in `useEffect`\n- Unsubscribes on unmount\n- Re-renders component when the variable changes\n\n## `useRepSecure(key)`\n\n```typescript\nfunction useRepSecure(key: string): {\n value: string | null;\n loading: boolean;\n error: Error | null;\n};\n```\n\nReads a SENSITIVE tier variable. Async — fetches a session key on first call.\n\n| Parameter | Type | Description |\n|---|---|---|\n| `key` | `string` | Variable name (e.g., `'ANALYTICS_KEY'`) |\n\n**Returns:** `{ value, loading, error }` state object.\n\n**Behavior:**\n- Initial state: `{ value: null, loading: true, error: null }`\n- Success: `{ value: '...', loading: false, error: null }`\n- Failure: `{ value: null, loading: false, error: Error }`\n- Decrypted value is cached for the page lifetime\n- Re-fetches if `key` changes\n- Cleans up on unmount (cancelled flag prevents state update after unmount)\n\n## Requirements\n\n- React >= 16.8\n- `@rep-protocol/sdk` peer dependency","src/content/docs/reference/adapters/react.mdx","6718145cd5b95e97","guides/migration/overview",{"id":448,"data":450,"body":456,"filePath":457,"digest":458,"deferredRender":16},{"title":451,"description":452,"editUrl":16,"head":453,"template":18,"sidebar":454,"pagefind":16,"draft":20},"Migration Overview","A four-phase approach to migrating from build-time env vars to REP.",[],{"hidden":20,"attrs":455},{},"import { Steps, Aside } from '@astrojs/starlight/components';\n\nREP is designed for incremental adoption. You don't need to migrate everything at once — you can start with a single variable and expand from there.\n\n## Migration phases\n\n\u003CSteps>\n\n1. **Infrastructure**\n\n Set up the gateway in your deployment pipeline:\n - [ ] Download or build the gateway binary\n - [ ] Add the gateway to your Dockerfile or Kubernetes deployment\n - [ ] Configure `REP_GATEWAY_*` settings\n - [ ] Verify with `curl /rep/health`\n\n2. **SDK adoption**\n\n Replace env var reads in your application code:\n - [ ] Install `@rep-protocol/sdk`\n - [ ] Replace `import.meta.env.VITE_*` / `process.env.REACT_APP_*` with `rep.get()`\n - [ ] Replace sensitive var reads with `await rep.getSecure()`\n - [ ] Add default values for local development\n - [ ] Run the codemod for automated migration (optional)\n\n3. **Build cleanup**\n\n Remove build-time env var configuration:\n - [ ] Remove `.env.production`, `.env.staging` etc. from the build\n - [ ] Remove `--build-arg` flags from Docker builds\n - [ ] Remove framework-specific env var type declarations\n - [ ] Run `rep typegen` to generate SDK type declarations\n - [ ] Update CI/CD to use environment-agnostic builds\n\n4. **Hardening**\n\n Enable production security features:\n - [ ] Create a `.rep.yaml` manifest with all variables declared\n - [ ] Enable `--strict` mode for guardrail enforcement\n - [ ] Configure `allowed_origins` for session key CORS\n - [ ] Add `rep validate` to CI\n - [ ] Add `rep lint` to CI to scan bundles for leaked secrets\n - [ ] Review variable classification with the [decision tree](/concepts/variable-classification/)\n\n\u003C/Steps>\n\n## Using the codemod\n\nFor automated migration, the codemod transforms env var access patterns:\n\n```bash\n# Vite projects\nnpx @rep-protocol/codemod --framework vite src/\n\n# Create React App projects\nnpx @rep-protocol/codemod --framework cra src/\n\n# Next.js projects\nnpx @rep-protocol/codemod --framework next src/\n```\n\nUse `--dry-run` to preview changes before applying:\n\n```bash\nnpx @rep-protocol/codemod --framework vite --dry-run src/\n```\n\nSee framework-specific migration guides:\n- [From Vite](/guides/migration/from-vite/)\n- [From Create React App](/guides/migration/from-cra/)\n- [From Next.js](/guides/migration/from-next/)\n\n## After migration\n\nThe codemod handles the code changes. You still need to:\n\n1. Remove framework-specific type augmentations (e.g., `vite-env.d.ts` `ImportMeta` overrides)\n2. Run `rep typegen` to generate typed SDK overloads\n3. Update container config to set `REP_PUBLIC_*` / `REP_SENSITIVE_*` environment variables\n4. Verify with a test deployment\n\n\u003CAside type=\"tip\">\n You can start without a manifest file. The gateway works with just naming conventions. Add `.rep.yaml` later when you want validation and type generation.\n\u003C/Aside>","src/content/docs/guides/migration/overview.mdx","25098723d72fadad","reference/adapters/svelte",{"id":459,"data":461,"body":467,"filePath":468,"digest":469,"deferredRender":16},{"title":462,"description":463,"editUrl":16,"head":464,"template":18,"sidebar":465,"pagefind":16,"draft":20},"Svelte Adapter API","API reference for @rep-protocol/svelte stores.",[],{"hidden":20,"attrs":466},{},"```bash\nnpm install @rep-protocol/svelte @rep-protocol/sdk\n```\n\n## `repStore(key, defaultValue?)`\n\n```typescript\nfunction repStore(key: string, defaultValue?: string): Readable\u003Cstring | undefined>;\n```\n\nReads a PUBLIC tier variable as a Svelte `Readable` store.\n\n| Parameter | Type | Description |\n|---|---|---|\n| `key` | `string` | Variable name |\n| `defaultValue` | `string` | Optional fallback value |\n\n**Returns:** `Readable\u003Cstring | undefined>`\n\n**Behavior:**\n- Synchronous initial value from the payload\n- SSE subscription is **lazy** — established only when the store has subscribers\n- Updates automatically on config changes via hot reload\n- SSE connection closes when all subscribers unsubscribe\n\n## `repSecureStore(key)`\n\n```typescript\nfunction repSecureStore(key: string): Readable\u003Cstring | null>;\n```\n\nReads a SENSITIVE tier variable as a `Readable` store.\n\n| Parameter | Type | Description |\n|---|---|---|\n| `key` | `string` | Variable name |\n\n**Returns:** `Readable\u003Cstring | null>`\n\n**Behavior:**\n- Starts as `null`\n- Resolves after session key fetch and decryption\n- Errors are swallowed (SDK logs them); store stays `null`\n- Does **not** support hot reload\n\n## Requirements\n\n- Svelte >= 4 or Svelte 5\n- `@rep-protocol/sdk` peer dependency","src/content/docs/reference/adapters/svelte.mdx","1fd7407bcd7cca40","reference/adapters/vue",{"id":470,"data":472,"body":478,"filePath":479,"digest":480,"deferredRender":16},{"title":473,"description":474,"editUrl":16,"head":475,"template":18,"sidebar":476,"pagefind":16,"draft":20},"Vue Adapter API","API reference for @rep-protocol/vue composables.",[],{"hidden":20,"attrs":477},{},"```bash\nnpm install @rep-protocol/vue @rep-protocol/sdk\n```\n\n## `useRep(key, defaultValue?)`\n\n```typescript\nfunction useRep(key: string, defaultValue?: string): Ref\u003Cstring | undefined>;\n```\n\nReads a PUBLIC tier variable as a reactive `Ref`.\n\n| Parameter | Type | Description |\n|---|---|---|\n| `key` | `string` | Variable name |\n| `defaultValue` | `string` | Optional fallback value |\n\n**Returns:** `Ref\u003Cstring | undefined>`\n\n**Behavior:**\n- Set immediately from the injected payload\n- Subscribes to hot reload on creation\n- Unsubscribes via `onUnmounted`\n- Must be called inside `setup()`\n\n## `useRepSecure(key)`\n\n```typescript\nfunction useRepSecure(key: string): Ref\u003Cstring | null>;\n```\n\nReads a SENSITIVE tier variable as a reactive `Ref`.\n\n| Parameter | Type | Description |\n|---|---|---|\n| `key` | `string` | Variable name |\n\n**Returns:** `Ref\u003Cstring | null>`\n\n**Behavior:**\n- Starts as `null`\n- Resolves after session key fetch and decryption\n- Errors are swallowed (SDK logs them); ref stays `null`\n- Does **not** subscribe to hot reload\n\n## Requirements\n\n- Vue >= 3.0\n- `@rep-protocol/sdk` peer dependency\n- Must be called from `setup()` for `onUnmounted` cleanup","src/content/docs/reference/adapters/vue.mdx","0c7046e6fbeddda7"] \ No newline at end of file +[["Map",1,2,9,10],"meta::meta",["Map",3,4,5,6,7,8],"astro-version","5.17.3","content-config-digest","28e7bc87492477d9","astro-config-digest","{\"root\":{},\"srcDir\":{},\"publicDir\":{},\"outDir\":{},\"cacheDir\":{},\"site\":\"https://rep-protocol.dev\",\"compressHTML\":true,\"base\":\"/\",\"trailingSlash\":\"ignore\",\"output\":\"static\",\"scopedStyleStrategy\":\"where\",\"build\":{\"format\":\"directory\",\"client\":{},\"server\":{},\"assets\":\"_astro\",\"serverEntry\":\"entry.mjs\",\"redirects\":true,\"inlineStylesheets\":\"auto\",\"concurrency\":1},\"server\":{\"open\":false,\"host\":false,\"port\":4321,\"streaming\":true,\"allowedHosts\":[]},\"redirects\":{},\"image\":{\"endpoint\":{\"route\":\"/_image\"},\"service\":{\"entrypoint\":\"astro/assets/services/sharp\",\"config\":{}},\"domains\":[],\"remotePatterns\":[],\"responsiveStyles\":false},\"devToolbar\":{\"enabled\":true},\"markdown\":{\"syntaxHighlight\":false,\"shikiConfig\":{\"langs\":[],\"langAlias\":{},\"theme\":\"github-dark\",\"themes\":{},\"wrap\":false,\"transformers\":[]},\"remarkPlugins\":[null,null,null],\"rehypePlugins\":[null,[null,{\"experimentalHeadingIdCompat\":false}],null,[null,{\"themes\":[{\"name\":\"Night Owl No Italics\",\"type\":\"dark\",\"colors\":{\"focusBorder\":\"#122d42\",\"foreground\":\"#d6deeb\",\"disabledForeground\":\"#cccccc80\",\"descriptionForeground\":\"#d6deebb3\",\"errorForeground\":\"#ef5350\",\"icon.foreground\":\"#c5c5c5\",\"contrastActiveBorder\":null,\"contrastBorder\":\"#122d42\",\"textBlockQuote.background\":\"#7f7f7f1a\",\"textBlockQuote.border\":\"#007acc80\",\"textCodeBlock.background\":\"#4f4f4f\",\"textLink.activeForeground\":\"#3794ff\",\"textLink.foreground\":\"#3794ff\",\"textPreformat.foreground\":\"#d7ba7d\",\"textSeparator.foreground\":\"#ffffff2e\",\"editor.background\":\"#23262f\",\"editor.foreground\":\"#d6deeb\",\"editorLineNumber.foreground\":\"#4b6479\",\"editorLineNumber.activeForeground\":\"#c5e4fd\",\"editorActiveLineNumber.foreground\":\"#c6c6c6\",\"editor.selectionBackground\":\"#1d3b53\",\"editor.inactiveSelectionBackground\":\"#7e57c25a\",\"editor.selectionHighlightBackground\":\"#5f7e9779\",\"editorError.foreground\":\"#ef5350\",\"editorWarning.foreground\":\"#b39554\",\"editorInfo.foreground\":\"#3794ff\",\"editorHint.foreground\":\"#eeeeeeb2\",\"problemsErrorIcon.foreground\":\"#ef5350\",\"problemsWarningIcon.foreground\":\"#b39554\",\"problemsInfoIcon.foreground\":\"#3794ff\",\"editor.findMatchBackground\":\"#5f7e9779\",\"editor.findMatchHighlightBackground\":\"#1085bb5d\",\"editor.findRangeHighlightBackground\":\"#3a3d4166\",\"editorLink.activeForeground\":\"#4e94ce\",\"editorLightBulb.foreground\":\"#ffcc00\",\"editorLightBulbAutoFix.foreground\":\"#75beff\",\"diffEditor.insertedTextBackground\":\"#99b76d23\",\"diffEditor.insertedTextBorder\":\"#c5e47833\",\"diffEditor.removedTextBackground\":\"#ef535033\",\"diffEditor.removedTextBorder\":\"#ef53504d\",\"diffEditor.insertedLineBackground\":\"#9bb95533\",\"diffEditor.removedLineBackground\":\"#ff000033\",\"editorStickyScroll.background\":\"#011627\",\"editorStickyScrollHover.background\":\"#2a2d2e\",\"editorInlayHint.background\":\"#5f7e97cc\",\"editorInlayHint.foreground\":\"#ffffff\",\"editorInlayHint.typeBackground\":\"#5f7e97cc\",\"editorInlayHint.typeForeground\":\"#ffffff\",\"editorInlayHint.parameterBackground\":\"#5f7e97cc\",\"editorInlayHint.parameterForeground\":\"#ffffff\",\"editorPane.background\":\"#011627\",\"editorGroup.emptyBackground\":\"#011627\",\"editorGroup.focusedEmptyBorder\":null,\"editorGroupHeader.tabsBackground\":\"var(--sl-color-black)\",\"editorGroupHeader.tabsBorder\":\"color-mix(in srgb, var(--sl-color-gray-5), transparent 25%)\",\"editorGroupHeader.noTabsBackground\":\"#011627\",\"editorGroupHeader.border\":null,\"editorGroup.border\":\"#011627\",\"editorGroup.dropBackground\":\"#7e57c273\",\"editorGroup.dropIntoPromptForeground\":\"#d6deeb\",\"editorGroup.dropIntoPromptBackground\":\"#021320\",\"editorGroup.dropIntoPromptBorder\":null,\"sideBySideEditor.horizontalBorder\":\"#011627\",\"sideBySideEditor.verticalBorder\":\"#011627\",\"scrollbar.shadow\":\"#010b14\",\"scrollbarSlider.background\":\"#ffffff17\",\"scrollbarSlider.hoverBackground\":\"#ffffff40\",\"scrollbarSlider.activeBackground\":\"#084d8180\",\"panel.background\":\"#011627\",\"panel.border\":\"#5f7e97\",\"panelTitle.activeBorder\":\"#5f7e97\",\"panelTitle.activeForeground\":\"#ffffffcc\",\"panelTitle.inactiveForeground\":\"#d6deeb80\",\"panelSectionHeader.background\":\"#80808051\",\"terminal.background\":\"#011627\",\"widget.shadow\":\"#011627\",\"editorWidget.background\":\"#021320\",\"editorWidget.foreground\":\"#d6deeb\",\"editorWidget.border\":\"#5f7e97\",\"quickInput.background\":\"#021320\",\"quickInput.foreground\":\"#d6deeb\",\"quickInputTitle.background\":\"#ffffff1a\",\"pickerGroup.foreground\":\"#d1aaff\",\"pickerGroup.border\":\"#011627\",\"editor.hoverHighlightBackground\":\"#7e57c25a\",\"editorHoverWidget.background\":\"#011627\",\"editorHoverWidget.foreground\":\"#d6deeb\",\"editorHoverWidget.border\":\"#5f7e97\",\"editorHoverWidget.statusBarBackground\":\"#011a2f\",\"titleBar.activeBackground\":\"var(--sl-color-black)\",\"titleBar.activeForeground\":\"var(--sl-color-text)\",\"titleBar.inactiveBackground\":\"#010e1a\",\"titleBar.inactiveForeground\":\"#eeefff99\",\"titleBar.border\":\"color-mix(in srgb, var(--sl-color-gray-5), transparent 25%)\",\"toolbar.hoverBackground\":\"#5a5d5e50\",\"toolbar.activeBackground\":\"#63666750\",\"tab.activeBackground\":\"#0b2942\",\"tab.unfocusedActiveBackground\":\"#0b2942\",\"tab.inactiveBackground\":\"#01111d\",\"tab.unfocusedInactiveBackground\":\"#01111d\",\"tab.activeForeground\":\"var(--sl-color-text)\",\"tab.inactiveForeground\":\"#5f7e97\",\"tab.unfocusedActiveForeground\":\"#5f7e97\",\"tab.unfocusedInactiveForeground\":\"#5f7e97\",\"tab.hoverBackground\":null,\"tab.unfocusedHoverBackground\":null,\"tab.hoverForeground\":null,\"tab.unfocusedHoverForeground\":null,\"tab.border\":\"#272b3b\",\"tab.lastPinnedBorder\":\"#585858\",\"tab.activeBorder\":\"transparent\",\"tab.unfocusedActiveBorder\":\"#262a39\",\"tab.activeBorderTop\":\"var(--sl-color-accent-high)\",\"tab.unfocusedActiveBorderTop\":null,\"tab.hoverBorder\":null,\"tab.unfocusedHoverBorder\":null,\"tab.activeModifiedBorder\":\"#3399cc\",\"tab.inactiveModifiedBorder\":\"#3399cc80\",\"tab.unfocusedActiveModifiedBorder\":\"#3399cc80\",\"tab.unfocusedInactiveModifiedBorder\":\"#3399cc40\",\"badge.background\":\"#5f7e97\",\"badge.foreground\":\"#ffffff\",\"button.background\":\"#7e57c2cc\",\"button.foreground\":\"#ffffffcc\",\"button.border\":\"#122d42\",\"button.separator\":\"#ffffff52\",\"button.hoverBackground\":\"#7e57c2\",\"button.secondaryBackground\":\"#3a3d41\",\"button.secondaryForeground\":\"#ffffff\",\"button.secondaryHoverBackground\":\"#46494e\",\"dropdown.background\":\"#011627\",\"dropdown.foreground\":\"#ffffffcc\",\"dropdown.border\":\"#5f7e97\",\"list.activeSelectionBackground\":\"#234d708c\",\"list.activeSelectionForeground\":\"#ffffff\",\"tree.indentGuidesStroke\":\"#585858\",\"input.background\":\"#0b253a\",\"input.foreground\":\"#ffffffcc\",\"input.placeholderForeground\":\"#5f7e97\",\"inputOption.activeBorder\":\"#ffffffcc\",\"inputOption.hoverBackground\":\"#5a5d5e80\",\"inputOption.activeBackground\":\"#122d4266\",\"inputOption.activeForeground\":\"#ffffff\",\"inputValidation.infoBackground\":\"#00589ef2\",\"inputValidation.infoBorder\":\"#64b5f6\",\"inputValidation.warningBackground\":\"#675700f2\",\"inputValidation.warningBorder\":\"#ffca28\",\"inputValidation.errorBackground\":\"#ab0300f2\",\"inputValidation.errorBorder\":\"#ef5350\",\"keybindingLabel.background\":\"#8080802b\",\"keybindingLabel.foreground\":\"#cccccc\",\"keybindingLabel.border\":\"#33333399\",\"keybindingLabel.bottomBorder\":\"#44444499\",\"menu.foreground\":\"#ffffffcc\",\"menu.background\":\"#011627\",\"menu.selectionForeground\":\"#ffffff\",\"menu.selectionBackground\":\"#234d708c\",\"menu.separatorBackground\":\"#606060\",\"editor.snippetTabstopHighlightBackground\":\"#7c7c74c\",\"editor.snippetFinalTabstopHighlightBorder\":\"#525252\",\"terminal.ansiBlack\":\"#011627\",\"terminal.ansiRed\":\"#ef5350\",\"terminal.ansiGreen\":\"#22da6e\",\"terminal.ansiYellow\":\"#c5e478\",\"terminal.ansiBlue\":\"#82aaff\",\"terminal.ansiMagenta\":\"#c792ea\",\"terminal.ansiCyan\":\"#21c7a8\",\"terminal.ansiWhite\":\"#ffffff\",\"terminal.ansiBrightBlack\":\"#575656\",\"terminal.ansiBrightRed\":\"#ef5350\",\"terminal.ansiBrightGreen\":\"#22da6e\",\"terminal.ansiBrightYellow\":\"#ffeb95\",\"terminal.ansiBrightBlue\":\"#82aaff\",\"terminal.ansiBrightMagenta\":\"#c792ea\",\"terminal.ansiBrightCyan\":\"#7fdbca\",\"terminal.ansiBrightWhite\":\"#ffffff\",\"selection.background\":\"#4373c2\",\"input.border\":\"#5f7e97\",\"punctuation.definition.generic.begin.html\":\"#ef5350f2\",\"progress.background\":\"#7e57c2\",\"breadcrumb.foreground\":\"#a599e9\",\"breadcrumb.focusForeground\":\"#ffffff\",\"breadcrumb.activeSelectionForeground\":\"#ffffff\",\"breadcrumbPicker.background\":\"#001122\",\"list.invalidItemForeground\":\"#975f94\",\"list.dropBackground\":\"#011627\",\"list.focusBackground\":\"#010d18\",\"list.focusForeground\":\"#ffffff\",\"list.highlightForeground\":\"#ffffff\",\"list.hoverBackground\":\"#011627\",\"list.hoverForeground\":\"#ffffff\",\"list.inactiveSelectionBackground\":\"#0e293f\",\"list.inactiveSelectionForeground\":\"#5f7e97\",\"activityBar.background\":\"#011627\",\"activityBar.dropBackground\":\"#5f7e97\",\"activityBar.foreground\":\"#5f7e97\",\"activityBar.border\":\"#011627\",\"activityBarBadge.background\":\"#44596b\",\"activityBarBadge.foreground\":\"#ffffff\",\"sideBar.background\":\"#011627\",\"sideBar.foreground\":\"#89a4bb\",\"sideBar.border\":\"#011627\",\"sideBarTitle.foreground\":\"#5f7e97\",\"sideBarSectionHeader.background\":\"#011627\",\"sideBarSectionHeader.foreground\":\"#5f7e97\",\"editorCursor.foreground\":\"#80a4c2\",\"editor.wordHighlightBackground\":\"#f6bbe533\",\"editor.wordHighlightStrongBackground\":\"#e2a2f433\",\"editor.lineHighlightBackground\":\"#0003\",\"editor.rangeHighlightBackground\":\"#7e57c25a\",\"editorIndentGuide.background\":\"#5e81ce52\",\"editorIndentGuide.activeBackground\":\"#7e97ac\",\"editorRuler.foreground\":\"#5e81ce52\",\"editorCodeLens.foreground\":\"#5e82ceb4\",\"editorBracketMatch.background\":\"#5f7e974d\",\"editorOverviewRuler.currentContentForeground\":\"#7e57c2\",\"editorOverviewRuler.incomingContentForeground\":\"#7e57c2\",\"editorOverviewRuler.commonContentForeground\":\"#7e57c2\",\"editorGutter.background\":\"#011627\",\"editorGutter.modifiedBackground\":\"#e2b93d\",\"editorGutter.addedBackground\":\"#9ccc65\",\"editorGutter.deletedBackground\":\"#ef5350\",\"editorSuggestWidget.background\":\"#2c3043\",\"editorSuggestWidget.border\":\"#2b2f40\",\"editorSuggestWidget.foreground\":\"#d6deeb\",\"editorSuggestWidget.highlightForeground\":\"#ffffff\",\"editorSuggestWidget.selectedBackground\":\"#5f7e97\",\"debugExceptionWidget.background\":\"#011627\",\"debugExceptionWidget.border\":\"#5f7e97\",\"editorMarkerNavigation.background\":\"#0b2942\",\"editorMarkerNavigationError.background\":\"#ef5350\",\"editorMarkerNavigationWarning.background\":\"#ffca28\",\"peekView.border\":\"#5f7e97\",\"peekViewEditor.background\":\"#011627\",\"peekViewEditor.matchHighlightBackground\":\"#7e57c25a\",\"peekViewResult.background\":\"#011627\",\"peekViewResult.fileForeground\":\"#5f7e97\",\"peekViewResult.lineForeground\":\"#5f7e97\",\"peekViewResult.matchHighlightBackground\":\"#ffffffcc\",\"peekViewResult.selectionBackground\":\"#2e3250\",\"peekViewResult.selectionForeground\":\"#5f7e97\",\"peekViewTitle.background\":\"#011627\",\"peekViewTitleDescription.foreground\":\"#697098\",\"peekViewTitleLabel.foreground\":\"#5f7e97\",\"merge.currentHeaderBackground\":\"#5f7e97\",\"merge.incomingHeaderBackground\":\"#7e57c25a\",\"statusBar.background\":\"#011627\",\"statusBar.foreground\":\"#5f7e97\",\"statusBar.border\":\"#262a39\",\"statusBar.debuggingBackground\":\"#202431\",\"statusBar.debuggingBorder\":\"#1f2330\",\"statusBar.noFolderBackground\":\"#011627\",\"statusBar.noFolderBorder\":\"#25293a\",\"statusBarItem.activeBackground\":\"#202431\",\"statusBarItem.hoverBackground\":\"#202431\",\"statusBarItem.prominentBackground\":\"#202431\",\"statusBarItem.prominentHoverBackground\":\"#202431\",\"notifications.background\":\"#01111d\",\"notifications.border\":\"#262a39\",\"notificationCenter.border\":\"#262a39\",\"notificationToast.border\":\"#262a39\",\"notifications.foreground\":\"#ffffffcc\",\"notificationLink.foreground\":\"#80cbc4\",\"extensionButton.prominentForeground\":\"#ffffffcc\",\"extensionButton.prominentBackground\":\"#7e57c2cc\",\"extensionButton.prominentHoverBackground\":\"#7e57c2\",\"terminal.selectionBackground\":\"#1b90dd4d\",\"terminalCursor.background\":\"#234d70\",\"debugToolBar.background\":\"#011627\",\"welcomePage.buttonBackground\":\"#011627\",\"welcomePage.buttonHoverBackground\":\"#011627\",\"walkThrough.embeddedEditorBackground\":\"#011627\",\"gitDecoration.modifiedResourceForeground\":\"#a2bffc\",\"gitDecoration.deletedResourceForeground\":\"#ef535090\",\"gitDecoration.untrackedResourceForeground\":\"#c5e478ff\",\"gitDecoration.ignoredResourceForeground\":\"#395a75\",\"gitDecoration.conflictingResourceForeground\":\"#ffeb95cc\",\"source.elm\":\"#5f7e97\",\"string.quoted.single.js\":\"#ffffff\",\"meta.objectliteral.js\":\"#82aaff\"},\"fg\":\"#d6deeb\",\"bg\":\"#23262f\",\"semanticHighlighting\":false,\"settings\":[{\"name\":\"Changed\",\"scope\":[\"markup.changed\",\"meta.diff.header.git\",\"meta.diff.header.from-file\",\"meta.diff.header.to-file\"],\"settings\":{\"foreground\":\"#a2bffc\"}},{\"name\":\"Deleted\",\"scope\":[\"markup.deleted.diff\"],\"settings\":{\"foreground\":\"#f27775fe\"}},{\"name\":\"Inserted\",\"scope\":[\"markup.inserted.diff\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Global settings\",\"settings\":{\"background\":\"#011627\",\"foreground\":\"#d6deeb\"}},{\"name\":\"Comment\",\"scope\":[\"comment\"],\"settings\":{\"foreground\":\"#919f9f\",\"fontStyle\":\"\"}},{\"name\":\"String\",\"scope\":[\"string\"],\"settings\":{\"foreground\":\"#ecc48d\"}},{\"name\":\"String Quoted\",\"scope\":[\"string.quoted\",\"variable.other.readwrite.js\"],\"settings\":{\"foreground\":\"#ecc48d\"}},{\"name\":\"Support Constant Math\",\"scope\":[\"support.constant.math\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Number\",\"scope\":[\"constant.numeric\",\"constant.character.numeric\"],\"settings\":{\"foreground\":\"#f78c6c\",\"fontStyle\":\"\"}},{\"name\":\"Built-in constant\",\"scope\":[\"constant.language\",\"punctuation.definition.constant\",\"variable.other.constant\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"User-defined constant\",\"scope\":[\"constant.character\",\"constant.other\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"Constant Character Escape\",\"scope\":[\"constant.character.escape\"],\"settings\":{\"foreground\":\"#f78c6c\"}},{\"name\":\"RegExp String\",\"scope\":[\"string.regexp\",\"string.regexp keyword.other\"],\"settings\":{\"foreground\":\"#5ca7e4\"}},{\"name\":\"Comma in functions\",\"scope\":[\"meta.function punctuation.separator.comma\"],\"settings\":{\"foreground\":\"#889fb2\"}},{\"name\":\"Variable\",\"scope\":[\"variable\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Keyword\",\"scope\":[\"punctuation.accessor\",\"keyword\"],\"settings\":{\"foreground\":\"#c792ea\",\"fontStyle\":\"\"}},{\"name\":\"Storage\",\"scope\":[\"storage\",\"meta.var.expr\",\"meta.class meta.method.declaration meta.var.expr storage.type.js\",\"storage.type.property.js\",\"storage.type.property.ts\",\"storage.type.property.tsx\"],\"settings\":{\"foreground\":\"#c792ea\",\"fontStyle\":\"\"}},{\"name\":\"Storage type\",\"scope\":[\"storage.type\"],\"settings\":{\"foreground\":\"#c792ea\"}},{\"name\":\"Storage type\",\"scope\":[\"storage.type.function.arrow.js\"],\"settings\":{\"fontStyle\":\"\"}},{\"name\":\"Class name\",\"scope\":[\"entity.name.class\",\"meta.class entity.name.type.class\"],\"settings\":{\"foreground\":\"#ffcb8b\"}},{\"name\":\"Inherited class\",\"scope\":[\"entity.other.inherited-class\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Function name\",\"scope\":[\"entity.name.function\"],\"settings\":{\"foreground\":\"#c792ea\",\"fontStyle\":\"\"}},{\"name\":\"Meta Tag\",\"scope\":[\"punctuation.definition.tag\",\"meta.tag\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"HTML Tag names\",\"scope\":[\"entity.name.tag\",\"meta.tag.other.html\",\"meta.tag.other.js\",\"meta.tag.other.tsx\",\"entity.name.tag.tsx\",\"entity.name.tag.js\",\"entity.name.tag\",\"meta.tag.js\",\"meta.tag.tsx\",\"meta.tag.html\"],\"settings\":{\"foreground\":\"#caece6\",\"fontStyle\":\"\"}},{\"name\":\"Tag attribute\",\"scope\":[\"entity.other.attribute-name\"],\"settings\":{\"fontStyle\":\"\",\"foreground\":\"#c5e478\"}},{\"name\":\"Entity Name Tag Custom\",\"scope\":[\"entity.name.tag.custom\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Library (function & constant)\",\"scope\":[\"support.function\",\"support.constant\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"Support Constant Property Value meta\",\"scope\":[\"support.constant.meta.property-value\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"Library class/type\",\"scope\":[\"support.type\",\"support.class\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Support Variable DOM\",\"scope\":[\"support.variable.dom\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Invalid\",\"scope\":[\"invalid\"],\"settings\":{\"background\":\"#ff2c83\",\"foreground\":\"#ffffff\"}},{\"name\":\"Invalid deprecated\",\"scope\":[\"invalid.deprecated\"],\"settings\":{\"foreground\":\"#ffffff\",\"background\":\"#d3423e\"}},{\"name\":\"Keyword Operator\",\"scope\":[\"keyword.operator\"],\"settings\":{\"foreground\":\"#7fdbca\",\"fontStyle\":\"\"}},{\"name\":\"Keyword Operator Relational\",\"scope\":[\"keyword.operator.relational\"],\"settings\":{\"foreground\":\"#c792ea\",\"fontStyle\":\"\"}},{\"name\":\"Keyword Operator Assignment\",\"scope\":[\"keyword.operator.assignment\"],\"settings\":{\"foreground\":\"#c792ea\"}},{\"name\":\"Keyword Operator Arithmetic\",\"scope\":[\"keyword.operator.arithmetic\"],\"settings\":{\"foreground\":\"#c792ea\"}},{\"name\":\"Keyword Operator Bitwise\",\"scope\":[\"keyword.operator.bitwise\"],\"settings\":{\"foreground\":\"#c792ea\"}},{\"name\":\"Keyword Operator Increment\",\"scope\":[\"keyword.operator.increment\"],\"settings\":{\"foreground\":\"#c792ea\"}},{\"name\":\"Keyword Operator Ternary\",\"scope\":[\"keyword.operator.ternary\"],\"settings\":{\"foreground\":\"#c792ea\"}},{\"name\":\"Double-Slashed Comment\",\"scope\":[\"comment.line.double-slash\"],\"settings\":{\"foreground\":\"#919f9f\"}},{\"name\":\"Object\",\"scope\":[\"object\"],\"settings\":{\"foreground\":\"#cdebf7\"}},{\"name\":\"Null\",\"scope\":[\"constant.language.null\"],\"settings\":{\"foreground\":\"#ff6a83\"}},{\"name\":\"Meta Brace\",\"scope\":[\"meta.brace\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"Meta Delimiter Period\",\"scope\":[\"meta.delimiter.period\"],\"settings\":{\"foreground\":\"#c792ea\",\"fontStyle\":\"\"}},{\"name\":\"Punctuation Definition String\",\"scope\":[\"punctuation.definition.string\"],\"settings\":{\"foreground\":\"#d9f5dd\"}},{\"name\":\"Punctuation Definition String Markdown\",\"scope\":[\"punctuation.definition.string.begin.markdown\"],\"settings\":{\"foreground\":\"#ff6a83\"}},{\"name\":\"Boolean\",\"scope\":[\"constant.language.boolean\"],\"settings\":{\"foreground\":\"#ff6a83\"}},{\"name\":\"Object Comma\",\"scope\":[\"object.comma\"],\"settings\":{\"foreground\":\"#ffffff\"}},{\"name\":\"Variable Parameter Function\",\"scope\":[\"variable.parameter.function\"],\"settings\":{\"foreground\":\"#7fdbca\",\"fontStyle\":\"\"}},{\"name\":\"Support Type Property Name & entity name tags\",\"scope\":[\"support.type.vendor.property-name\",\"support.constant.vendor.property-value\",\"support.type.property-name\",\"meta.property-list entity.name.tag\"],\"settings\":{\"foreground\":\"#80cbc4\",\"fontStyle\":\"\"}},{\"name\":\"Entity Name tag reference in stylesheets\",\"scope\":[\"meta.property-list entity.name.tag.reference\"],\"settings\":{\"foreground\":\"#57eaf1\"}},{\"name\":\"Constant Other Color RGB Value Punctuation Definition Constant\",\"scope\":[\"constant.other.color.rgb-value punctuation.definition.constant\"],\"settings\":{\"foreground\":\"#f78c6c\"}},{\"name\":\"Constant Other Color\",\"scope\":[\"constant.other.color\"],\"settings\":{\"foreground\":\"#ffeb95\"}},{\"name\":\"Keyword Other Unit\",\"scope\":[\"keyword.other.unit\"],\"settings\":{\"foreground\":\"#ffeb95\"}},{\"name\":\"Meta Selector\",\"scope\":[\"meta.selector\"],\"settings\":{\"foreground\":\"#c792ea\",\"fontStyle\":\"\"}},{\"name\":\"Entity Other Attribute Name Id\",\"scope\":[\"entity.other.attribute-name.id\"],\"settings\":{\"foreground\":\"#fad430\"}},{\"name\":\"Meta Property Name\",\"scope\":[\"meta.property-name\"],\"settings\":{\"foreground\":\"#80cbc4\"}},{\"name\":\"Doctypes\",\"scope\":[\"entity.name.tag.doctype\",\"meta.tag.sgml.doctype\"],\"settings\":{\"foreground\":\"#c792ea\",\"fontStyle\":\"\"}},{\"name\":\"Punctuation Definition Parameters\",\"scope\":[\"punctuation.definition.parameters\"],\"settings\":{\"foreground\":\"#d9f5dd\"}},{\"name\":\"Keyword Control Operator\",\"scope\":[\"keyword.control.operator\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"Keyword Operator Logical\",\"scope\":[\"keyword.operator.logical\"],\"settings\":{\"foreground\":\"#c792ea\",\"fontStyle\":\"\"}},{\"name\":\"Variable Instances\",\"scope\":[\"variable.instance\",\"variable.other.instance\",\"variable.readwrite.instance\",\"variable.other.readwrite.instance\",\"variable.other.property\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"Variable Property Other object property\",\"scope\":[\"variable.other.object.property\"],\"settings\":{\"foreground\":\"#faf39f\",\"fontStyle\":\"\"}},{\"name\":\"Variable Property Other object\",\"scope\":[\"variable.other.object.js\"],\"settings\":{\"fontStyle\":\"\"}},{\"name\":\"Entity Name Function\",\"scope\":[\"entity.name.function\"],\"settings\":{\"foreground\":\"#82aaff\",\"fontStyle\":\"\"}},{\"name\":\"Keyword Operator Comparison, returns, imports, and Keyword Operator Ruby\",\"scope\":[\"keyword.control.conditional.js\",\"keyword.operator.comparison\",\"keyword.control.flow.js\",\"keyword.control.flow.ts\",\"keyword.control.flow.tsx\",\"keyword.control.ruby\",\"keyword.control.def.ruby\",\"keyword.control.loop.js\",\"keyword.control.loop.ts\",\"keyword.control.import.js\",\"keyword.control.import.ts\",\"keyword.control.import.tsx\",\"keyword.control.from.js\",\"keyword.control.from.ts\",\"keyword.control.from.tsx\",\"keyword.control.conditional.js\",\"keyword.control.conditional.ts\",\"keyword.control.switch.js\",\"keyword.control.switch.ts\",\"keyword.operator.instanceof.js\",\"keyword.operator.expression.instanceof.ts\",\"keyword.operator.expression.instanceof.tsx\"],\"settings\":{\"foreground\":\"#c792ea\",\"fontStyle\":\"\"}},{\"name\":\"Support Constant, `new` keyword, Special Method Keyword, `debugger`, other keywords\",\"scope\":[\"support.constant\",\"keyword.other.special-method\",\"keyword.other.new\",\"keyword.other.debugger\",\"keyword.control\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"Support Function\",\"scope\":[\"support.function\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Invalid Broken\",\"scope\":[\"invalid.broken\"],\"settings\":{\"foreground\":\"#989da0\",\"background\":\"#F78C6C\"}},{\"name\":\"Invalid Unimplemented\",\"scope\":[\"invalid.unimplemented\"],\"settings\":{\"background\":\"#8BD649\",\"foreground\":\"#ffffff\"}},{\"name\":\"Invalid Illegal\",\"scope\":[\"invalid.illegal\"],\"settings\":{\"foreground\":\"#ffffff\",\"background\":\"#ec5f67\"}},{\"name\":\"Language Variable\",\"scope\":[\"variable.language\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"Support Variable Property\",\"scope\":[\"support.variable.property\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"Variable Function\",\"scope\":[\"variable.function\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"Variable Interpolation\",\"scope\":[\"variable.interpolation\"],\"settings\":{\"foreground\":\"#ef787f\"}},{\"name\":\"Meta Function Call\",\"scope\":[\"meta.function-call\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"Punctuation Section Embedded\",\"scope\":[\"punctuation.section.embedded\"],\"settings\":{\"foreground\":\"#e2817f\"}},{\"name\":\"Punctuation Tweaks\",\"scope\":[\"punctuation.terminator.expression\",\"punctuation.definition.arguments\",\"punctuation.definition.array\",\"punctuation.section.array\",\"meta.array\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"More Punctuation Tweaks\",\"scope\":[\"punctuation.definition.list.begin\",\"punctuation.definition.list.end\",\"punctuation.separator.arguments\",\"punctuation.definition.list\"],\"settings\":{\"foreground\":\"#d9f5dd\"}},{\"name\":\"Template Strings\",\"scope\":[\"string.template meta.template.expression\"],\"settings\":{\"foreground\":\"#e2817f\"}},{\"name\":\"Backtics(``) in Template Strings\",\"scope\":[\"string.template punctuation.definition.string\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"Italics\",\"scope\":[\"italic\"],\"settings\":{\"foreground\":\"#c792ea\",\"fontStyle\":\"italic\"}},{\"name\":\"Bold\",\"scope\":[\"bold\"],\"settings\":{\"foreground\":\"#c5e478\",\"fontStyle\":\"bold\"}},{\"name\":\"Quote\",\"scope\":[\"quote\"],\"settings\":{\"foreground\":\"#969bb7\",\"fontStyle\":\"\"}},{\"name\":\"Raw Code\",\"scope\":[\"raw\"],\"settings\":{\"foreground\":\"#80cbc4\"}},{\"name\":\"CoffeScript Variable Assignment\",\"scope\":[\"variable.assignment.coffee\"],\"settings\":{\"foreground\":\"#31e1eb\"}},{\"name\":\"CoffeScript Parameter Function\",\"scope\":[\"variable.parameter.function.coffee\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"CoffeeScript Assignments\",\"scope\":[\"variable.assignment.coffee\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"C# Readwrite Variables\",\"scope\":[\"variable.other.readwrite.cs\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"C# Classes & Storage types\",\"scope\":[\"entity.name.type.class.cs\",\"storage.type.cs\"],\"settings\":{\"foreground\":\"#ffcb8b\"}},{\"name\":\"C# Namespaces\",\"scope\":[\"entity.name.type.namespace.cs\"],\"settings\":{\"foreground\":\"#b2ccd6\"}},{\"name\":\"C# Unquoted String Zone\",\"scope\":[\"string.unquoted.preprocessor.message.cs\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"C# Region\",\"scope\":[\"punctuation.separator.hash.cs\",\"keyword.preprocessor.region.cs\",\"keyword.preprocessor.endregion.cs\"],\"settings\":{\"foreground\":\"#ffcb8b\",\"fontStyle\":\"bold\"}},{\"name\":\"C# Other Variables\",\"scope\":[\"variable.other.object.cs\"],\"settings\":{\"foreground\":\"#b2ccd6\"}},{\"name\":\"C# Enum\",\"scope\":[\"entity.name.type.enum.cs\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Dart String\",\"scope\":[\"string.interpolated.single.dart\",\"string.interpolated.double.dart\"],\"settings\":{\"foreground\":\"#ffcb8b\"}},{\"name\":\"Dart Class\",\"scope\":[\"support.class.dart\"],\"settings\":{\"foreground\":\"#ffcb8b\"}},{\"name\":\"Tag names in Stylesheets\",\"scope\":[\"entity.name.tag.css\",\"entity.name.tag.less\",\"entity.name.tag.custom.css\",\"support.constant.property-value.css\"],\"settings\":{\"foreground\":\"#ff6d6d\",\"fontStyle\":\"\"}},{\"name\":\"Wildcard(*) selector in Stylesheets\",\"scope\":[\"entity.name.tag.wildcard.css\",\"entity.name.tag.wildcard.less\",\"entity.name.tag.wildcard.scss\",\"entity.name.tag.wildcard.sass\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"CSS Keyword Other Unit\",\"scope\":[\"keyword.other.unit.css\"],\"settings\":{\"foreground\":\"#ffeb95\"}},{\"name\":\"Attribute Name for CSS\",\"scope\":[\"meta.attribute-selector.css entity.other.attribute-name.attribute\",\"variable.other.readwrite.js\"],\"settings\":{\"foreground\":\"#f78c6c\"}},{\"name\":\"Elixir Classes\",\"scope\":[\"source.elixir support.type.elixir\",\"source.elixir meta.module.elixir entity.name.class.elixir\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"Elixir Functions\",\"scope\":[\"source.elixir entity.name.function\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Elixir Constants\",\"scope\":[\"source.elixir constant.other.symbol.elixir\",\"source.elixir constant.other.keywords.elixir\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"Elixir String Punctuations\",\"scope\":[\"source.elixir punctuation.definition.string\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Elixir\",\"scope\":[\"source.elixir variable.other.readwrite.module.elixir\",\"source.elixir variable.other.readwrite.module.elixir punctuation.definition.variable.elixir\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Elixir Binary Punctuations\",\"scope\":[\"source.elixir .punctuation.binary.elixir\"],\"settings\":{\"foreground\":\"#c792ea\",\"fontStyle\":\"\"}},{\"name\":\"Closure Constant Keyword\",\"scope\":[\"constant.keyword.clojure\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"Go Function Calls\",\"scope\":[\"source.go meta.function-call.go\"],\"settings\":{\"foreground\":\"#dddddd\"}},{\"name\":\"Go Keywords\",\"scope\":[\"source.go keyword.package.go\",\"source.go keyword.import.go\",\"source.go keyword.function.go\",\"source.go keyword.type.go\",\"source.go keyword.struct.go\",\"source.go keyword.interface.go\",\"source.go keyword.const.go\",\"source.go keyword.var.go\",\"source.go keyword.map.go\",\"source.go keyword.channel.go\",\"source.go keyword.control.go\"],\"settings\":{\"foreground\":\"#c792ea\"}},{\"name\":\"Go Constants e.g. nil, string format (%s, %d, etc.)\",\"scope\":[\"source.go constant.language.go\",\"source.go constant.other.placeholder.go\"],\"settings\":{\"foreground\":\"#ff6a83\"}},{\"name\":\"C++ Functions\",\"scope\":[\"entity.name.function.preprocessor.cpp\",\"entity.scope.name.cpp\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"C++ Meta Namespace\",\"scope\":[\"meta.namespace-block.cpp\"],\"settings\":{\"foreground\":\"#e0dec6\"}},{\"name\":\"C++ Language Primitive Storage\",\"scope\":[\"storage.type.language.primitive.cpp\"],\"settings\":{\"foreground\":\"#ff6a83\"}},{\"name\":\"C++ Preprocessor Macro\",\"scope\":[\"meta.preprocessor.macro.cpp\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"C++ Variable Parameter\",\"scope\":[\"variable.parameter\"],\"settings\":{\"foreground\":\"#ffcb8b\"}},{\"name\":\"Powershell Variables\",\"scope\":[\"variable.other.readwrite.powershell\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"Powershell Function\",\"scope\":[\"support.function.powershell\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"ID Attribute Name in HTML\",\"scope\":[\"entity.other.attribute-name.id.html\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"HTML Punctuation Definition Tag\",\"scope\":[\"punctuation.definition.tag.html\"],\"settings\":{\"foreground\":\"#6ae9f0\"}},{\"name\":\"HTML Doctype\",\"scope\":[\"meta.tag.sgml.doctype.html\"],\"settings\":{\"foreground\":\"#c792ea\",\"fontStyle\":\"\"}},{\"name\":\"JavaScript Classes\",\"scope\":[\"meta.class entity.name.type.class.js\"],\"settings\":{\"foreground\":\"#ffcb8b\"}},{\"name\":\"JavaScript Method Declaration e.g. `constructor`\",\"scope\":[\"meta.method.declaration storage.type.js\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"JavaScript Terminator\",\"scope\":[\"terminator.js\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"JavaScript Meta Punctuation Definition\",\"scope\":[\"meta.js punctuation.definition.js\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"Entity Names in Code Documentations\",\"scope\":[\"entity.name.type.instance.jsdoc\",\"entity.name.type.instance.phpdoc\"],\"settings\":{\"foreground\":\"#889fb2\"}},{\"name\":\"Other Variables in Code Documentations\",\"scope\":[\"variable.other.jsdoc\",\"variable.other.phpdoc\"],\"settings\":{\"foreground\":\"#78ccf0\"}},{\"name\":\"JavaScript module imports and exports\",\"scope\":[\"variable.other.meta.import.js\",\"meta.import.js variable.other\",\"variable.other.meta.export.js\",\"meta.export.js variable.other\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"JavaScript Variable Parameter Function\",\"scope\":[\"variable.parameter.function.js\"],\"settings\":{\"foreground\":\"#8b96ea\"}},{\"name\":\"JavaScript[React] Variable Other Object\",\"scope\":[\"variable.other.object.js\",\"variable.other.object.jsx\",\"variable.object.property.js\",\"variable.object.property.jsx\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"JavaScript Variables\",\"scope\":[\"variable.js\",\"variable.other.js\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"JavaScript Entity Name Type\",\"scope\":[\"entity.name.type.js\",\"entity.name.type.module.js\"],\"settings\":{\"foreground\":\"#ffcb8b\",\"fontStyle\":\"\"}},{\"name\":\"JavaScript Support Classes\",\"scope\":[\"support.class.js\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"JSON Property Names\",\"scope\":[\"support.type.property-name.json\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"JSON Support Constants\",\"scope\":[\"support.constant.json\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"JSON Property values (string)\",\"scope\":[\"meta.structure.dictionary.value.json string.quoted.double\"],\"settings\":{\"foreground\":\"#c789d6\"}},{\"name\":\"Strings in JSON values\",\"scope\":[\"string.quoted.double.json punctuation.definition.string.json\"],\"settings\":{\"foreground\":\"#80cbc4\"}},{\"name\":\"Specific JSON Property values like null\",\"scope\":[\"meta.structure.dictionary.json meta.structure.dictionary.value constant.language\"],\"settings\":{\"foreground\":\"#ff6a83\"}},{\"name\":\"JavaScript Other Variable\",\"scope\":[\"variable.other.object.js\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"Ruby Variables\",\"scope\":[\"variable.other.ruby\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"Ruby Class\",\"scope\":[\"entity.name.type.class.ruby\"],\"settings\":{\"foreground\":\"#ecc48d\"}},{\"name\":\"Ruby Hashkeys\",\"scope\":[\"constant.language.symbol.hashkey.ruby\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"LESS Tag names\",\"scope\":[\"entity.name.tag.less\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"LESS Keyword Other Unit\",\"scope\":[\"keyword.other.unit.css\"],\"settings\":{\"foreground\":\"#ffeb95\"}},{\"name\":\"Attribute Name for LESS\",\"scope\":[\"meta.attribute-selector.less entity.other.attribute-name.attribute\"],\"settings\":{\"foreground\":\"#f78c6c\"}},{\"name\":\"Markdown Headings\",\"scope\":[\"markup.heading.markdown\",\"markup.heading.setext.1.markdown\",\"markup.heading.setext.2.markdown\"],\"settings\":{\"foreground\":\"#82b1ff\"}},{\"name\":\"Markdown Italics\",\"scope\":[\"markup.italic.markdown\"],\"settings\":{\"foreground\":\"#c792ea\",\"fontStyle\":\"italic\"}},{\"name\":\"Markdown Bold\",\"scope\":[\"markup.bold.markdown\"],\"settings\":{\"foreground\":\"#c5e478\",\"fontStyle\":\"bold\"}},{\"name\":\"Markdown Quote + others\",\"scope\":[\"markup.quote.markdown\"],\"settings\":{\"foreground\":\"#969bb7\",\"fontStyle\":\"\"}},{\"name\":\"Markdown Raw Code + others\",\"scope\":[\"markup.inline.raw.markdown\"],\"settings\":{\"foreground\":\"#80cbc4\"}},{\"name\":\"Markdown Links\",\"scope\":[\"markup.underline.link.markdown\",\"markup.underline.link.image.markdown\"],\"settings\":{\"foreground\":\"#ff869a\",\"fontStyle\":\"underline\"}},{\"name\":\"Markdown Link Title and Description\",\"scope\":[\"string.other.link.title.markdown\",\"string.other.link.description.markdown\"],\"settings\":{\"foreground\":\"#d6deeb\",\"fontStyle\":\"underline\"}},{\"name\":\"Markdown Punctuation\",\"scope\":[\"punctuation.definition.string.markdown\",\"punctuation.definition.string.begin.markdown\",\"punctuation.definition.string.end.markdown\",\"meta.link.inline.markdown punctuation.definition.string\"],\"settings\":{\"foreground\":\"#82b1ff\"}},{\"name\":\"Markdown MetaData Punctuation\",\"scope\":[\"punctuation.definition.metadata.markdown\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"Markdown List Punctuation\",\"scope\":[\"beginning.punctuation.definition.list.markdown\"],\"settings\":{\"foreground\":\"#82b1ff\"}},{\"name\":\"Markdown Inline Raw String\",\"scope\":[\"markup.inline.raw.string.markdown\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"PHP Variables\",\"scope\":[\"variable.other.php\"],\"settings\":{\"foreground\":\"#bec5d4\"}},{\"name\":\"Support Classes in PHP\",\"scope\":[\"support.class.php\"],\"settings\":{\"foreground\":\"#ffcb8b\"}},{\"name\":\"Punctuations in PHP function calls\",\"scope\":[\"meta.function-call.php punctuation\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"PHP Global Variables\",\"scope\":[\"variable.other.global.php\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Declaration Punctuation in PHP Global Variables\",\"scope\":[\"variable.other.global.php punctuation.definition.variable\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Language Constants in Python\",\"scope\":[\"constant.language.python\"],\"settings\":{\"foreground\":\"#ff6a83\"}},{\"name\":\"Python Function Parameter and Arguments\",\"scope\":[\"variable.parameter.function.python\",\"meta.function-call.arguments.python\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"Python Function Call\",\"scope\":[\"meta.function-call.python\",\"meta.function-call.generic.python\"],\"settings\":{\"foreground\":\"#b2ccd6\"}},{\"name\":\"Punctuations in Python\",\"scope\":[\"punctuation.python\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"Decorator Functions in Python\",\"scope\":[\"entity.name.function.decorator.python\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Python Language Variable\",\"scope\":[\"source.python variable.language.special\"],\"settings\":{\"foreground\":\"#8eace3\"}},{\"name\":\"Python import control keyword\",\"scope\":[\"keyword.control\"],\"settings\":{\"foreground\":\"#c792ea\"}},{\"name\":\"SCSS Variable\",\"scope\":[\"variable.scss\",\"variable.sass\",\"variable.parameter.url.scss\",\"variable.parameter.url.sass\"],\"settings\":{\"foreground\":\"#c5e478\"}},{\"name\":\"Variables in SASS At-Rules\",\"scope\":[\"source.css.scss meta.at-rule variable\",\"source.css.sass meta.at-rule variable\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"Variables in SASS At-Rules\",\"scope\":[\"source.css.scss meta.at-rule variable\",\"source.css.sass meta.at-rule variable\"],\"settings\":{\"foreground\":\"#bec5d4\"}},{\"name\":\"Attribute Name for SASS\",\"scope\":[\"meta.attribute-selector.scss entity.other.attribute-name.attribute\",\"meta.attribute-selector.sass entity.other.attribute-name.attribute\"],\"settings\":{\"foreground\":\"#f78c6c\"}},{\"name\":\"Tag names in SASS\",\"scope\":[\"entity.name.tag.scss\",\"entity.name.tag.sass\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"SASS Keyword Other Unit\",\"scope\":[\"keyword.other.unit.scss\",\"keyword.other.unit.sass\"],\"settings\":{\"foreground\":\"#ffeb95\"}},{\"name\":\"TypeScript[React] Variables and Object Properties\",\"scope\":[\"variable.other.readwrite.alias.ts\",\"variable.other.readwrite.alias.tsx\",\"variable.other.readwrite.ts\",\"variable.other.readwrite.tsx\",\"variable.other.object.ts\",\"variable.other.object.tsx\",\"variable.object.property.ts\",\"variable.object.property.tsx\",\"variable.other.ts\",\"variable.other.tsx\",\"variable.tsx\",\"variable.ts\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"TypeScript[React] Entity Name Types\",\"scope\":[\"entity.name.type.ts\",\"entity.name.type.tsx\"],\"settings\":{\"foreground\":\"#ffcb8b\"}},{\"name\":\"TypeScript[React] Node Classes\",\"scope\":[\"support.class.node.ts\",\"support.class.node.tsx\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"TypeScript[React] Entity Name Types as Parameters\",\"scope\":[\"meta.type.parameters.ts entity.name.type\",\"meta.type.parameters.tsx entity.name.type\"],\"settings\":{\"foreground\":\"#889fb2\"}},{\"name\":\"TypeScript[React] Import/Export Punctuations\",\"scope\":[\"meta.import.ts punctuation.definition.block\",\"meta.import.tsx punctuation.definition.block\",\"meta.export.ts punctuation.definition.block\",\"meta.export.tsx punctuation.definition.block\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"TypeScript[React] Punctuation Decorators\",\"scope\":[\"meta.decorator punctuation.decorator.ts\",\"meta.decorator punctuation.decorator.tsx\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"TypeScript[React] Punctuation Decorators\",\"scope\":[\"meta.tag.js meta.jsx.children.tsx\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"YAML Entity Name Tags\",\"scope\":[\"entity.name.tag.yaml\"],\"settings\":{\"foreground\":\"#7fdbca\"}},{\"name\":\"JavaScript Variable Other ReadWrite\",\"scope\":[\"variable.other.readwrite.js\",\"variable.parameter\"],\"settings\":{\"foreground\":\"#d7dbe0\"}},{\"name\":\"Support Class Component\",\"scope\":[\"support.class.component.js\",\"support.class.component.tsx\"],\"settings\":{\"foreground\":\"#f78c6c\",\"fontStyle\":\"\"}},{\"name\":\"Text nested in React tags\",\"scope\":[\"meta.jsx.children\",\"meta.jsx.children.js\",\"meta.jsx.children.tsx\"],\"settings\":{\"foreground\":\"#d6deeb\"}},{\"name\":\"TypeScript Classes\",\"scope\":[\"meta.class entity.name.type.class.tsx\"],\"settings\":{\"foreground\":\"#ffcb8b\"}},{\"name\":\"TypeScript Entity Name Type\",\"scope\":[\"entity.name.type.tsx\",\"entity.name.type.module.tsx\"],\"settings\":{\"foreground\":\"#ffcb8b\"}},{\"name\":\"TypeScript Class Variable Keyword\",\"scope\":[\"meta.class.ts meta.var.expr.ts storage.type.ts\",\"meta.class.tsx meta.var.expr.tsx storage.type.tsx\"],\"settings\":{\"foreground\":\"#c792ea\"}},{\"name\":\"TypeScript Method Declaration e.g. `constructor`\",\"scope\":[\"meta.method.declaration storage.type.ts\",\"meta.method.declaration storage.type.tsx\"],\"settings\":{\"foreground\":\"#82aaff\"}},{\"name\":\"normalize font style of certain components\",\"scope\":[\"meta.property-list.css meta.property-value.css variable.other.less\",\"meta.property-list.scss variable.scss\",\"meta.property-list.sass variable.sass\",\"meta.brace\",\"keyword.operator.operator\",\"keyword.operator.or.regexp\",\"keyword.operator.expression.in\",\"keyword.operator.relational\",\"keyword.operator.assignment\",\"keyword.operator.comparison\",\"keyword.operator.type\",\"keyword.operator\",\"keyword\",\"punctuation.definintion.string\",\"punctuation\",\"variable.other.readwrite.js\",\"storage.type\",\"source.css\",\"string.quoted\"],\"settings\":{\"fontStyle\":\"\"}}],\"styleOverrides\":{\"frames\":{\"editorBackground\":\"var(--sl-color-gray-6)\",\"terminalBackground\":\"var(--sl-color-gray-6)\",\"editorActiveTabBackground\":\"var(--sl-color-gray-6)\",\"terminalTitlebarDotsForeground\":\"color-mix(in srgb, var(--sl-color-gray-5), transparent 25%)\",\"terminalTitlebarDotsOpacity\":\"0.75\",\"inlineButtonForeground\":\"var(--sl-color-text)\",\"frameBoxShadowCssValue\":\"none\"},\"textMarkers\":{\"markBackground\":\"#ffffff17\",\"markBorderColor\":\"#ffffff40\"}}},{\"name\":\"Night Owl Light\",\"type\":\"light\",\"colors\":{\"focusBorder\":\"#93a1a1\",\"foreground\":\"#403f53\",\"disabledForeground\":\"#61616180\",\"descriptionForeground\":\"#403f53\",\"errorForeground\":\"#403f53\",\"icon.foreground\":\"#424242\",\"contrastActiveBorder\":null,\"contrastBorder\":null,\"textBlockQuote.background\":\"#7f7f7f1a\",\"textBlockQuote.border\":\"#007acc80\",\"textCodeBlock.background\":\"#dcdcdc66\",\"textLink.activeForeground\":\"#006ab1\",\"textLink.foreground\":\"#006ab1\",\"textPreformat.foreground\":\"#a31515\",\"textSeparator.foreground\":\"#0000002e\",\"editor.background\":\"#f6f7f9\",\"editor.foreground\":\"#403f53\",\"editorLineNumber.foreground\":\"#90a7b2\",\"editorLineNumber.activeForeground\":\"#403f53\",\"editorActiveLineNumber.foreground\":\"#0b216f\",\"editor.selectionBackground\":\"#e0e0e0\",\"editor.inactiveSelectionBackground\":\"#e0e0e080\",\"editor.selectionHighlightBackground\":\"#339cec33\",\"editorError.foreground\":\"#e64d49\",\"editorWarning.foreground\":\"#daaa01\",\"editorInfo.foreground\":\"#1a85ff\",\"editorHint.foreground\":\"#6c6c6c\",\"problemsErrorIcon.foreground\":\"#e64d49\",\"problemsWarningIcon.foreground\":\"#daaa01\",\"problemsInfoIcon.foreground\":\"#1a85ff\",\"editor.findMatchBackground\":\"#93a1a16c\",\"editor.findMatchHighlightBackground\":\"#93a1a16c\",\"editor.findRangeHighlightBackground\":\"#7497a633\",\"editorLink.activeForeground\":\"#0000ff\",\"editorLightBulb.foreground\":\"#ddb100\",\"editorLightBulbAutoFix.foreground\":\"#007acc\",\"diffEditor.insertedTextBackground\":\"#9ccc2c40\",\"diffEditor.insertedTextBorder\":null,\"diffEditor.removedTextBackground\":\"#ff000033\",\"diffEditor.removedTextBorder\":null,\"diffEditor.insertedLineBackground\":\"#9bb95533\",\"diffEditor.removedLineBackground\":\"#ff000033\",\"editorStickyScroll.background\":\"#fbfbfb\",\"editorStickyScrollHover.background\":\"#f0f0f0\",\"editorInlayHint.background\":\"#2aa29899\",\"editorInlayHint.foreground\":\"#f0f0f0\",\"editorInlayHint.typeBackground\":\"#2aa29899\",\"editorInlayHint.typeForeground\":\"#f0f0f0\",\"editorInlayHint.parameterBackground\":\"#2aa29899\",\"editorInlayHint.parameterForeground\":\"#f0f0f0\",\"editorPane.background\":\"#fbfbfb\",\"editorGroup.emptyBackground\":null,\"editorGroup.focusedEmptyBorder\":null,\"editorGroupHeader.tabsBackground\":\"var(--sl-color-gray-6)\",\"editorGroupHeader.tabsBorder\":\"color-mix(in srgb, var(--sl-color-gray-5), transparent 25%)\",\"editorGroupHeader.noTabsBackground\":\"#f0f0f0\",\"editorGroupHeader.border\":null,\"editorGroup.border\":\"#f0f0f0\",\"editorGroup.dropBackground\":\"#2677cb2d\",\"editorGroup.dropIntoPromptForeground\":\"#403f53\",\"editorGroup.dropIntoPromptBackground\":\"#f0f0f0\",\"editorGroup.dropIntoPromptBorder\":null,\"sideBySideEditor.horizontalBorder\":\"#f0f0f0\",\"sideBySideEditor.verticalBorder\":\"#f0f0f0\",\"scrollbar.shadow\":\"#cccccc\",\"scrollbarSlider.background\":\"#0000001a\",\"scrollbarSlider.hoverBackground\":\"#00000055\",\"scrollbarSlider.activeBackground\":\"#00000099\",\"panel.background\":\"#f0f0f0\",\"panel.border\":\"#d9d9d9\",\"panelTitle.activeBorder\":\"#424242\",\"panelTitle.activeForeground\":\"#424242\",\"panelTitle.inactiveForeground\":\"#424242bf\",\"panelSectionHeader.background\":\"#80808051\",\"terminal.background\":\"#f6f6f6\",\"widget.shadow\":\"#d9d9d9\",\"editorWidget.background\":\"#f0f0f0\",\"editorWidget.foreground\":\"#403f53\",\"editorWidget.border\":\"#d9d9d9\",\"quickInput.background\":\"#f0f0f0\",\"quickInput.foreground\":\"#403f53\",\"quickInputTitle.background\":\"#0000000f\",\"pickerGroup.foreground\":\"#403f53\",\"pickerGroup.border\":\"#d9d9d9\",\"editor.hoverHighlightBackground\":\"#339cec33\",\"editorHoverWidget.background\":\"#f0f0f0\",\"editorHoverWidget.foreground\":\"#403f53\",\"editorHoverWidget.border\":\"#d9d9d9\",\"editorHoverWidget.statusBarBackground\":\"#e4e4e4\",\"titleBar.activeBackground\":\"var(--sl-color-gray-6)\",\"titleBar.activeForeground\":\"var(--sl-color-text)\",\"titleBar.inactiveBackground\":\"#f0f0f099\",\"titleBar.inactiveForeground\":\"#33333399\",\"titleBar.border\":\"color-mix(in srgb, var(--sl-color-gray-5), transparent 25%)\",\"toolbar.hoverBackground\":\"#b8b8b850\",\"toolbar.activeBackground\":\"#a6a6a650\",\"tab.activeBackground\":\"#f6f6f6\",\"tab.unfocusedActiveBackground\":\"#f6f6f6\",\"tab.inactiveBackground\":\"#f0f0f0\",\"tab.unfocusedInactiveBackground\":\"#f0f0f0\",\"tab.activeForeground\":\"var(--sl-color-text)\",\"tab.inactiveForeground\":\"#403f53\",\"tab.unfocusedActiveForeground\":\"#403f53b3\",\"tab.unfocusedInactiveForeground\":\"#403f5380\",\"tab.hoverBackground\":null,\"tab.unfocusedHoverBackground\":null,\"tab.hoverForeground\":null,\"tab.unfocusedHoverForeground\":null,\"tab.border\":\"#f0f0f0\",\"tab.lastPinnedBorder\":\"#a9a9a9\",\"tab.activeBorder\":\"transparent\",\"tab.unfocusedActiveBorder\":null,\"tab.activeBorderTop\":\"var(--sl-color-accent)\",\"tab.unfocusedActiveBorderTop\":null,\"tab.hoverBorder\":null,\"tab.unfocusedHoverBorder\":null,\"tab.activeModifiedBorder\":\"#2aa298\",\"tab.inactiveModifiedBorder\":\"#93a1a1\",\"tab.unfocusedActiveModifiedBorder\":\"#93a1a1\",\"tab.unfocusedInactiveModifiedBorder\":\"#93a1a1\",\"badge.background\":\"#2aa298\",\"badge.foreground\":\"#f0f0f0\",\"button.background\":\"#2aa298\",\"button.foreground\":\"#f0f0f0\",\"button.border\":null,\"button.separator\":\"#f0f0f066\",\"button.hoverBackground\":\"#22827a\",\"button.secondaryBackground\":\"#5f6a79\",\"button.secondaryForeground\":\"#ffffff\",\"button.secondaryHoverBackground\":\"#4c5561\",\"dropdown.background\":\"#f0f0f0\",\"dropdown.foreground\":\"#403f53\",\"dropdown.border\":\"#d9d9d9\",\"list.activeSelectionBackground\":\"#d3e8f8\",\"list.activeSelectionForeground\":\"#403f53\",\"tree.indentGuidesStroke\":\"#a9a9a9\",\"input.background\":\"#f0f0f0\",\"input.foreground\":\"#403f53\",\"input.placeholderForeground\":\"#93a1a1\",\"inputOption.activeBorder\":\"#2aa298\",\"inputOption.hoverBackground\":\"#b8b8b850\",\"inputOption.activeBackground\":\"#93a1a133\",\"inputOption.activeForeground\":\"#000000\",\"inputValidation.infoBackground\":\"#f0f0f0\",\"inputValidation.infoBorder\":\"#d0d0d0\",\"inputValidation.warningBackground\":\"#daaa01\",\"inputValidation.warningBorder\":\"#e0af02\",\"inputValidation.errorBackground\":\"#f76e6e\",\"inputValidation.errorBorder\":\"#de3d3b\",\"keybindingLabel.background\":\"#dddddd66\",\"keybindingLabel.foreground\":\"#555555\",\"keybindingLabel.border\":\"#cccccc66\",\"keybindingLabel.bottomBorder\":\"#bbbbbb66\",\"menu.foreground\":\"#403f53\",\"menu.background\":\"#f0f0f0\",\"menu.selectionForeground\":\"#403f53\",\"menu.selectionBackground\":\"#d3e8f8\",\"menu.separatorBackground\":\"#d4d4d4\",\"editor.snippetTabstopHighlightBackground\":\"#0a326433\",\"editor.snippetFinalTabstopHighlightBorder\":\"#0a326480\",\"terminal.ansiBlack\":\"#403f53\",\"terminal.ansiRed\":\"#de3d3b\",\"terminal.ansiGreen\":\"#08916a\",\"terminal.ansiYellow\":\"#e0af02\",\"terminal.ansiBlue\":\"#288ed7\",\"terminal.ansiMagenta\":\"#d6438a\",\"terminal.ansiCyan\":\"#2aa298\",\"terminal.ansiWhite\":\"#f0f0f0\",\"terminal.ansiBrightBlack\":\"#403f53\",\"terminal.ansiBrightRed\":\"#de3d3b\",\"terminal.ansiBrightGreen\":\"#08916a\",\"terminal.ansiBrightYellow\":\"#daaa01\",\"terminal.ansiBrightBlue\":\"#288ed7\",\"terminal.ansiBrightMagenta\":\"#d6438a\",\"terminal.ansiBrightCyan\":\"#2aa298\",\"terminal.ansiBrightWhite\":\"#f0f0f0\",\"selection.background\":\"#7a8181ad\",\"notifications.background\":\"#f0f0f0\",\"notifications.foreground\":\"#403f53\",\"notificationLink.foreground\":\"#994cc3\",\"notifications.border\":\"#cccccc\",\"notificationCenter.border\":\"#cccccc\",\"notificationToast.border\":\"#cccccc\",\"notificationCenterHeader.foreground\":\"#403f53\",\"notificationCenterHeader.background\":\"#f0f0f0\",\"input.border\":\"#d9d9d9\",\"progressBar.background\":\"#2aa298\",\"list.inactiveSelectionBackground\":\"#e0e7ea\",\"list.inactiveSelectionForeground\":\"#403f53\",\"list.focusBackground\":\"#d3e8f8\",\"list.hoverBackground\":\"#d3e8f8\",\"list.focusForeground\":\"#403f53\",\"list.hoverForeground\":\"#403f53\",\"list.highlightForeground\":\"#403f53\",\"list.errorForeground\":\"#e64d49\",\"list.warningForeground\":\"#daaa01\",\"activityBar.background\":\"#f0f0f0\",\"activityBar.foreground\":\"#403f53\",\"activityBar.dropBackground\":\"#d0d0d0\",\"activityBarBadge.background\":\"#403f53\",\"activityBarBadge.foreground\":\"#f0f0f0\",\"activityBar.border\":\"#f0f0f0\",\"sideBar.background\":\"#f0f0f0\",\"sideBar.foreground\":\"#403f53\",\"sideBarTitle.foreground\":\"#403f53\",\"sideBar.border\":\"#f0f0f0\",\"editorGroup.background\":\"#f6f6f6\",\"editorCursor.foreground\":\"#90a7b2\",\"editor.wordHighlightBackground\":\"#339cec33\",\"editor.wordHighlightStrongBackground\":\"#007dd659\",\"editor.lineHighlightBackground\":\"#f0f0f0\",\"editor.rangeHighlightBackground\":\"#7497a633\",\"editorWhitespace.foreground\":\"#d9d9d9\",\"editorIndentGuide.background\":\"#d9d9d9\",\"editorCodeLens.foreground\":\"#403f53\",\"editorBracketMatch.background\":\"#d3e8f8\",\"editorBracketMatch.border\":\"#2aa298\",\"editorError.border\":\"#fbfbfb\",\"editorWarning.border\":\"#daaa01\",\"editorGutter.addedBackground\":\"#49d0c5\",\"editorGutter.modifiedBackground\":\"#6fbef6\",\"editorGutter.deletedBackground\":\"#f76e6e\",\"editorRuler.foreground\":\"#d9d9d9\",\"editorOverviewRuler.errorForeground\":\"#e64d49\",\"editorOverviewRuler.warningForeground\":\"#daaa01\",\"editorSuggestWidget.background\":\"#f0f0f0\",\"editorSuggestWidget.foreground\":\"#403f53\",\"editorSuggestWidget.highlightForeground\":\"#403f53\",\"editorSuggestWidget.selectedBackground\":\"#d3e8f8\",\"editorSuggestWidget.border\":\"#d9d9d9\",\"debugExceptionWidget.background\":\"#f0f0f0\",\"debugExceptionWidget.border\":\"#d9d9d9\",\"editorMarkerNavigation.background\":\"#d0d0d0\",\"editorMarkerNavigationError.background\":\"#f76e6e\",\"editorMarkerNavigationWarning.background\":\"#daaa01\",\"debugToolBar.background\":\"#f0f0f0\",\"extensionButton.prominentBackground\":\"#2aa298\",\"extensionButton.prominentForeground\":\"#f0f0f0\",\"statusBar.background\":\"#f0f0f0\",\"statusBar.border\":\"#f0f0f0\",\"statusBar.debuggingBackground\":\"#f0f0f0\",\"statusBar.debuggingForeground\":\"#403f53\",\"statusBar.foreground\":\"#403f53\",\"statusBar.noFolderBackground\":\"#f0f0f0\",\"statusBar.noFolderForeground\":\"#403f53\",\"peekView.border\":\"#d9d9d9\",\"peekViewEditor.background\":\"#f6f6f6\",\"peekViewEditorGutter.background\":\"#f6f6f6\",\"peekViewEditor.matchHighlightBackground\":\"#49d0c5\",\"peekViewResult.background\":\"#f0f0f0\",\"peekViewResult.fileForeground\":\"#403f53\",\"peekViewResult.lineForeground\":\"#403f53\",\"peekViewResult.matchHighlightBackground\":\"#49d0c5\",\"peekViewResult.selectionBackground\":\"#e0e7ea\",\"peekViewResult.selectionForeground\":\"#403f53\",\"peekViewTitle.background\":\"#f0f0f0\",\"peekViewTitleLabel.foreground\":\"#403f53\",\"peekViewTitleDescription.foreground\":\"#403f53\",\"terminal.foreground\":\"#403f53\"},\"fg\":\"#403f53\",\"bg\":\"#f6f7f9\",\"semanticHighlighting\":false,\"settings\":[{\"name\":\"Changed\",\"scope\":[\"markup.changed\",\"meta.diff.header.git\",\"meta.diff.header.from-file\",\"meta.diff.header.to-file\"],\"settings\":{\"foreground\":\"#556484\"}},{\"name\":\"Deleted\",\"scope\":[\"markup.deleted.diff\"],\"settings\":{\"foreground\":\"#ae3c3afd\"}},{\"name\":\"Inserted\",\"scope\":[\"markup.inserted.diff\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Global settings\",\"settings\":{\"background\":\"#011627\",\"foreground\":\"#403f53\"}},{\"name\":\"Comment\",\"scope\":[\"comment\"],\"settings\":{\"foreground\":\"#5f636f\"}},{\"name\":\"String\",\"scope\":[\"string\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"String Quoted\",\"scope\":[\"string.quoted\",\"variable.other.readwrite.js\"],\"settings\":{\"foreground\":\"#984e4d\"}},{\"name\":\"Support Constant Math\",\"scope\":[\"support.constant.math\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Number\",\"scope\":[\"constant.numeric\",\"constant.character.numeric\"],\"settings\":{\"foreground\":\"#aa0982\",\"fontStyle\":\"\"}},{\"name\":\"Built-in constant\",\"scope\":[\"constant.language\",\"punctuation.definition.constant\",\"variable.other.constant\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"User-defined constant\",\"scope\":[\"constant.character\",\"constant.other\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Constant Character Escape\",\"scope\":[\"constant.character.escape\"],\"settings\":{\"foreground\":\"#aa0982\"}},{\"name\":\"RegExp String\",\"scope\":[\"string.regexp\",\"string.regexp keyword.other\"],\"settings\":{\"foreground\":\"#3a688f\"}},{\"name\":\"Comma in functions\",\"scope\":[\"meta.function punctuation.separator.comma\"],\"settings\":{\"foreground\":\"#4d667b\"}},{\"name\":\"Variable\",\"scope\":[\"variable\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Keyword\",\"scope\":[\"punctuation.accessor\",\"keyword\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Storage\",\"scope\":[\"storage\",\"meta.var.expr\",\"meta.class meta.method.declaration meta.var.expr storage.type.js\",\"storage.type.property.js\",\"storage.type.property.ts\",\"storage.type.property.tsx\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Storage type\",\"scope\":[\"storage.type\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Storage type\",\"scope\":[\"storage.type.function.arrow.js\"],\"settings\":{\"fontStyle\":\"\"}},{\"name\":\"Class name\",\"scope\":[\"entity.name.class\",\"meta.class entity.name.type.class\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"Inherited class\",\"scope\":[\"entity.other.inherited-class\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Function name\",\"scope\":[\"entity.name.function\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Meta Tag\",\"scope\":[\"punctuation.definition.tag\",\"meta.tag\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"HTML Tag names\",\"scope\":[\"entity.name.tag\",\"meta.tag.other.html\",\"meta.tag.other.js\",\"meta.tag.other.tsx\",\"entity.name.tag.tsx\",\"entity.name.tag.js\",\"entity.name.tag\",\"meta.tag.js\",\"meta.tag.tsx\",\"meta.tag.html\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Tag attribute\",\"scope\":[\"entity.other.attribute-name\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Entity Name Tag Custom\",\"scope\":[\"entity.name.tag.custom\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Library (function & constant)\",\"scope\":[\"support.function\",\"support.constant\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Support Constant Property Value meta\",\"scope\":[\"support.constant.meta.property-value\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Library class/type\",\"scope\":[\"support.type\",\"support.class\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Support Variable DOM\",\"scope\":[\"support.variable.dom\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Invalid\",\"scope\":[\"invalid\"],\"settings\":{\"foreground\":\"#bb2060\"}},{\"name\":\"Invalid deprecated\",\"scope\":[\"invalid.deprecated\"],\"settings\":{\"foreground\":\"#b23834\"}},{\"name\":\"Keyword Operator\",\"scope\":[\"keyword.operator\"],\"settings\":{\"foreground\":\"#096e72\",\"fontStyle\":\"\"}},{\"name\":\"Keyword Operator Relational\",\"scope\":[\"keyword.operator.relational\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Keyword Operator Assignment\",\"scope\":[\"keyword.operator.assignment\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Keyword Operator Arithmetic\",\"scope\":[\"keyword.operator.arithmetic\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Keyword Operator Bitwise\",\"scope\":[\"keyword.operator.bitwise\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Keyword Operator Increment\",\"scope\":[\"keyword.operator.increment\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Keyword Operator Ternary\",\"scope\":[\"keyword.operator.ternary\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Double-Slashed Comment\",\"scope\":[\"comment.line.double-slash\"],\"settings\":{\"foreground\":\"#5d6376\"}},{\"name\":\"Object\",\"scope\":[\"object\"],\"settings\":{\"foreground\":\"#58656a\"}},{\"name\":\"Null\",\"scope\":[\"constant.language.null\"],\"settings\":{\"foreground\":\"#a24848\"}},{\"name\":\"Meta Brace\",\"scope\":[\"meta.brace\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"Meta Delimiter Period\",\"scope\":[\"meta.delimiter.period\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Punctuation Definition String\",\"scope\":[\"punctuation.definition.string\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"Punctuation Definition String Markdown\",\"scope\":[\"punctuation.definition.string.begin.markdown\"],\"settings\":{\"foreground\":\"#a24848\"}},{\"name\":\"Boolean\",\"scope\":[\"constant.language.boolean\"],\"settings\":{\"foreground\":\"#a24848\"}},{\"name\":\"Object Comma\",\"scope\":[\"object.comma\"],\"settings\":{\"foreground\":\"#646464\"}},{\"name\":\"Variable Parameter Function\",\"scope\":[\"variable.parameter.function\"],\"settings\":{\"foreground\":\"#096e72\",\"fontStyle\":\"\"}},{\"name\":\"Support Type Property Name & entity name tags\",\"scope\":[\"support.type.vendor.property-name\",\"support.constant.vendor.property-value\",\"support.type.property-name\",\"meta.property-list entity.name.tag\"],\"settings\":{\"foreground\":\"#096e72\",\"fontStyle\":\"\"}},{\"name\":\"Entity Name tag reference in stylesheets\",\"scope\":[\"meta.property-list entity.name.tag.reference\"],\"settings\":{\"foreground\":\"#286d70\"}},{\"name\":\"Constant Other Color RGB Value Punctuation Definition Constant\",\"scope\":[\"constant.other.color.rgb-value punctuation.definition.constant\"],\"settings\":{\"foreground\":\"#aa0982\"}},{\"name\":\"Constant Other Color\",\"scope\":[\"constant.other.color\"],\"settings\":{\"foreground\":\"#aa0982\"}},{\"name\":\"Keyword Other Unit\",\"scope\":[\"keyword.other.unit\"],\"settings\":{\"foreground\":\"#aa0982\"}},{\"name\":\"Meta Selector\",\"scope\":[\"meta.selector\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Entity Other Attribute Name Id\",\"scope\":[\"entity.other.attribute-name.id\"],\"settings\":{\"foreground\":\"#aa0982\"}},{\"name\":\"Meta Property Name\",\"scope\":[\"meta.property-name\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Doctypes\",\"scope\":[\"entity.name.tag.doctype\",\"meta.tag.sgml.doctype\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Punctuation Definition Parameters\",\"scope\":[\"punctuation.definition.parameters\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"Keyword Control Operator\",\"scope\":[\"keyword.control.operator\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Keyword Operator Logical\",\"scope\":[\"keyword.operator.logical\"],\"settings\":{\"foreground\":\"#8844ae\",\"fontStyle\":\"\"}},{\"name\":\"Variable Instances\",\"scope\":[\"variable.instance\",\"variable.other.instance\",\"variable.readwrite.instance\",\"variable.other.readwrite.instance\",\"variable.other.property\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Variable Property Other object property\",\"scope\":[\"variable.other.object.property\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"Variable Property Other object\",\"scope\":[\"variable.other.object.js\"],\"settings\":{\"fontStyle\":\"\"}},{\"name\":\"Entity Name Function\",\"scope\":[\"entity.name.function\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Keyword Operator Comparison, imports, returns and Keyword Operator Ruby\",\"scope\":[\"keyword.operator.comparison\",\"keyword.control.flow.js\",\"keyword.control.flow.ts\",\"keyword.control.flow.tsx\",\"keyword.control.ruby\",\"keyword.control.module.ruby\",\"keyword.control.class.ruby\",\"keyword.control.def.ruby\",\"keyword.control.loop.js\",\"keyword.control.loop.ts\",\"keyword.control.import.js\",\"keyword.control.import.ts\",\"keyword.control.import.tsx\",\"keyword.control.from.js\",\"keyword.control.from.ts\",\"keyword.control.from.tsx\",\"keyword.operator.instanceof.js\",\"keyword.operator.expression.instanceof.ts\",\"keyword.operator.expression.instanceof.tsx\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Keyword Control Conditional\",\"scope\":[\"keyword.control.conditional.js\",\"keyword.control.conditional.ts\",\"keyword.control.switch.js\",\"keyword.control.switch.ts\"],\"settings\":{\"foreground\":\"#8844ae\",\"fontStyle\":\"\"}},{\"name\":\"Support Constant, `new` keyword, Special Method Keyword, `debugger`, other keywords\",\"scope\":[\"support.constant\",\"keyword.other.special-method\",\"keyword.other.new\",\"keyword.other.debugger\",\"keyword.control\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Support Function\",\"scope\":[\"support.function\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Invalid Broken\",\"scope\":[\"invalid.broken\"],\"settings\":{\"foreground\":\"#aa0982\"}},{\"name\":\"Invalid Unimplemented\",\"scope\":[\"invalid.unimplemented\"],\"settings\":{\"foreground\":\"#486e26\"}},{\"name\":\"Invalid Illegal\",\"scope\":[\"invalid.illegal\"],\"settings\":{\"foreground\":\"#984e4d\"}},{\"name\":\"Language Variable\",\"scope\":[\"variable.language\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Support Variable Property\",\"scope\":[\"support.variable.property\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Variable Function\",\"scope\":[\"variable.function\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Variable Interpolation\",\"scope\":[\"variable.interpolation\"],\"settings\":{\"foreground\":\"#a64348\"}},{\"name\":\"Meta Function Call\",\"scope\":[\"meta.function-call\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Punctuation Section Embedded\",\"scope\":[\"punctuation.section.embedded\"],\"settings\":{\"foreground\":\"#b23834\"}},{\"name\":\"Punctuation Tweaks\",\"scope\":[\"punctuation.terminator.expression\",\"punctuation.definition.arguments\",\"punctuation.definition.array\",\"punctuation.section.array\",\"meta.array\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"More Punctuation Tweaks\",\"scope\":[\"punctuation.definition.list.begin\",\"punctuation.definition.list.end\",\"punctuation.separator.arguments\",\"punctuation.definition.list\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"Template Strings\",\"scope\":[\"string.template meta.template.expression\"],\"settings\":{\"foreground\":\"#b23834\"}},{\"name\":\"Backtics(``) in Template Strings\",\"scope\":[\"string.template punctuation.definition.string\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"Italics\",\"scope\":[\"italic\"],\"settings\":{\"foreground\":\"#8844ae\",\"fontStyle\":\"italic\"}},{\"name\":\"Bold\",\"scope\":[\"bold\"],\"settings\":{\"foreground\":\"#3b61b0\",\"fontStyle\":\"bold\"}},{\"name\":\"Quote\",\"scope\":[\"quote\"],\"settings\":{\"foreground\":\"#5c6285\"}},{\"name\":\"Raw Code\",\"scope\":[\"raw\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"CoffeScript Variable Assignment\",\"scope\":[\"variable.assignment.coffee\"],\"settings\":{\"foreground\":\"#186e73\"}},{\"name\":\"CoffeScript Parameter Function\",\"scope\":[\"variable.parameter.function.coffee\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"CoffeeScript Assignments\",\"scope\":[\"variable.assignment.coffee\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"C# Readwrite Variables\",\"scope\":[\"variable.other.readwrite.cs\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"C# Classes & Storage types\",\"scope\":[\"entity.name.type.class.cs\",\"storage.type.cs\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"C# Namespaces\",\"scope\":[\"entity.name.type.namespace.cs\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Tag names in Stylesheets\",\"scope\":[\"entity.name.tag.css\",\"entity.name.tag.less\",\"entity.name.tag.custom.css\",\"support.constant.property-value.css\"],\"settings\":{\"foreground\":\"#984e4d\",\"fontStyle\":\"\"}},{\"name\":\"Wildcard(*) selector in Stylesheets\",\"scope\":[\"entity.name.tag.wildcard.css\",\"entity.name.tag.wildcard.less\",\"entity.name.tag.wildcard.scss\",\"entity.name.tag.wildcard.sass\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"CSS Keyword Other Unit\",\"scope\":[\"keyword.other.unit.css\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Attribute Name for CSS\",\"scope\":[\"meta.attribute-selector.css entity.other.attribute-name.attribute\",\"variable.other.readwrite.js\"],\"settings\":{\"foreground\":\"#aa0982\"}},{\"name\":\"Elixir Classes\",\"scope\":[\"source.elixir support.type.elixir\",\"source.elixir meta.module.elixir entity.name.class.elixir\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Elixir Functions\",\"scope\":[\"source.elixir entity.name.function\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Elixir Constants\",\"scope\":[\"source.elixir constant.other.symbol.elixir\",\"source.elixir constant.other.keywords.elixir\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Elixir String Punctuations\",\"scope\":[\"source.elixir punctuation.definition.string\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Elixir\",\"scope\":[\"source.elixir variable.other.readwrite.module.elixir\",\"source.elixir variable.other.readwrite.module.elixir punctuation.definition.variable.elixir\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Elixir Binary Punctuations\",\"scope\":[\"source.elixir .punctuation.binary.elixir\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Closure Constant Keyword\",\"scope\":[\"constant.keyword.clojure\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Go Function Calls\",\"scope\":[\"source.go meta.function-call.go\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Go Keywords\",\"scope\":[\"source.go keyword.package.go\",\"source.go keyword.import.go\",\"source.go keyword.function.go\",\"source.go keyword.type.go\",\"source.go keyword.struct.go\",\"source.go keyword.interface.go\",\"source.go keyword.const.go\",\"source.go keyword.var.go\",\"source.go keyword.map.go\",\"source.go keyword.channel.go\",\"source.go keyword.control.go\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"Go Constants e.g. nil, string format (%s, %d, etc.)\",\"scope\":[\"source.go constant.language.go\",\"source.go constant.other.placeholder.go\"],\"settings\":{\"foreground\":\"#a24848\"}},{\"name\":\"C++ Functions\",\"scope\":[\"entity.name.function.preprocessor.cpp\",\"entity.scope.name.cpp\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"C++ Meta Namespace\",\"scope\":[\"meta.namespace-block.cpp\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"C++ Language Primitive Storage\",\"scope\":[\"storage.type.language.primitive.cpp\"],\"settings\":{\"foreground\":\"#a24848\"}},{\"name\":\"C++ Preprocessor Macro\",\"scope\":[\"meta.preprocessor.macro.cpp\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"C++ Variable Parameter\",\"scope\":[\"variable.parameter\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"Powershell Variables\",\"scope\":[\"variable.other.readwrite.powershell\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Powershell Function\",\"scope\":[\"support.function.powershell\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"ID Attribute Name in HTML\",\"scope\":[\"entity.other.attribute-name.id.html\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"HTML Punctuation Definition Tag\",\"scope\":[\"punctuation.definition.tag.html\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"HTML Doctype\",\"scope\":[\"meta.tag.sgml.doctype.html\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"JavaScript Classes\",\"scope\":[\"meta.class entity.name.type.class.js\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"JavaScript Method Declaration e.g. `constructor`\",\"scope\":[\"meta.method.declaration storage.type.js\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"JavaScript Terminator\",\"scope\":[\"terminator.js\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"JavaScript Meta Punctuation Definition\",\"scope\":[\"meta.js punctuation.definition.js\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"Entity Names in Code Documentations\",\"scope\":[\"entity.name.type.instance.jsdoc\",\"entity.name.type.instance.phpdoc\"],\"settings\":{\"foreground\":\"#4d667b\"}},{\"name\":\"Other Variables in Code Documentations\",\"scope\":[\"variable.other.jsdoc\",\"variable.other.phpdoc\"],\"settings\":{\"foreground\":\"#3e697c\"}},{\"name\":\"JavaScript module imports and exports\",\"scope\":[\"variable.other.meta.import.js\",\"meta.import.js variable.other\",\"variable.other.meta.export.js\",\"meta.export.js variable.other\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"JavaScript Variable Parameter Function\",\"scope\":[\"variable.parameter.function.js\"],\"settings\":{\"foreground\":\"#555ea2\"}},{\"name\":\"JavaScript[React] Variable Other Object\",\"scope\":[\"variable.other.object.js\",\"variable.other.object.jsx\",\"variable.object.property.js\",\"variable.object.property.jsx\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"JavaScript Variables\",\"scope\":[\"variable.js\",\"variable.other.js\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"JavaScript Entity Name Type\",\"scope\":[\"entity.name.type.js\",\"entity.name.type.module.js\"],\"settings\":{\"foreground\":\"#111111\",\"fontStyle\":\"\"}},{\"name\":\"JavaScript Support Classes\",\"scope\":[\"support.class.js\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"JSON Property Names\",\"scope\":[\"support.type.property-name.json\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"JSON Support Constants\",\"scope\":[\"support.constant.json\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"JSON Property values (string)\",\"scope\":[\"meta.structure.dictionary.value.json string.quoted.double\"],\"settings\":{\"foreground\":\"#7c5686\"}},{\"name\":\"Strings in JSON values\",\"scope\":[\"string.quoted.double.json punctuation.definition.string.json\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Specific JSON Property values like null\",\"scope\":[\"meta.structure.dictionary.json meta.structure.dictionary.value constant.language\"],\"settings\":{\"foreground\":\"#a24848\"}},{\"name\":\"JavaScript Other Variable\",\"scope\":[\"variable.other.object.js\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Ruby Variables\",\"scope\":[\"variable.other.ruby\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"Ruby Class\",\"scope\":[\"entity.name.type.class.ruby\"],\"settings\":{\"foreground\":\"#984e4d\"}},{\"name\":\"Ruby Hashkeys\",\"scope\":[\"constant.language.symbol.hashkey.ruby\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Ruby Symbols\",\"scope\":[\"constant.language.symbol.ruby\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"LESS Tag names\",\"scope\":[\"entity.name.tag.less\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"LESS Keyword Other Unit\",\"scope\":[\"keyword.other.unit.css\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Attribute Name for LESS\",\"scope\":[\"meta.attribute-selector.less entity.other.attribute-name.attribute\"],\"settings\":{\"foreground\":\"#aa0982\"}},{\"name\":\"Markdown Headings\",\"scope\":[\"markup.heading.markdown\",\"markup.heading.setext.1.markdown\",\"markup.heading.setext.2.markdown\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Markdown Italics\",\"scope\":[\"markup.italic.markdown\"],\"settings\":{\"foreground\":\"#8844ae\",\"fontStyle\":\"italic\"}},{\"name\":\"Markdown Bold\",\"scope\":[\"markup.bold.markdown\"],\"settings\":{\"foreground\":\"#3b61b0\",\"fontStyle\":\"bold\"}},{\"name\":\"Markdown Quote + others\",\"scope\":[\"markup.quote.markdown\"],\"settings\":{\"foreground\":\"#5c6285\"}},{\"name\":\"Markdown Raw Code + others\",\"scope\":[\"markup.inline.raw.markdown\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Markdown Links\",\"scope\":[\"markup.underline.link.markdown\",\"markup.underline.link.image.markdown\"],\"settings\":{\"foreground\":\"#954f5a\",\"fontStyle\":\"underline\"}},{\"name\":\"Markdown Link Title and Description\",\"scope\":[\"string.other.link.title.markdown\",\"string.other.link.description.markdown\"],\"settings\":{\"foreground\":\"#403f53\",\"fontStyle\":\"underline\"}},{\"name\":\"Markdown Punctuation\",\"scope\":[\"punctuation.definition.string.markdown\",\"punctuation.definition.string.begin.markdown\",\"punctuation.definition.string.end.markdown\",\"meta.link.inline.markdown punctuation.definition.string\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Markdown MetaData Punctuation\",\"scope\":[\"punctuation.definition.metadata.markdown\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Markdown List Punctuation\",\"scope\":[\"beginning.punctuation.definition.list.markdown\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Markdown Inline Raw String\",\"scope\":[\"markup.inline.raw.string.markdown\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"PHP Variables\",\"scope\":[\"variable.other.php\",\"variable.other.property.php\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"Support Classes in PHP\",\"scope\":[\"support.class.php\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"Punctuations in PHP function calls\",\"scope\":[\"meta.function-call.php punctuation\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"PHP Global Variables\",\"scope\":[\"variable.other.global.php\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Declaration Punctuation in PHP Global Variables\",\"scope\":[\"variable.other.global.php punctuation.definition.variable\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Language Constants in Python\",\"scope\":[\"constant.language.python\"],\"settings\":{\"foreground\":\"#a24848\"}},{\"name\":\"Python Function Parameter and Arguments\",\"scope\":[\"variable.parameter.function.python\",\"meta.function-call.arguments.python\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Python Function Call\",\"scope\":[\"meta.function-call.python\",\"meta.function-call.generic.python\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"Punctuations in Python\",\"scope\":[\"punctuation.python\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"Decorator Functions in Python\",\"scope\":[\"entity.name.function.decorator.python\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Python Language Variable\",\"scope\":[\"source.python variable.language.special\"],\"settings\":{\"foreground\":\"#aa0982\"}},{\"name\":\"Python import control keyword\",\"scope\":[\"keyword.control\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"SCSS Variable\",\"scope\":[\"variable.scss\",\"variable.sass\",\"variable.parameter.url.scss\",\"variable.parameter.url.sass\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Variables in SASS At-Rules\",\"scope\":[\"source.css.scss meta.at-rule variable\",\"source.css.sass meta.at-rule variable\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"Variables in SASS At-Rules\",\"scope\":[\"source.css.scss meta.at-rule variable\",\"source.css.sass meta.at-rule variable\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"Attribute Name for SASS\",\"scope\":[\"meta.attribute-selector.scss entity.other.attribute-name.attribute\",\"meta.attribute-selector.sass entity.other.attribute-name.attribute\"],\"settings\":{\"foreground\":\"#aa0982\"}},{\"name\":\"Tag names in SASS\",\"scope\":[\"entity.name.tag.scss\",\"entity.name.tag.sass\"],\"settings\":{\"foreground\":\"#096e72\"}},{\"name\":\"SASS Keyword Other Unit\",\"scope\":[\"keyword.other.unit.scss\",\"keyword.other.unit.sass\"],\"settings\":{\"foreground\":\"#8844ae\"}},{\"name\":\"TypeScript[React] Variables and Object Properties\",\"scope\":[\"variable.other.readwrite.alias.ts\",\"variable.other.readwrite.alias.tsx\",\"variable.other.readwrite.ts\",\"variable.other.readwrite.tsx\",\"variable.other.object.ts\",\"variable.other.object.tsx\",\"variable.object.property.ts\",\"variable.object.property.tsx\",\"variable.other.ts\",\"variable.other.tsx\",\"variable.tsx\",\"variable.ts\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"TypeScript[React] Entity Name Types\",\"scope\":[\"entity.name.type.ts\",\"entity.name.type.tsx\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"TypeScript[React] Node Classes\",\"scope\":[\"support.class.node.ts\",\"support.class.node.tsx\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"TypeScript[React] Entity Name Types as Parameters\",\"scope\":[\"meta.type.parameters.ts entity.name.type\",\"meta.type.parameters.tsx entity.name.type\"],\"settings\":{\"foreground\":\"#4d667b\"}},{\"name\":\"TypeScript[React] Import/Export Punctuations\",\"scope\":[\"meta.import.ts punctuation.definition.block\",\"meta.import.tsx punctuation.definition.block\",\"meta.export.ts punctuation.definition.block\",\"meta.export.tsx punctuation.definition.block\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"TypeScript[React] Punctuation Decorators\",\"scope\":[\"meta.decorator punctuation.decorator.ts\",\"meta.decorator punctuation.decorator.tsx\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"TypeScript[React] Punctuation Decorators\",\"scope\":[\"meta.tag.js meta.jsx.children.tsx\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"YAML Entity Name Tags\",\"scope\":[\"entity.name.tag.yaml\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"JavaScript Variable Other ReadWrite\",\"scope\":[\"variable.other.readwrite.js\",\"variable.parameter\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"Support Class Component\",\"scope\":[\"support.class.component.js\",\"support.class.component.tsx\"],\"settings\":{\"foreground\":\"#aa0982\",\"fontStyle\":\"\"}},{\"name\":\"Text nested in React tags\",\"scope\":[\"meta.jsx.children\",\"meta.jsx.children.js\",\"meta.jsx.children.tsx\"],\"settings\":{\"foreground\":\"#403f53\"}},{\"name\":\"TypeScript Classes\",\"scope\":[\"meta.class entity.name.type.class.tsx\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"TypeScript Entity Name Type\",\"scope\":[\"entity.name.type.tsx\",\"entity.name.type.module.tsx\"],\"settings\":{\"foreground\":\"#111111\"}},{\"name\":\"TypeScript Class Variable Keyword\",\"scope\":[\"meta.class.ts meta.var.expr.ts storage.type.ts\",\"meta.class.tsx meta.var.expr.tsx storage.type.tsx\"],\"settings\":{\"foreground\":\"#76578b\"}},{\"name\":\"TypeScript Method Declaration e.g. `constructor`\",\"scope\":[\"meta.method.declaration storage.type.ts\",\"meta.method.declaration storage.type.tsx\"],\"settings\":{\"foreground\":\"#3b61b0\"}},{\"name\":\"normalize font style of certain components\",\"scope\":[\"meta.property-list.css meta.property-value.css variable.other.less\",\"meta.property-list.scss variable.scss\",\"meta.property-list.sass variable.sass\",\"meta.brace\",\"keyword.operator.operator\",\"keyword.operator.or.regexp\",\"keyword.operator.expression.in\",\"keyword.operator.relational\",\"keyword.operator.assignment\",\"keyword.operator.comparison\",\"keyword.operator.type\",\"keyword.operator\",\"keyword\",\"punctuation.definintion.string\",\"punctuation\",\"variable.other.readwrite.js\",\"storage.type\",\"source.css\",\"string.quoted\"],\"settings\":{\"fontStyle\":\"\"}}],\"styleOverrides\":{\"frames\":{\"editorBackground\":\"var(--sl-color-gray-7)\",\"terminalBackground\":\"var(--sl-color-gray-7)\",\"editorActiveTabBackground\":\"var(--sl-color-gray-7)\",\"terminalTitlebarDotsForeground\":\"color-mix(in srgb, var(--sl-color-gray-5), transparent 25%)\",\"terminalTitlebarDotsOpacity\":\"0.75\",\"inlineButtonForeground\":\"var(--sl-color-text)\",\"frameBoxShadowCssValue\":\"none\"},\"textMarkers\":{\"markBackground\":\"#0000001a\",\"markBorderColor\":\"#00000055\"}}}],\"defaultLocale\":\"en\",\"cascadeLayer\":\"starlight.components\",\"styleOverrides\":{\"borderRadius\":\"0px\",\"borderWidth\":\"1px\",\"codePaddingBlock\":\"0.75rem\",\"codePaddingInline\":\"1rem\",\"codeFontFamily\":\"var(--__sl-font-mono)\",\"codeFontSize\":\"var(--sl-text-code)\",\"codeLineHeight\":\"var(--sl-line-height)\",\"uiFontFamily\":\"var(--__sl-font)\",\"textMarkers\":{\"lineDiffIndicatorMarginLeft\":\"0.25rem\",\"defaultChroma\":\"45\",\"backgroundOpacity\":\"60%\"}},\"plugins\":[{\"name\":\"Starlight Plugin\",\"hooks\":{}},{\"name\":\"astro-expressive-code\",\"hooks\":{}}]}]],\"remarkRehype\":{},\"gfm\":true,\"smartypants\":true},\"security\":{\"checkOrigin\":true,\"allowedDomains\":[]},\"env\":{\"schema\":{},\"validateSecrets\":false},\"experimental\":{\"clientPrerender\":false,\"contentIntellisense\":false,\"headingIdCompat\":false,\"preserveScriptOrder\":false,\"liveContentCollections\":false,\"csp\":false,\"staticImportMetaEnv\":false,\"chromeDevtoolsWorkspace\":false,\"failOnPrerenderConflict\":false,\"svgo\":false},\"legacy\":{\"collections\":false},\"prefetch\":{\"prefetchAll\":true},\"i18n\":{\"defaultLocale\":\"en\",\"locales\":[\"en\"],\"routing\":{\"prefixDefaultLocale\":false,\"redirectToDefaultLocale\":false,\"fallbackType\":\"redirect\"}}}","docs",["Map",11,12,25,26,36,37,47,48,58,59,85,86,96,97,107,108,118,119,129,130,140,141,151,152,162,163,173,174,184,185,195,196,206,207,217,218,228,229,239,240,250,251,261,262,272,273,283,284,294,295,305,306,316,317,327,328,338,339,349,350,360,361,371,372,382,383,393,394,404,405,415,416,426,427,437,438,448,449,459,460,470,471],"contributing",{"id":11,"data":13,"body":22,"filePath":23,"digest":24,"deferredRender":16},{"title":14,"description":15,"editUrl":16,"head":17,"template":18,"sidebar":19,"pagefind":16,"draft":20},"Contributing","How to contribute to the Runtime Environment Protocol project.",true,[],"doc",{"hidden":20,"attrs":21},false,{},"import { Aside } from '@astrojs/starlight/components';\n\n## Getting started\n\n### Prerequisites\n\n- **Node.js** >= 20.0.0\n- **pnpm** >= 9.0.0 — `npm install -g pnpm`\n- **Go** >= 1.24.5 (for gateway development only)\n\n### Setup\n\n```bash\ngit clone https://github.com/ruachtech/rep.git\ncd rep\npnpm install\npnpm run build\npnpm run test\n```\n\nFor gateway:\n```bash\ncd gateway\ngo test -race ./...\n```\n\n## Project structure\n\n```\nrep/\n├── spec/ # Protocol specification documents\n├── schema/ # JSON schemas for payload and manifest\n├── gateway/ # Go reference implementation (stdlib only)\n├── sdk/ # @rep-protocol/sdk (zero runtime deps)\n├── cli/ # @rep-protocol/cli\n├── adapters/ # React, Vue, Svelte adapters\n├── codemod/ # Migration tool\n├── docs/ # This documentation site (Astro/Starlight)\n└── examples/ # Example applications\n```\n\n## Commit conventions\n\nThis project uses [Conventional Commits](https://www.conventionalcommits.org/). Every commit to `main` must follow this format:\n\n```\n\u003Ctype>(\u003Cscope>): \u003Cdescription>\n\n[optional body]\n```\n\n### Types\n\n| Type | Effect | Example |\n|---|---|---|\n| `fix` | Patch release | `fix(sdk): handle missing meta field` |\n| `feat` | Minor release | `feat(gateway): add poll mode for hot reload` |\n| `feat!` | Major release | `feat!(sdk)!: rename getSecure to decrypt` |\n| `docs` | No release | `docs(spec): clarify SRI verification` |\n| `chore` | No release | `chore: update dev dependencies` |\n| `refactor` | No release | `refactor(gateway): extract inject middleware` |\n| `test` | No release | `test(sdk): add hot reload tests` |\n| `perf` | No release | `perf(gateway): reduce allocation in inject` |\n\n### Scopes\n\n`sdk`, `gateway`, `cli`, `react`, `vue`, `svelte`, `codemod`, `spec`, `docs`\n\n## Code style\n\n### Go (Gateway)\n\n- **Standard library only.** No third-party dependencies.\n- Structured logging via `log/slog`\n- Error wrapping: `fmt.Errorf(\"context: %w\", err)`\n- No `init()` functions\n- Tests use stdlib only (`testing`, `net/http/httptest`)\n- Use `t.Setenv()` for env var tests (never `os.Setenv` directly)\n- Run with `-race` flag\n\n### TypeScript (SDK, CLI, Adapters)\n\n- Zero runtime dependencies for the SDK\n- Vitest + jsdom for testing\n- `vi.resetModules()` before each SDK test (because `_init()` runs on module load)\n- DOM cleanup in `beforeEach`\n\n## Testing\n\n```bash\n# All TypeScript packages\npnpm run test\n\n# Gateway (from gateway/)\ngo test -race ./...\n\n# Specific package\npnpm --filter @rep-protocol/sdk run test\n```\n\n## Release process\n\nReleases are automated via [release-please](https://github.com/googleapis/release-please):\n\n1. Push conventional commits to `main`\n2. Release-please creates/updates a Release PR with version bumps and changelogs\n3. Merging the Release PR triggers npm publishing for all packages\n4. The gateway is versioned independently via `gateway/VERSION` and released through GoReleaser\n\n\u003CAside type=\"caution\">\n Do not manually bump versions in `package.json` or create release tags. The automation handles this.\n\u003C/Aside>\n\n## PR guidelines\n\n- Branch from `main`\n- Keep PRs focused on a single change\n- Include tests for new functionality\n- Use squash-merge with a conventional commit message","src/content/docs/contributing.mdx","bdae584b684babbb","concepts/how-it-works",{"id":25,"data":27,"body":33,"filePath":34,"digest":35,"deferredRender":16},{"title":28,"description":29,"editUrl":16,"head":30,"template":18,"sidebar":31,"pagefind":16,"draft":20},"How REP Works","Architecture overview — gateway modes, startup sequence, and HTML injection.",[],{"hidden":20,"attrs":32},{},"import { Aside } from '@astrojs/starlight/components';\n\n## Architecture\n\nREP introduces a lightweight gateway process between the browser and your static file server. The gateway reads `REP_*` environment variables at startup, classifies them, and injects a `\u003Cscript>` tag into every HTML response.\n\n```\nContainer boot:\n 1. Gateway reads all REP_* environment variables (+ optional .env file)\n 2. Classifies into PUBLIC / SENSITIVE / SERVER tiers (by prefix)\n 3. Runs guardrails (entropy scan, known format detection) on PUBLIC vars\n 4. Generates ephemeral AES-256 key + HMAC secret (in-memory only)\n 5. Encrypts SENSITIVE vars → base64 blob\n 6. Computes HMAC integrity token\n 7. Pre-renders \u003Cscript id=\"__rep__\" type=\"application/json\"> tag\n```\n\n## Gateway modes\n\n### Proxy mode (recommended)\n\nThe gateway sits in front of an existing web server (nginx, Caddy, etc.) and intercepts HTML responses:\n\n```\nBrowser → [REP Gateway :8080] → [nginx / Caddy :80]\n```\n\nFor `text/html` responses, the gateway injects the payload before `\u003C/head>`. All other responses pass through unmodified.\n\n### Embedded mode\n\nThe gateway serves static files directly — no upstream server needed:\n\n```\nBrowser → [REP Gateway :8080] (serves files from --static-dir)\n```\n\nThis enables `FROM scratch` Docker containers: just the gateway binary and your `dist/` folder. No nginx, no Node.js, no shell.\n\n## Startup sequence\n\nThe gateway performs these steps in order at process start:\n\n1. Load `.env` file if `--env-file` is specified (existing env vars take precedence)\n2. Read all `REP_*` environment variables\n3. Classify each into PUBLIC, SENSITIVE, or SERVER tier\n4. Validate name uniqueness after prefix stripping\n5. Load and validate `.rep.yaml` manifest if `--manifest` is specified\n6. Run secret detection guardrails on PUBLIC variables\n7. Exit with error if `--strict` and guardrails triggered\n8. Generate ephemeral master key, derive AES-256 key via HKDF-SHA256\n9. Encrypt all SENSITIVE values with AES-256-GCM\n10. Compute HMAC-SHA256 integrity token\n11. Construct the payload JSON\n12. Register HTTP handlers (injection, session key, health, hot reload)\n13. Start accepting connections\n14. Log startup summary\n\n\u003CAside type=\"tip\">\n Ephemeral keys are regenerated on every restart. A gateway restart invalidates all previously issued session keys and re-encrypts the sensitive blob. This is by design — key compromise requires process compromise.\n\u003C/Aside>\n\n## HTML injection\n\nWhen the gateway intercepts an HTML response, it injects a `\u003Cscript>` block:\n\n```html\n\u003Cscript id=\"__rep__\" type=\"application/json\"\n data-rep-version=\"0.1.0\"\n data-rep-integrity=\"sha256-{base64_hash}\">\n{\n \"public\": {\n \"API_URL\": \"https://api.example.com\",\n \"FEATURE_FLAGS\": \"dark-mode,beta\"\n },\n \"sensitive\": \"{base64_aes_gcm_blob}\",\n \"_meta\": {\n \"version\": \"0.1.0\",\n \"injected_at\": \"2026-02-18T14:30:00.000Z\",\n \"integrity\": \"hmac-sha256:{base64_signature}\",\n \"key_endpoint\": \"/rep/session-key\",\n \"hot_reload\": \"/rep/changes\",\n \"ttl\": 0\n }\n}\n\u003C/script>\n```\n\n**Injection rules:**\n\n1. Insert before `\u003C/head>` (preferred)\n2. If no `\u003C/head>`, insert after `\u003Chead>`\n3. If neither exists, prepend to the response body\n\n\u003CAside type=\"caution\">\n `type=\"application/json\"` is critical — it prevents the browser from executing the tag. This is inert data, not executable JavaScript. Never change this to `text/javascript`.\n\u003C/Aside>\n\n## SDK initialization\n\nThe SDK reads the injected payload **synchronously** on import:\n\n1. Locate `\u003Cscript id=\"__rep__\">` in the DOM\n2. Parse the JSON content\n3. Verify `data-rep-integrity` against the content (async, non-blocking)\n4. Freeze the `public` object\n5. Set internal state flags (`_available`, `_tampered`)\n\nNo network calls happen during initialization. `rep.get()` is available immediately — before your first component renders.\n\n## Gateway endpoints\n\nThe gateway exposes three endpoints alongside HTML injection:\n\n| Endpoint | Purpose |\n|---|---|\n| `GET /rep/health` | Health check — variable counts, guardrail status, uptime |\n| `GET /rep/session-key` | Short-lived AES decryption key for SENSITIVE variables |\n| `GET /rep/changes` | SSE stream for hot reload (if enabled) |\n\nSee the [Gateway Endpoints reference](/reference/gateway-endpoints/) for full details.","src/content/docs/concepts/how-it-works.mdx","f91489b3baf50987","concepts/variable-classification",{"id":36,"data":38,"body":44,"filePath":45,"digest":46,"deferredRender":16},{"title":39,"description":40,"editUrl":16,"head":41,"template":18,"sidebar":42,"pagefind":16,"draft":20},"Variable Classification","The three-tier security model — PUBLIC, SENSITIVE, and SERVER variables.",[],{"hidden":20,"attrs":43},{},"import { Aside } from '@astrojs/starlight/components';\n\nREP classifies every environment variable into one of three security tiers based on its prefix. This is the foundational design decision — it forces an explicit security choice for every variable.\n\n## The three tiers\n\n| Prefix | Tier | Behaviour | SDK Access |\n|---|---|---|---|\n| `REP_PUBLIC_*` | **PUBLIC** | Plaintext JSON in page source | `rep.get('KEY')` (sync) |\n| `REP_SENSITIVE_*` | **SENSITIVE** | AES-256-GCM encrypted blob | `await rep.getSecure('KEY')` |\n| `REP_SERVER_*` | **SERVER** | Never sent to client | N/A |\n| `REP_GATEWAY_*` | *(config)* | Gateway configuration, not app vars | N/A |\n\nVariables without a `REP_` prefix are ignored by the gateway entirely. This prevents accidental exposure of system variables like `PATH`, `HOME`, or database credentials.\n\n## Classification rules\n\n1. Classification is determined **exclusively by prefix**. There is no override mechanism.\n2. The gateway will not inject any variable without a `REP_` prefix.\n3. Prefixes are stripped before injection: `REP_PUBLIC_API_URL` becomes `API_URL` in the payload.\n4. Names must be unique after stripping. If `REP_PUBLIC_API_URL` and `REP_SENSITIVE_API_URL` both exist, the gateway refuses to start.\n\n## Decision tree\n\nUse this guide to classify each variable:\n\n```\nDoes the value contain credentials, tokens, or keys?\n├── Yes → Does it need to reach the browser at all?\n│ ├── No → REP_SERVER_*\n│ └── Yes → REP_SENSITIVE_*\n└── No → Is it configuration the app needs at runtime?\n ├── Yes → REP_PUBLIC_*\n └── No → REP_SERVER_* or don't use REP_ prefix\n```\n\n## Common misclassifications\n\n| Variable | Wrong Tier | Correct Tier | Reason |\n|---|---|---|---|\n| `DATABASE_URL` | PUBLIC | **SERVER** | Database credentials must never reach the browser |\n| `STRIPE_SECRET_KEY` | SENSITIVE | **SERVER** | Secret keys should never be decryptable client-side |\n| `STRIPE_PUBLISHABLE_KEY` | SERVER | **PUBLIC** | Publishable keys are designed to be public |\n| `API_URL` | SENSITIVE | **PUBLIC** | API endpoints are visible in network requests anyway |\n| `JWT_SECRET` | SENSITIVE | **SERVER** | Signing secrets must stay server-side |\n| `OAUTH_CLIENT_ID` | SERVER | **SENSITIVE** | Client IDs are needed browser-side but not public |\n| `ANALYTICS_WRITE_KEY` | PUBLIC | **SENSITIVE** | Write keys allow data ingestion — encrypt them |\n| `FEATURE_FLAGS` | SENSITIVE | **PUBLIC** | Feature flag names have no security value |\n| `SENTRY_DSN` | PUBLIC | **SENSITIVE** | DSNs contain project-specific ingestion endpoints |\n| `APP_VERSION` | SENSITIVE | **PUBLIC** | Version strings are informational, not secret |\n| `INTERNAL_SERVICE_TOKEN` | SENSITIVE | **SERVER** | Service-to-service tokens must not reach the browser |\n| `CDN_BASE_URL` | SENSITIVE | **PUBLIC** | CDN URLs are visible in every asset request |\n\n\u003CAside type=\"tip\">\n When in doubt, start with the most restrictive tier (SERVER) and relax only when you can articulate why the browser needs the value.\n\u003C/Aside>\n\n## Automatic secret detection (guardrails)\n\nAt startup, the gateway scans all `REP_PUBLIC_*` values for patterns indicating potential misclassification:\n\n| Detection | Description |\n|---|---|\n| **Shannon entropy > 4.5** | Random-looking strings typical of API keys and tokens |\n| **Known key formats** | AWS keys (`AKIA...`), JWTs (`eyJ...`), GitHub tokens (`ghp_...`), Stripe keys (`sk_live_...`), private keys (`-----BEGIN`) |\n| **Length anomalies** | Strings > 64 characters that may be encoded secrets |\n\nWhen a potential misclassification is detected:\n\n- The gateway logs a **WARNING** with the variable name (never the value)\n- In `--strict` mode, the gateway refuses to start\n- The gateway never silently changes classification — you must fix the prefix\n\n\u003CAside type=\"caution\">\n Guardrails use heuristics, not certainty. A low-entropy secret (like a short password) may not trigger detection. Use `--strict` mode in production and review your `.rep.yaml` manifest in code review.\n\u003C/Aside>\n\n## Manifest validation\n\nWhen a `.rep.yaml` manifest is present, the gateway can validate at startup that:\n\n- All required variables are present in the environment\n- Variable values match declared types (url, number, enum, etc.)\n- Variables are in the correct tier\n\nSee the [Manifest guide](/guides/manifest/) for details.","src/content/docs/concepts/variable-classification.mdx","f2021196e99b810e","quick-start",{"id":47,"data":49,"body":55,"filePath":56,"digest":57,"deferredRender":16},{"title":50,"description":51,"editUrl":16,"head":52,"template":18,"sidebar":53,"pagefind":16,"draft":20},"Quick Start","Get REP running in under 5 minutes — no manifest file, no configuration step.",[],{"hidden":20,"attrs":54},{},"import { Steps, Tabs, TabItem, Aside } from '@astrojs/starlight/components';\n\nThe `.rep.yaml` manifest is entirely optional. The gateway works with just environment variables — the naming convention **is** the configuration.\n\n\u003CSteps>\n\n1. **Rename your environment variables**\n\n Add the `REP_PUBLIC_`, `REP_SENSITIVE_`, or `REP_SERVER_` prefix to classify each variable:\n\n ```bash\n # Before (Vite) → After (REP)\n VITE_API_URL → REP_PUBLIC_API_URL\n VITE_FEATURE_FLAGS → REP_PUBLIC_FEATURE_FLAGS\n\n # Before (CRA) → After (REP)\n REACT_APP_API_URL → REP_PUBLIC_API_URL\n\n # Should be encrypted in the browser\n REACT_APP_ANALYTICS_KEY → REP_SENSITIVE_ANALYTICS_KEY\n\n # Should never reach the browser\n DB_PASSWORD → REP_SERVER_DB_PASSWORD\n ```\n\n2. **Install the SDK and update your code**\n\n ```bash\n npm install @rep-protocol/sdk\n ```\n\n Replace your `import.meta.env.*` / `process.env.*` reads:\n\n ```typescript\n import { rep } from '@rep-protocol/sdk';\n\n // Was: import.meta.env.VITE_API_URL\n const apiUrl = rep.get('API_URL');\n\n // With a default value for local development\n const apiUrl = rep.get('API_URL', 'http://localhost:3001');\n\n // Sensitive variable — encrypted, decrypted on demand\n const key = await rep.getSecure('ANALYTICS_KEY');\n ```\n\n `rep.get()` is **synchronous** — the SDK reads the payload from the DOM on import, before your first component renders. No loading state needed.\n\n3. **Build your app (nothing changes)**\n\n ```bash\n npm run build\n ```\n\n The output is now environment-agnostic. The same `dist/` folder goes to every environment.\n\n4. **Run the gateway**\n\n \u003CTabs>\n \u003CTabItem label=\"Binary\">\n ```bash\n REP_PUBLIC_API_URL=https://api.example.com \\\n REP_PUBLIC_FEATURE_FLAGS=dark-mode,new-checkout \\\n REP_SENSITIVE_ANALYTICS_KEY=ak_live_abc123 \\\n ./rep-gateway --mode embedded --static-dir ./dist\n ```\n \u003C/TabItem>\n \u003CTabItem label=\"Docker\">\n ```bash\n docker run --rm -p 8080:8080 \\\n -e REP_PUBLIC_API_URL=https://api.example.com \\\n -e REP_PUBLIC_FEATURE_FLAGS=dark-mode,new-checkout \\\n -e REP_SENSITIVE_ANALYTICS_KEY=ak_live_abc123 \\\n -v \"$(pwd)/dist:/static:ro\" \\\n ghcr.io/ruachtech/rep/gateway:latest \\\n --mode embedded --static-dir /static\n ```\n \u003C/TabItem>\n \u003C/Tabs>\n\n Open `http://localhost:8080` — the gateway injected your variables into every HTML response.\n\n\u003C/Steps>\n\n## Changing config without rebuilding\n\nStop the gateway. Restart with different values. Same `dist/` folder, different runtime config:\n\n```bash\nREP_PUBLIC_API_URL=https://api.prod.example.com \\\nREP_PUBLIC_FEATURE_FLAGS=dark-mode \\\nREP_SENSITIVE_ANALYTICS_KEY=ak_live_prod_xyz \\\n./rep-gateway --mode embedded --static-dir ./dist\n```\n\nNo rebuild. No new container image. This is the core proposition.\n\n## Proxy mode\n\nIf you already have nginx, Caddy, or another static file server, run the gateway in front of it instead:\n\n```bash\nREP_PUBLIC_API_URL=https://api.example.com \\\n./rep-gateway --mode proxy --upstream localhost:80\n```\n\nThe gateway intercepts `text/html` responses, injects the `\u003Cscript>` tag, and passes everything else through unmodified.\n\n## What's next?\n\n- [Add a manifest file](/guides/manifest/) for startup validation and TypeScript type generation\n- [Framework-specific guides](/frameworks/react/) for React, Vue, and Svelte adapters\n- [Deploy with Docker](/deployment/docker-embedded/) for production containers\n- [Variable classification](/concepts/variable-classification/) to understand the three-tier security model","src/content/docs/quick-start.mdx","9ef19fc715dfa8e5","index",{"id":58,"data":60,"body":82,"filePath":83,"digest":84,"deferredRender":16},{"title":61,"description":62,"editUrl":16,"head":63,"template":64,"hero":65,"sidebar":80,"pagefind":16,"draft":20},"REP — Runtime Environment Protocol","Build once. Deploy anywhere. Securely. The missing security layer for environment variables in browser applications.",[],"splash",{"tagline":66,"actions":67},"The missing security layer for environment variables in browser applications. Build once, deploy anywhere — with encryption, integrity verification, and secret detection built in.",[68,74],{"text":50,"link":69,"variant":70,"icon":71},"/quick-start/","primary",{"type":72,"name":73},"icon","right-arrow",{"text":75,"link":76,"variant":77,"icon":78},"View on GitHub","https://github.com/ruachtech/rep","minimal",{"type":72,"name":79},"external",{"hidden":20,"attrs":81},{},"import { Card, CardGrid, Tabs, TabItem } from '@astrojs/starlight/components';\n\n\u003Cdiv style=\"max-width: 720px; margin: 0 auto 2rem;\">\n \u003Cvideo controls playsinline preload=\"metadata\" style=\"width: 100%; border-radius: 8px; border: 1px solid var(--sl-color-gray-5);\">\n \u003Csource src=\"https://github.com/RuachTech/rep/releases/download/v0.1.3/rep-gateway-demo.mp4\" type=\"video/mp4\" />\n \u003C/video>\n \u003Cp style=\"text-align: center; font-size: 0.85rem; color: var(--sl-color-gray-3); margin-top: 0.5rem;\">Same frontend image, different environment, dynamic variables — no rebuild, no redeploy.\u003C/p>\n\u003C/div>\n\n## The Problem\n\nEvery frontend framework resolves environment variables at **build time** — `process.env.API_URL` becomes a hardcoded string in your JavaScript bundle. This creates problems that compound in production:\n\n\u003CCardGrid>\n \u003CCard title=\"One build per environment\" icon=\"warning\">\n Your staging bundle can't be promoted to production. You rebuild for every environment, breaking the container promise of \"build once, run anywhere.\"\n \u003C/Card>\n \u003CCard title=\"No security model\" icon=\"error\">\n All variables are treated equally. API keys, analytics tokens, and public URLs all end up as plaintext strings in your bundle — visible to anyone who opens View Source.\n \u003C/Card>\n \u003CCard title=\"Config changes require redeployment\" icon=\"close\">\n Need to rotate an API key or flip a feature flag? Rebuild, re-test, redeploy. Even if your backend can hot-swap config, your frontend can't.\n \u003C/Card>\n \u003CCard title=\"Secrets leak into build logs\" icon=\"error\">\n CI/CD pipelines pass secrets as build args. They appear in Docker layer history, build logs, and cached artifacts — creating supply chain risk.\n \u003C/Card>\n\u003C/CardGrid>\n\n## What REP Does\n\nREP is an open protocol and reference implementation that **decouples environment variables from the build process entirely**. A lightweight gateway reads variables at startup, classifies them by security tier, encrypts sensitive values, and injects them into HTML responses — whether you're running containers, static builds, or local development.\n\n\u003CCardGrid>\n \u003CCard title=\"Three Security Tiers\" icon=\"approve-check\">\n **PUBLIC** — plaintext, synchronous access. **SENSITIVE** — AES-256-GCM encrypted, decrypted on demand. **SERVER** — never sent to the browser. Classification by naming convention eliminates ambiguity.\n \u003C/Card>\n \u003CCard title=\"Encryption + Integrity\" icon=\"lock\">\n Sensitive variables are encrypted with ephemeral keys generated at startup. Every payload carries an HMAC-SHA256 integrity token and SRI hash to detect tampering in transit.\n \u003C/Card>\n \u003CCard title=\"Secret Detection Guardrails\" icon=\"shield\">\n Entropy analysis and known-format matching (AWS keys, JWTs, Stripe keys, GitHub tokens) catch misclassified secrets before they reach the browser. Strict mode makes warnings into hard failures.\n \u003C/Card>\n \u003CCard title=\"Hot Reload via SSE\" icon=\"refresh\">\n Config changes push to every connected browser via Server-Sent Events. No page reload, no redeployment. Edit an env file or rotate a ConfigMap — the UI updates live.\n \u003C/Card>\n\u003C/CardGrid>\n\n## Works Everywhere\n\nREP operates at the **infrastructure layer** — no build-tool plugins, no framework coupling. It works with any frontend stack that produces HTML.\n\n\u003CCardGrid>\n \u003CCard title=\"Containers\" icon=\"rocket\">\n Reverse proxy mode sits in front of nginx, caddy, or any upstream. Embedded mode serves static files directly from a `FROM scratch` image.\n \u003C/Card>\n \u003CCard title=\"Static Builds\" icon=\"document\">\n Build your app once with `npm run build`. The gateway injects config into the static HTML at serve time — same artifact for every environment.\n \u003C/Card>\n \u003CCard title=\"Local Development\" icon=\"terminal\">\n The CLI wraps the gateway for local dev. Proxy your Vite/webpack dev server with hot reload, or serve a production build with live config changes.\n \u003C/Card>\n \u003CCard title=\"Any Framework\" icon=\"puzzle\">\n First-party adapters for React, Vue, and Svelte. A zero-dependency TypeScript SDK works with anything — Angular, vanilla JS, or your custom setup.\n \u003C/Card>\n\u003C/CardGrid>\n\n## Compared to Existing Solutions\n\n| Approach | Security Tiers | Encrypted Vars | Integrity Check | Hot Reload | Standalone Binary |\n|---|:---:|:---:|:---:|:---:|:---:|\n| `envsubst` / `sed` on bundles | -- | -- | -- | -- | -- |\n| Fetch `/config.json` at runtime | -- | -- | -- | -- | -- |\n| `window.__ENV__` via shell script | -- | -- | -- | -- | -- |\n| Build-tool plugins (dotenv, etc.) | -- | -- | -- | -- | -- |\n| **REP** | **3-tier** | **AES-256-GCM** | **HMAC + SRI** | **SSE** | **~6MB Go** |\n\n## Quick Example\n\n\u003CTabs>\n \u003CTabItem label=\"SDK Usage\">\n```typescript\nimport { rep } from '@rep-protocol/sdk';\n\n// Synchronous — no loading state needed\nconst apiUrl = rep.get('API_URL');\nconst flags = rep.get('FEATURE_FLAGS');\n\n// Encrypted — decrypted on demand via session key\nconst key = await rep.getSecure('ANALYTICS_KEY');\n\n// Hot reload — react to config changes live\nrep.onChange('FEATURE_FLAGS', (newValue) => {\n console.log('Flags updated:', newValue);\n});\n```\n \u003C/TabItem>\n \u003CTabItem label=\"Docker Compose\">\n```yaml\n# Same image, different config — true build-once, deploy-anywhere\nservices:\n frontend-staging:\n image: myapp:latest\n environment:\n REP_PUBLIC_API_URL: \"https://api.staging.example.com\"\n REP_SENSITIVE_ANALYTICS_KEY: \"UA-XXXXX-staging\"\n REP_SERVER_INTERNAL_SECRET: \"never-reaches-browser\"\n\n frontend-prod:\n image: myapp:latest # SAME IMAGE\n environment:\n REP_PUBLIC_API_URL: \"https://api.example.com\"\n REP_SENSITIVE_ANALYTICS_KEY: \"UA-XXXXX-prod\"\n REP_SERVER_INTERNAL_SECRET: \"also-never-reaches-browser\"\n```\n \u003C/TabItem>\n \u003CTabItem label=\"Variable Tiers\">\n```bash\n# PUBLIC — plaintext in page source, rep.get()\nREP_PUBLIC_API_URL=https://api.example.com\n\n# SENSITIVE — AES-256-GCM encrypted, await rep.getSecure()\nREP_SENSITIVE_ANALYTICS_KEY=UA-12345-1\n\n# SERVER — never leaves the gateway process\nREP_SERVER_DB_PASSWORD=never-reaches-browser\n```\n \u003C/TabItem>\n\u003C/Tabs>\n\n## Project Components\n\n\u003CCardGrid>\n \u003CCard title=\"Gateway\" icon=\"rocket\">\n Go binary (~6MB). Zero dependencies. `FROM scratch` compatible. Proxy or embedded mode.\n \u003C/Card>\n \u003CCard title=\"SDK\" icon=\"document\">\n TypeScript. Zero runtime deps. ~1.5KB gzipped. Synchronous `get()`, async `getSecure()`.\n \u003C/Card>\n \u003CCard title=\"CLI\" icon=\"terminal\">\n `rep validate`, `rep typegen`, `rep lint`, `rep dev`. Full development workflow.\n \u003C/Card>\n \u003CCard title=\"Adapters\" icon=\"puzzle\">\n First-party React, Vue, and Svelte adapters with hot-reload-aware hooks and stores.\n \u003C/Card>\n\u003C/CardGrid>\n\n## Specification Status\n\n| Document | Status | Version |\n|---|---|---|\n| [REP-RFC-0001](/spec/rfc-0001/) | Active | 0.1.0 |\n| [Security Model](/spec/security-model/) | Active | 0.1.0 |\n| [Conformance](/spec/conformance/) | Active | 0.1.0 |\n\nSpecification documents are licensed under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/). Code is licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0).","src/content/docs/index.mdx","df8031851dc4eec7","concepts/security-model",{"id":85,"data":87,"body":93,"filePath":94,"digest":95,"deferredRender":16},{"title":88,"description":89,"editUrl":16,"head":90,"template":18,"sidebar":91,"pagefind":16,"draft":20},"Security Model","Threat analysis, trust boundaries, and what REP protects against (and what it doesn't).",[],{"hidden":20,"attrs":92},{},"import { Aside } from '@astrojs/starlight/components';\n\nREP does not claim to make browser-side configuration \"secure\" in an absolute sense. It makes it **significantly more secure than the status quo** while making security trade-offs explicit and auditable.\n\n## Fundamental axiom\n\n> **Anything that reaches the browser is ultimately accessible to the user and to any code running in the browser context.**\n\nREP cannot change this axiom. What it does is:\n\n1. **Prevent accidental exposure** through classification and guardrails\n2. **Raise the bar for casual extraction** through encryption of sensitive values\n3. **Make intentional access auditable** through session key logging and rate limiting\n4. **Eliminate unnecessary exposure** through the SERVER tier\n5. **Detect tampering** through integrity verification\n\n## Trust boundaries\n\n```\n┌────────────────────────────────────────────────────────────────┐\n│ TRUSTED ZONE │\n│ │\n│ Orchestrator (K8s, ECS) │\n│ ↓ │\n│ REP Gateway (Go binary) → Static File Server (nginx) │\n│ │\n│ REP_SERVER_* vars NEVER cross this boundary │\n├────────────────────────────────────────────────────────────────┤\n│ TRANSIT (HTTPS/TLS) │\n├────────────────────────────────────────────────────────────────┤\n│ UNTRUSTED ZONE │\n│ │\n│ Browser: Application Code, REP SDK, Extensions, DevTools │\n│ Everything here is visible to the user │\n└────────────────────────────────────────────────────────────────┘\n```\n\n## Threat analysis\n\n### T1: Accidental secret exposure (HIGH)\n\nA developer prefixes a database password with `REP_PUBLIC_` instead of `REP_SERVER_`.\n\n**Mitigations:**\n- Naming convention forces an explicit classification decision\n- Guardrail scanning detects secret-like patterns in PUBLIC values\n- `--strict` mode makes guardrail warnings into hard failures\n- Manifest validation confirms variables match their declared tier\n\n**Residual risk:** Low-entropy secrets may not trigger heuristic detection.\n\n### T2: XSS exfiltration of public variables (MEDIUM)\n\nAn attacker achieves XSS and reads public config values.\n\n**Mitigations:** Largely out of scope — PUBLIC variables are by definition visible to browser code. REP helps indirectly by forcing classification (so truly sensitive values aren't in PUBLIC) and providing the SERVER tier for values that don't belong in the browser at all.\n\n### T3: XSS exfiltration of sensitive variables (MEDIUM-HIGH)\n\nAn attacker achieves XSS and attempts to read encrypted SENSITIVE values.\n\n**Mitigations:**\n- Values are AES-256-GCM encrypted at rest in the HTML\n- Decryption requires fetching a session key from `/rep/session-key`\n- Session keys are single-use (prevents replay)\n- Session keys expire in 30 seconds\n- Endpoint is rate-limited (10 req/min per IP)\n- CORS validates the requesting origin\n- All key issuances are audit-logged\n\n**Residual risk:** A sophisticated same-origin XSS attack could fetch a session key and decrypt values. REP raises the bar from \"read the DOM\" to \"make an authenticated, rate-limited, logged API call.\"\n\n### T4: MITM payload tampering (HIGH)\n\nAn attacker modifies the injected `\u003Cscript>` tag in transit.\n\n**Mitigations:**\n- HMAC-SHA256 integrity token computed over the canonical payload\n- SRI hash on the `data-rep-integrity` attribute\n- SDK sets `_tampered` flag if integrity check fails\n- `verify()` function exposes tamper state to the application\n\n**Limitation:** If the attacker can rewrite the entire script block (including the integrity attribute), verification cannot detect this. HTTPS is the primary defense against MITM.\n\n### T5: Environment variable leakage via gateway (CRITICAL)\n\nThe gateway process itself is compromised, leaking SERVER-tier variables.\n\n**Mitigations:**\n- Strict prefix filtering — only `REP_*` variables are processed\n- No shell execution within the gateway\n- No filesystem writes\n- Minimal dependencies (zero external Go deps)\n- Compatible with read-only filesystems\n- Static binary, `FROM scratch` compatible\n- Non-root user execution (UID 65534)\n\n### T6: DoS via session key endpoint (LOW)\n\nAn attacker floods `/rep/session-key` to exhaust resources.\n\n**Mitigations:** Rate limiting (10 req/min/IP), minimal computation per request, automatic key expiry cleanup, separate health port for monitoring.\n\n### T7: Supply chain attack on SDK (HIGH)\n\nThe SDK package is compromised to exfiltrate variables.\n\n**Mitigations:** Minimal surface (<2KB, ~150 lines), zero runtime dependencies, lockfile pinning, npm provenance, self-hostable (vendor the file).\n\n## Hardening recommendations\n\n### Production gateway configuration\n\n```bash\nREP_GATEWAY_STRICT=true # Fail on guardrail warnings\nREP_GATEWAY_ALLOWED_ORIGINS=https://app.example.com\nREP_GATEWAY_LOG_FORMAT=json # Structured logging for SIEM\n```\n\n### Minimal Docker image\n\n```dockerfile\nFROM scratch\nCOPY rep-gateway /rep-gateway\nCOPY dist/ /static/\nUSER 65534:65534\nENTRYPOINT [\"/rep-gateway\"]\nCMD [\"--mode\", \"embedded\", \"--static-dir\", \"/static\", \"--strict\"]\n```\n\n### Content Security Policy\n\n```\nContent-Security-Policy:\n default-src 'self';\n script-src 'self';\n connect-src 'self';\n style-src 'self' 'unsafe-inline';\n```\n\nThe `\u003Cscript id=\"__rep__\" type=\"application/json\">` tag is inert data — it does not execute. No `script-src` exception or nonce is needed for the REP payload.\n\n### Monitoring\n\n| Log Event | Level | Alert On |\n|---|---|---|\n| `rep.guardrail.warning` | WARN | Any occurrence in production |\n| `rep.session_key.issued` | INFO | Rate exceeding baseline |\n| `rep.session_key.rejected` | WARN | Any occurrence |\n| `rep.session_key.rate_limited` | WARN | Sustained bursts |\n| `rep.config.changed` | INFO | Unexpected changes |\n| `rep.inject.html` | DEBUG | N/A |\n\n## Known limitations\n\n1. **No client-side HMAC verification.** The HMAC secret never leaves the gateway. The SDK verifies via SRI hash only.\n2. **Sensitive tier is defense-in-depth, not absolute.** A determined attacker with XSS can eventually decrypt sensitive values.\n3. **No key rotation without restart.** Ephemeral keys are generated once at startup.\n4. **Guardrails are heuristic.** They catch common patterns but cannot detect all secrets.\n5. **Hot reload has an eventual consistency window.** Between config change and SSE delivery, clients see stale values.\n\nFor the full formal analysis, see the [Security Model specification](/spec/security-model/).","src/content/docs/concepts/security-model.mdx","2f14d5039615f826","deployment/ci-cd",{"id":96,"data":98,"body":104,"filePath":105,"digest":106,"deferredRender":16},{"title":99,"description":100,"editUrl":16,"head":101,"template":18,"sidebar":102,"pagefind":16,"draft":20},"CI/CD Pipeline","Build once, deploy everywhere — same image across staging and production.",[],{"hidden":20,"attrs":103},{},"import { Aside } from '@astrojs/starlight/components';\n\n## The fundamental shift\n\nWith REP, your CI/CD pipeline changes from \"build per environment\" to \"build once, promote everywhere\":\n\n**Before REP:**\n```\nBuild (staging) → Test → Deploy to staging\nBuild (prod) → Deploy to prod ← DIFFERENT BINARY\n```\n\n**After REP:**\n```\nBuild (once) → Test → Deploy to staging (with staging env vars)\n → Promote SAME IMAGE to prod (with prod env vars)\n```\n\nThe image that passed your tests is the **exact same binary** that goes to production.\n\n## GitHub Actions example\n\n```yaml\nname: Build and Deploy\n\non:\n push:\n branches: [main]\n\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n\n - name: Build frontend (environment-agnostic)\n run: |\n docker build -t myapp:${{ github.sha }} .\n # No --build-arg for API_URL, no .env files\n # The image is environment-agnostic\n\n - name: Push to registry\n run: docker push ghcr.io/myorg/myapp:${{ github.sha }}\n\n test:\n needs: build\n runs-on: ubuntu-latest\n steps:\n - name: Run E2E tests\n run: |\n docker run -d --name test-app \\\n -e REP_PUBLIC_API_URL=https://api.test.example.com \\\n -e REP_PUBLIC_FEATURE_FLAGS=all \\\n -p 8080:8080 \\\n ghcr.io/myorg/myapp:${{ github.sha }}\n\n npx playwright test --base-url http://localhost:8080\n\n deploy-staging:\n needs: test\n runs-on: ubuntu-latest\n steps:\n - name: Deploy to staging\n run: |\n kubectl set image deployment/frontend \\\n frontend=ghcr.io/myorg/myapp:${{ github.sha }}\n # ConfigMap provides staging REP_PUBLIC_* and REP_SENSITIVE_* vars\n\n deploy-prod:\n needs: deploy-staging\n runs-on: ubuntu-latest\n environment: production # Requires manual approval\n steps:\n - name: Promote SAME IMAGE to production\n run: |\n # SAME SHA — exact same binary that was tested\n kubectl set image deployment/frontend \\\n frontend=ghcr.io/myorg/myapp:${{ github.sha }}\n # Different ConfigMap provides prod REP_* vars\n```\n\n## Manifest validation in CI\n\nAdd a validation step to catch configuration errors early:\n\n```yaml\n validate:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - name: Validate REP manifest\n run: npx @rep-protocol/cli validate --manifest .rep.yaml\n```\n\nThis checks that:\n- The manifest schema is valid\n- No naming collisions after prefix stripping\n- All type constraints are properly declared\n\n## Bundle scanning in CI\n\nScan built bundles for accidentally leaked secrets:\n\n```yaml\n lint:\n needs: build\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n - name: Build\n run: npm ci && npm run build\n - name: Scan for secrets\n run: npx @rep-protocol/cli lint --dir ./dist --strict\n```\n\nMinified code patterns are automatically filtered to avoid false positives, while real secrets in bundles are still detected. Use `--exclude` to skip specific files:\n\n```yaml\n - name: Scan for secrets\n run: npx @rep-protocol/cli lint --dir ./dist --strict --exclude \"vendor/**\"\n```\n\n\u003CAside type=\"tip\">\n Combine `rep validate` and `rep lint` as required CI checks. Validation catches schema issues at commit time; lint catches leaked secrets at build time.\n\u003C/Aside>","src/content/docs/deployment/ci-cd.mdx","bb8455015892e11f","concepts/hot-reload",{"id":107,"data":109,"body":115,"filePath":116,"digest":117,"deferredRender":16},{"title":110,"description":111,"editUrl":16,"head":112,"template":18,"sidebar":113,"pagefind":16,"draft":20},"Hot Reload","Live config updates via Server-Sent Events — no page reload, no redeployment.",[],{"hidden":20,"attrs":114},{},"import { Aside } from '@astrojs/starlight/components';\n\nHot reload is an optional feature that pushes configuration changes to the browser via Server-Sent Events (SSE). When enabled, the gateway monitors for environment variable changes and broadcasts updates to connected clients.\n\n## Enabling hot reload\n\n```bash\nrep-gateway --hot-reload --mode embedded --static-dir ./dist\n```\n\nOr via environment variable:\n\n```bash\nREP_GATEWAY_HOT_RELOAD=true\n```\n\n## SSE event format\n\nThe gateway exposes `GET /rep/changes` as an SSE endpoint:\n\n```\nevent: rep:config:update\ndata: {\"key\": \"FEATURE_FLAGS\", \"tier\": \"public\", \"value\": \"dark-mode,ai-assist\"}\nid: 1708267830000\n\nevent: rep:config:delete\ndata: {\"key\": \"DEPRECATED_FLAG\", \"tier\": \"public\"}\nid: 1708267831000\n```\n\n### Event types\n\n| Event | Description |\n|---|---|\n| `rep:config:update` | A variable's value changed or a new variable was added |\n| `rep:config:delete` | A variable was removed |\n\n## Change detection modes\n\nThe gateway supports three modes for detecting environment variable changes:\n\n### File watch (recommended for Kubernetes)\n\nWatches a mounted ConfigMap or secrets volume for file changes:\n\n```bash\nrep-gateway --hot-reload --hot-reload-mode file_watch\n```\n\nIdeal for Kubernetes deployments where ConfigMaps are mounted as volumes. Changes are detected within seconds of a ConfigMap update.\n\n### Signal mode\n\nRe-reads the environment on receipt of `SIGHUP`:\n\n```bash\n# In another terminal or from a process manager:\nkill -HUP $(pidof rep-gateway)\n```\n\nUseful for traditional deployments where an orchestrator can signal the gateway.\n\n### Poll mode\n\nPeriodically re-reads the config source:\n\n```bash\nrep-gateway --hot-reload --hot-reload-mode poll --hot-reload-poll-interval 30s\n```\n\nSimplest mode, but introduces a polling interval delay.\n\n## SDK integration\n\n### Lazy connection\n\nThe SDK does **not** establish an SSE connection on import. It connects lazily when `onChange()` or `onAnyChange()` is first called:\n\n```typescript\nimport { rep } from '@rep-protocol/sdk';\n\n// No SSE connection yet\n\nconst unsub = rep.onChange('FEATURE_FLAGS', (newValue, oldValue) => {\n console.log(`Flags changed: ${oldValue} → ${newValue}`);\n});\n// SSE connection established now\n\nunsub();\n// If no other listeners remain, SSE connection is closed\n```\n\nThis is a deliberate design choice — applications that don't use hot reload pay zero network cost.\n\n### Framework adapters\n\nAll framework adapters automatically subscribe to hot reload:\n\n- **React:** `useRep()` subscribes in `useEffect`, unsubscribes on unmount\n- **Vue:** `useRep()` subscribes in `setup()`, unsubscribes via `onUnmounted`\n- **Svelte:** `repStore()` subscribes when the store has subscribers, unsubscribes when the last subscriber leaves\n\n\u003CAside>\n `useRepSecure()`, `useRepSecure()` (Vue), and `repSecureStore()` do **not** subscribe to hot reload. Sensitive variables require re-fetching a session key, which is too expensive for automatic updates.\n\u003C/Aside>\n\n### Handling reconnection\n\nSSE has built-in reconnection. If the connection drops, the browser automatically reconnects after a brief delay. The `id` field in SSE events allows the gateway to replay missed events.\n\n## Kubernetes hot reload\n\nIn Kubernetes, combine ConfigMap volumes with file watch mode:\n\n```yaml\napiVersion: apps/v1\nkind: Deployment\nspec:\n template:\n spec:\n containers:\n - name: app\n image: myapp:latest\n args:\n - \"--hot-reload\"\n - \"--hot-reload-mode=file_watch\"\n volumeMounts:\n - name: config\n mountPath: /config\n volumes:\n - name: config\n configMap:\n name: app-config\n```\n\nWhen the ConfigMap is updated (`kubectl apply`), Kubernetes refreshes the mounted volume, the gateway detects the change, and connected browsers receive the update — all without a pod restart.\n\n\u003CAside type=\"caution\">\n Hot reload has an eventual consistency window. Between the config change and SSE delivery, clients see stale values. This window is typically sub-second for file watch mode but can be up to the poll interval for poll mode.\n\u003C/Aside>","src/content/docs/concepts/hot-reload.mdx","d5654cdd39f1b4e4","concepts/wire-format",{"id":118,"data":120,"body":126,"filePath":127,"digest":128,"deferredRender":16},{"title":121,"description":122,"editUrl":16,"head":123,"template":18,"sidebar":124,"pagefind":16,"draft":20},"Wire Format","Payload JSON structure, encrypted blob format, and integrity verification.",[],{"hidden":20,"attrs":125},{},"import { Aside } from '@astrojs/starlight/components';\n\n## Payload structure\n\nThe gateway injects a `\u003Cscript>` tag into HTML responses containing the REP payload as JSON:\n\n```html\n\u003Cscript id=\"__rep__\" type=\"application/json\"\n data-rep-version=\"0.1.0\"\n data-rep-integrity=\"sha256-{base64_hash}\">\n{\n \"public\": { ... },\n \"sensitive\": \"...\",\n \"_meta\": { ... }\n}\n\u003C/script>\n```\n\n### Fields\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `public` | `object` | Yes | Key-value map of PUBLIC tier variables (strings only) |\n| `sensitive` | `string` | No | Base64-encoded AES-256-GCM encrypted blob |\n| `_meta` | `object` | Yes | Payload metadata |\n\n### `_meta` fields\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `version` | `string` | Yes | Protocol version (semver) |\n| `injected_at` | `string` | Yes | RFC 3339 timestamp of injection |\n| `integrity` | `string` | Yes | `hmac-sha256:{base64_signature}` |\n| `key_endpoint` | `string` | No | Path to session key endpoint (`/rep/session-key`) |\n| `hot_reload` | `string` | No | Path to SSE endpoint (`/rep/changes`) |\n| `ttl` | `integer` | No | Cache TTL in seconds (0 = no cache) |\n\n### SRI attribute\n\nThe `data-rep-integrity` attribute contains a SHA-256 hash of the raw JSON content:\n\n```\ndata-rep-integrity=\"sha256-{base64_of_sha256_digest}\"\n```\n\nThe SDK verifies this using the Web Crypto API, comparing the hash against the actual `textContent` of the `\u003Cscript>` element (byte-for-byte matching the gateway's computation).\n\n## Encrypted blob format\n\nWhen SENSITIVE variables are present, they are encrypted into a single binary blob:\n\n```\n[12 bytes nonce][ciphertext][16 bytes GCM auth tag]\n```\n\n| Segment | Size | Description |\n|---|---|---|\n| Nonce | 12 bytes | Random IV for AES-256-GCM |\n| Ciphertext | Variable | Encrypted JSON of all sensitive key-value pairs |\n| Auth tag | 16 bytes | GCM authentication tag |\n\nThe entire blob is base64-encoded in the `sensitive` field.\n\n### Key derivation (HKDF-SHA256)\n\nThe encryption key is derived from an ephemeral master key using HKDF (RFC 5869):\n\n1. Gateway generates a 32-byte random master key at startup\n2. Extract: `PRK = HMAC-SHA256(salt=\"rep-v1\", IKM=master_key)`\n3. Expand: `derived_key = HKDF-Expand(PRK, info=\"rep-session-key\", L=32)`\n4. The derived key (not the master key) is issued via `/rep/session-key`\n5. Both master and derived keys exist only in memory — never stored to disk\n\n### Decryption (client-side)\n\nThe SDK decrypts sensitive variables in `getSecure()`:\n\n1. Fetch the session key from `/rep/session-key`\n2. Base64-decode the session key\n3. Base64-decode the `sensitive` blob\n4. Extract: first 12 bytes = nonce, last 16 bytes = auth tag, middle = ciphertext\n5. Decrypt with AES-256-GCM using `_meta.integrity` as Additional Authenticated Data (AAD)\n6. Parse the resulting JSON to get all sensitive key-value pairs\n7. Cache all decrypted values in memory for the page lifetime\n\n\u003CAside type=\"tip\">\n All sensitive variables are decrypted together on the first `getSecure()` call. Subsequent calls for different keys return from the in-memory cache without additional network requests.\n\u003C/Aside>\n\n## Integrity verification\n\n### HMAC-SHA256\n\nThe integrity token is computed over a canonicalized representation of the payload:\n\n1. Construct a JSON object with sorted keys, no whitespace\n2. Include both `public` and `sensitive` fields\n3. Compute: `HMAC-SHA256(secret, canonical_json)`\n4. Encode as: `hmac-sha256:{base64_signature}`\n\nThe HMAC secret exists only in the gateway's memory and is never transmitted. The SDK cannot verify the HMAC — this is by design. The HMAC enables server-side verification by other infrastructure components.\n\n### SRI verification (client-side)\n\nThe SDK verifies payload integrity using the `data-rep-integrity` attribute:\n\n1. Read the raw `textContent` of the `\u003Cscript>` element\n2. Compute SHA-256 using the Web Crypto API\n3. Compare with the `data-rep-integrity` attribute value\n4. Set `_tampered` flag if mismatch\n\nThis detects modifications to the payload content after injection (e.g., by a browser extension or CDN).\n\n## JSON schemas\n\nThe payload and manifest schemas are available as JSON Schema (Draft 2020-12):\n\n- [Payload schema](/schema/rep-payload.schema.json)\n- [Manifest schema](/schema/rep-manifest.schema.json)","src/content/docs/concepts/wire-format.mdx","b39643b664dea4e3","deployment/docker-compose",{"id":129,"data":131,"body":137,"filePath":138,"digest":139,"deferredRender":16},{"title":132,"description":133,"editUrl":16,"head":134,"template":18,"sidebar":135,"pagefind":16,"draft":20},"Docker Compose","Local multi-service setup with Docker Compose — same image, different config.",[],{"hidden":20,"attrs":136},{},"## Basic setup\n\n```yaml\n# docker-compose.yml\nservices:\n frontend:\n build: .\n ports:\n - \"8080:8080\"\n environment:\n REP_PUBLIC_API_URL: \"http://localhost:3000\"\n REP_PUBLIC_FEATURE_FLAGS: \"dark-mode,debug\"\n REP_SENSITIVE_ANALYTICS_KEY: \"test-key\"\n```\n\n## Same image, multiple environments\n\nThe core value proposition — one image, different config per environment:\n\n```yaml\nservices:\n frontend-staging:\n image: myapp:latest\n ports:\n - \"8080:8080\"\n environment:\n REP_PUBLIC_API_URL: \"https://api.staging.example.com\"\n REP_PUBLIC_FEATURE_FLAGS: \"dark-mode,beta-checkout\"\n REP_PUBLIC_ENV_NAME: \"staging\"\n REP_SENSITIVE_ANALYTICS_KEY: \"UA-XXXXX-staging\"\n REP_SERVER_INTERNAL_SECRET: \"staging-secret\"\n\n frontend-prod:\n image: myapp:latest # SAME IMAGE\n ports:\n - \"8081:8080\"\n environment:\n REP_PUBLIC_API_URL: \"https://api.example.com\"\n REP_PUBLIC_FEATURE_FLAGS: \"dark-mode\"\n REP_PUBLIC_ENV_NAME: \"production\"\n REP_SENSITIVE_ANALYTICS_KEY: \"UA-XXXXX-prod\"\n REP_SERVER_INTERNAL_SECRET: \"prod-secret\"\n REP_GATEWAY_STRICT: \"true\"\n```\n\n## With .env files\n\n```yaml\nservices:\n frontend:\n build: .\n ports:\n - \"8080:8080\"\n env_file:\n - .env.local\n```\n\n`.env.local`:\n```bash\nREP_PUBLIC_API_URL=http://localhost:3000\nREP_PUBLIC_FEATURE_FLAGS=dark-mode,debug\nREP_SENSITIVE_ANALYTICS_KEY=test-key-123\n```\n\n## Development with proxy mode\n\nRun the gateway as a proxy to your Vite dev server:\n\n```yaml\nservices:\n vite:\n build:\n context: .\n target: dev\n command: npm run dev -- --host\n ports:\n - \"5173:5173\"\n volumes:\n - .:/app\n - /app/node_modules\n\n gateway:\n image: ghcr.io/ruachtech/rep/gateway:latest\n ports:\n - \"8080:8080\"\n environment:\n REP_PUBLIC_API_URL: \"http://localhost:3000\"\n REP_GATEWAY_MODE: \"proxy\"\n REP_GATEWAY_UPSTREAM: \"vite:5173\"\n REP_GATEWAY_HOT_RELOAD: \"true\"\n depends_on:\n - vite\n```\n\nAccess the app at `http://localhost:8080` to see REP-injected variables.\n\n## Full stack example\n\n```yaml\nservices:\n frontend:\n build: .\n ports:\n - \"8080:8080\"\n environment:\n REP_PUBLIC_API_URL: \"http://localhost:3000\"\n REP_PUBLIC_FEATURE_FLAGS: \"all\"\n REP_SENSITIVE_ANALYTICS_KEY: \"test-key\"\n depends_on:\n - api\n\n api:\n image: your-api:latest\n ports:\n - \"3000:3000\"\n environment:\n DATABASE_URL: \"postgres://user:pass@db:5432/app\"\n depends_on:\n - db\n\n db:\n image: postgres:16-alpine\n environment:\n POSTGRES_USER: user\n POSTGRES_PASSWORD: pass\n POSTGRES_DB: app\n```","src/content/docs/deployment/docker-compose.mdx","d2a6b719e4b5d6f7","examples/quick-no-manifest",{"id":140,"data":142,"body":148,"filePath":149,"digest":150,"deferredRender":16},{"title":143,"description":144,"editUrl":16,"head":145,"template":18,"sidebar":146,"pagefind":16,"draft":20},"Zero-Config Quick Start","Use REP with just naming conventions — no manifest, no CLI, no configuration file.",[],{"hidden":20,"attrs":147},{},"import { Aside } from '@astrojs/starlight/components';\n\nThe `.rep.yaml` manifest is entirely optional. The gateway works with nothing but environment variables — the naming convention **is** the configuration.\n\n## How it works\n\n| Env var prefix | Tier | In the browser |\n|---|---|---|\n| `REP_PUBLIC_*` | PUBLIC | Plaintext in `\u003Cscript id=\"__rep__\">`. Read with `rep.get()`. |\n| `REP_SENSITIVE_*` | SENSITIVE | AES-256-GCM encrypted. Decrypt with `await rep.getSecure()`. |\n| `REP_SERVER_*` | SERVER | Never leaves the gateway process. |\n| `REP_GATEWAY_*` | Config | Gateway settings. Not injected into the app. |\n\nThat's the entire protocol.\n\n## Step 1 — Rename your env vars\n\n```bash\n# Before (Vite) → After (REP)\nVITE_API_URL → REP_PUBLIC_API_URL\nVITE_FEATURE_FLAGS → REP_PUBLIC_FEATURE_FLAGS\n\n# Before (CRA) → After (REP)\nREACT_APP_API_URL → REP_PUBLIC_API_URL\n\n# Should be encrypted\nREACT_APP_ANALYTICS_KEY → REP_SENSITIVE_ANALYTICS_KEY\n\n# Should never reach the browser\nDB_PASSWORD → REP_SERVER_DB_PASSWORD\n```\n\n## Step 2 — Install the SDK and update reads\n\n```bash\nnpm install @rep-protocol/sdk\n```\n\n```typescript\nimport { rep } from '@rep-protocol/sdk';\n\n// Was: import.meta.env.VITE_API_URL\nconst apiUrl = rep.get('API_URL');\n\n// With a default for local development\nconst apiUrl = rep.get('API_URL', 'http://localhost:3001');\n\n// Sensitive — encrypted, decrypted on demand\nconst key = await rep.getSecure('ANALYTICS_KEY');\n```\n\n## Step 3 — Build your app (nothing changes)\n\n```bash\nnpm run build\n```\n\nThe output is now environment-agnostic.\n\n## Step 4 — Run the gateway\n\n```bash\nREP_PUBLIC_API_URL=https://api.example.com \\\nREP_PUBLIC_FEATURE_FLAGS=dark-mode,new-checkout \\\nREP_SENSITIVE_ANALYTICS_KEY=ak_live_abc123 \\\n./rep-gateway --mode embedded --static-dir ./dist\n```\n\nOpen `http://localhost:8080` — done.\n\n## Changing config without rebuilding\n\n```bash\n# Stop. Change values. Restart.\nREP_PUBLIC_API_URL=https://api.prod.example.com \\\nREP_PUBLIC_FEATURE_FLAGS=dark-mode \\\n./rep-gateway --mode embedded --static-dir ./dist\n```\n\nSame `dist/` folder. Different runtime config.\n\n### Dev mode — file watch hot reload\n\nFor local development, point the gateway at a `.env.local` file and let it watch for changes automatically — no signals, no restarts:\n\n```bash\n# .env.local\nREP_PUBLIC_API_URL=http://localhost:3001\nREP_PUBLIC_FEATURE_FLAGS=dark-mode\nREP_SENSITIVE_ANALYTICS_KEY=ak_dev_abc123\n```\n\n```bash\n./rep-gateway --mode embedded --static-dir ./dist \\\n --hot-reload \\\n --hot-reload-mode=file_watch \\\n --env-file=.env.local \\\n --watch-path=.env.local\n```\n\nEdit `.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.\n\n\u003CAside type=\"tip\">\n The CLI dev command handles this automatically: `npx @rep-protocol/cli dev --proxy http://localhost:5173` starts the gateway with file watch mode already enabled. See the [Local Development guide](/guides/development/).\n\u003C/Aside>\n\n## When to add a manifest\n\nThe manifest is additive. Add it when you need:\n\n- **Startup validation** — fail fast if a required variable is missing\n- **Type constraints** — enforce `url`, `number`, `enum` shapes\n- **TypeScript types** — `rep typegen` generates typed overloads\n- **Documentation** — single source of truth for all variables\n\n\u003CAside type=\"tip\">\n Start without a manifest. Add one later when you want validation and type generation. See the [Manifest guide](/guides/manifest/).\n\u003C/Aside>","src/content/docs/examples/quick-no-manifest.mdx","907101e185bb976d","examples/todo-react",{"id":151,"data":153,"body":159,"filePath":160,"digest":161,"deferredRender":16},{"title":154,"description":155,"editUrl":16,"head":156,"template":18,"sidebar":157,"pagefind":16,"draft":20},"Todo App (React)","Full worked example — React app with useRep, useRepSecure, hot reload, and Docker deployment.",[],{"hidden":20,"attrs":158},{},"import { Aside } from '@astrojs/starlight/components';\n\nA complete React todo app demonstrating all REP features. Source code at [`examples/todo-react/`](https://github.com/ruachtech/rep/tree/main/examples/todo-react).\n\n## Features demonstrated\n\n| Feature | Component/File | REP API |\n|---|---|---|\n| Public variable access | `App.tsx` | `useRep('APP_TITLE')` |\n| Enum validation | `Header.tsx` | `useRep('ENV_NAME')` |\n| URL variable | `TodoList.tsx` | `useRep('API_URL')` |\n| Number constraint | `TodoList.tsx` | `useRep('MAX_TODOS')` |\n| Sensitive variable | `Analytics.tsx` | `useRepSecure('ANALYTICS_KEY')` |\n| Payload metadata | `Footer.tsx` | `rep.meta()` |\n\n## Environment variables\n\n| Variable | Tier | Type | Default | Description |\n|---|---|---|---|---|\n| `APP_TITLE` | public | string | `\"Todo App\"` | Page title |\n| `ENV_NAME` | public | enum | — | `development`, `staging`, `production` |\n| `API_URL` | public | url | — | Backend API endpoint |\n| `MAX_TODOS` | public | number | `100` | Maximum todo items |\n| `ANALYTICS_KEY` | sensitive | string | — | Analytics tracking key |\n\n## Running locally\n\n### With the CLI\n\n```bash\n# From the repo root\npnpm install\n\n# Validate the manifest\ncd examples/todo-react\nnpx @rep-protocol/cli validate\n\n# Generate TypeScript types\nnpx @rep-protocol/cli typegen\n\n# Start Vite dev server\npnpm dev\n\n# In another terminal: start REP gateway proxy\nnpx @rep-protocol/cli dev --proxy http://localhost:5173\n```\n\nOpen `http://localhost:8080` to see the app with REP-injected variables.\n\n### With Docker\n\n```bash\ncd examples/todo-react\ndocker build -t rep-todo .\n\n# Run with staging config\ndocker run -p 8080:8080 \\\n -e REP_PUBLIC_APP_TITLE=\"Todo - Staging\" \\\n -e REP_PUBLIC_ENV_NAME=staging \\\n -e REP_PUBLIC_API_URL=https://api.staging.example.com \\\n -e REP_PUBLIC_MAX_TODOS=50 \\\n -e REP_SENSITIVE_ANALYTICS_KEY=UA-XXXXX-staging \\\n rep-todo\n\n# Same image, production config\ndocker run -p 8080:8080 \\\n -e REP_PUBLIC_APP_TITLE=\"Todo\" \\\n -e REP_PUBLIC_ENV_NAME=production \\\n -e REP_PUBLIC_API_URL=https://api.example.com \\\n -e REP_SENSITIVE_ANALYTICS_KEY=UA-XXXXX-prod \\\n rep-todo\n```\n\n## Hot reload\n\nWith the CLI dev server running, edit `.env.local` and send SIGHUP to the gateway:\n\n```bash\n# Edit .env.local, then:\nkill -HUP $(pidof rep-gateway)\n```\n\nComponents using `useRep()` re-render automatically.\n\n## Dockerfile\n\nThe example uses a 3-stage multi-stage build:\n\n1. **Download gateway:** Alpine + curl fetches the pre-built binary from GitHub Releases\n2. **Build app:** Node + pnpm builds SDK, React adapter, and the app in dependency order\n3. **Final image:** `FROM scratch` with just the gateway binary and static files\n\n\u003CAside type=\"tip\">\n The `FROM scratch` final image contains no OS, no shell, and no package manager. Total size is approximately 8MB (6MB gateway + 2MB static assets).\n\u003C/Aside>","src/content/docs/examples/todo-react.mdx","24f3691e912bab52","deployment/kubernetes",{"id":162,"data":164,"body":170,"filePath":171,"digest":172,"deferredRender":16},{"title":165,"description":166,"editUrl":16,"head":167,"template":18,"sidebar":168,"pagefind":16,"draft":20},"Kubernetes","Deploy REP with ConfigMaps, Secrets, sidecars, and hot reload in Kubernetes.",[],{"hidden":20,"attrs":169},{},"import { Aside } from '@astrojs/starlight/components';\n\n## Embedded deployment\n\nThe simplest Kubernetes deployment — gateway serves files directly:\n\n```yaml\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: frontend\nspec:\n replicas: 3\n selector:\n matchLabels:\n app: frontend\n template:\n metadata:\n labels:\n app: frontend\n spec:\n containers:\n - name: app\n image: myapp:latest\n ports:\n - containerPort: 8080\n envFrom:\n - configMapRef:\n name: frontend-public-config\n - secretRef:\n name: frontend-sensitive-config\n livenessProbe:\n httpGet:\n path: /rep/health\n port: 8080\n initialDelaySeconds: 5\n readinessProbe:\n httpGet:\n path: /rep/health\n port: 8080\n initialDelaySeconds: 2\n\n---\napiVersion: v1\nkind: ConfigMap\nmetadata:\n name: frontend-public-config\ndata:\n REP_PUBLIC_API_URL: \"https://api.example.com\"\n REP_PUBLIC_FEATURE_FLAGS: \"dark-mode\"\n REP_PUBLIC_ENV_NAME: \"production\"\n REP_GATEWAY_STRICT: \"true\"\n\n---\napiVersion: v1\nkind: Secret\nmetadata:\n name: frontend-sensitive-config\ntype: Opaque\nstringData:\n REP_SENSITIVE_ANALYTICS_KEY: \"UA-XXXXX-prod\"\n REP_SENSITIVE_SENTRY_DSN: \"https://abc@sentry.io/123\"\n```\n\n## Sidecar pattern (with nginx)\n\nWhen you want nginx serving files with the gateway as a sidecar:\n\n```yaml\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: frontend\nspec:\n template:\n spec:\n containers:\n - name: nginx\n image: nginx:alpine\n volumeMounts:\n - name: static-files\n mountPath: /usr/share/nginx/html\n readOnly: true\n ports:\n - containerPort: 80\n\n - name: rep-gateway\n image: ghcr.io/ruachtech/rep/gateway:latest\n args:\n - \"--upstream=localhost:80\"\n - \"--port=8080\"\n - \"--strict\"\n - \"--hot-reload\"\n - \"--hot-reload-mode=file_watch\"\n - \"--watch-path=/config\"\n envFrom:\n - configMapRef:\n name: frontend-public-config\n - secretRef:\n name: frontend-sensitive-config\n volumeMounts:\n - name: config-volume\n mountPath: /config\n readOnly: true\n ports:\n - containerPort: 8080\n livenessProbe:\n httpGet:\n path: /rep/health\n port: 8080\n\n initContainers:\n - name: copy-static\n image: myapp:latest\n command: ['cp', '-r', '/app/dist/.', '/static/']\n volumeMounts:\n - name: static-files\n mountPath: /static\n\n volumes:\n - name: static-files\n emptyDir: {}\n - name: config-volume\n configMap:\n name: frontend-dynamic-config\n```\n\n## Hot reload with ConfigMaps\n\nUse file watch mode to detect ConfigMap changes without pod restarts:\n\n1. Mount the ConfigMap as a volume\n2. Enable `--hot-reload --hot-reload-mode=file_watch --watch-path=/config`\n3. Update the ConfigMap: `kubectl apply -f configmap.yaml`\n4. Kubernetes refreshes the mounted volume\n5. The gateway detects the change and broadcasts via SSE\n6. Connected browsers receive the update\n\n```bash\n# Update a config value\nkubectl patch configmap frontend-dynamic-config \\\n -p '{\"data\":{\"REP_PUBLIC_FEATURE_FLAGS\":\"dark-mode,ai-assist\"}}'\n```\n\n\u003CAside type=\"tip\">\n Use `--health-port 9090` to serve health checks on a separate port. This keeps the health endpoint accessible only within the cluster while the main port faces the load balancer.\n\u003C/Aside>\n\n## Service\n\n```yaml\napiVersion: v1\nkind: Service\nmetadata:\n name: frontend\nspec:\n selector:\n app: frontend\n ports:\n - port: 80\n targetPort: 8080\n type: ClusterIP\n```","src/content/docs/deployment/kubernetes.mdx","53259bc9fa4f21d7","deployment/docker-proxy",{"id":173,"data":175,"body":181,"filePath":182,"digest":183,"deferredRender":16},{"title":176,"description":177,"editUrl":16,"head":178,"template":18,"sidebar":179,"pagefind":16,"draft":20},"Docker — Proxy Mode","Run the REP gateway as a reverse proxy in front of nginx or Caddy.",[],{"hidden":20,"attrs":180},{},"import { Aside } from '@astrojs/starlight/components';\n\nIn proxy mode, the gateway sits in front of your existing web server and injects variables into HTML responses.\n\n```\nBrowser → [REP Gateway :8080] → [nginx :80]\n```\n\n## Dockerfile\n\n```dockerfile\n# Stage 1: Build the frontend\nFROM node:22-alpine AS build\nWORKDIR /app\nCOPY package*.json ./\nRUN npm ci\nCOPY . .\nRUN npm run build\n\n# Stage 2: nginx + REP gateway\nFROM nginx:alpine\n\n# Copy built assets to nginx\nCOPY --from=build /app/dist /usr/share/nginx/html\n\n# Add the REP gateway binary\nCOPY --from=ghcr.io/ruachtech/rep/gateway:latest \\\n /usr/local/bin/rep-gateway /usr/local/bin/rep-gateway\n\nEXPOSE 8080\n\nENTRYPOINT [\"rep-gateway\"]\nCMD [\"--mode\", \"proxy\", \"--upstream\", \"localhost:80\", \"--port\", \"8080\"]\n```\n\n## Running\n\n```bash\ndocker build -t myapp .\n\n# Staging\ndocker run -p 8080:8080 \\\n -e REP_PUBLIC_API_URL=https://api.staging.example.com \\\n -e REP_PUBLIC_FEATURE_FLAGS=dark-mode,beta \\\n -e REP_SENSITIVE_ANALYTICS_KEY=UA-XXXXX-staging \\\n myapp\n\n# Production — SAME IMAGE\ndocker run -p 8080:8080 \\\n -e REP_PUBLIC_API_URL=https://api.example.com \\\n -e REP_PUBLIC_FEATURE_FLAGS=dark-mode \\\n -e REP_SENSITIVE_ANALYTICS_KEY=UA-XXXXX-prod \\\n -e REP_GATEWAY_STRICT=true \\\n myapp\n```\n\n## How it works\n\n1. nginx starts and serves static files on port 80 (inside the container)\n2. The gateway starts and proxies all requests to `localhost:80`\n3. For `text/html` responses, the gateway intercepts and injects the REP payload\n4. All other responses (JS, CSS, images) pass through unmodified\n\n\u003CAside>\n The gateway strips `Accept-Encoding` from proxied requests so upstreams respond with identity encoding. This avoids decompress/recompress overhead. The gateway handles gzip compression for non-compliant upstreams via stdlib.\n\u003C/Aside>\n\n## When to use proxy mode\n\n- You need nginx features (gzip, caching headers, URL rewriting, basic auth)\n- You're adding REP to an existing deployment with minimal changes\n- Your infrastructure team prefers nginx/Caddy for static file serving","src/content/docs/deployment/docker-proxy.mdx","bc743b18d2af9c3d","deployment/docker-embedded",{"id":184,"data":186,"body":192,"filePath":193,"digest":194,"deferredRender":16},{"title":187,"description":188,"editUrl":16,"head":189,"template":18,"sidebar":190,"pagefind":16,"draft":20},"Docker — Embedded Mode","Minimal FROM scratch containers with the gateway serving files directly.",[],{"hidden":20,"attrs":191},{},"import { Aside } from '@astrojs/starlight/components';\n\nIn embedded mode, the gateway serves static files directly — no nginx, no Caddy, no Node.js. This produces the smallest possible production image.\n\n## Dockerfile\n\n```dockerfile\n# Stage 1: Build the frontend\nFROM node:22-alpine AS build\nWORKDIR /app\nCOPY package*.json ./\nRUN npm ci\nCOPY . .\nRUN npm run build\n\n# Stage 2: FROM scratch — nothing but the binary and static files\nFROM scratch\n\nCOPY --from=build /app/dist /static\nCOPY --from=ghcr.io/ruachtech/rep/gateway:latest \\\n /usr/local/bin/rep-gateway /rep-gateway\n\nEXPOSE 8080\nUSER 65534:65534\n\nENTRYPOINT [\"/rep-gateway\"]\nCMD [\"--mode\", \"embedded\", \"--static-dir\", \"/static\", \"--port\", \"8080\", \"--strict\"]\n```\n\n## What's in the image\n\nExactly two things:\n- Your built static files (`dist/`)\n- The REP gateway binary (~6MB)\n\nNo OS, no shell, no utilities, no package manager. Attack surface: near zero.\n\n## Running\n\n```bash\ndocker build -t myapp .\n\ndocker run -p 8080:8080 \\\n -e REP_PUBLIC_API_URL=https://api.example.com \\\n -e REP_SENSITIVE_ANALYTICS_KEY=UA-XXXXX \\\n -e REP_GATEWAY_STRICT=true \\\n -e REP_GATEWAY_ALLOWED_ORIGINS=https://app.example.com \\\n myapp\n```\n\n## Multi-architecture builds\n\n```dockerfile\n# In the gateway download stage\nARG TARGETARCH\n# The gateway image is multi-arch — Docker selects the correct binary\nCOPY --from=ghcr.io/ruachtech/rep/gateway:latest \\\n /usr/local/bin/rep-gateway /rep-gateway\n```\n\n## Security hardening\n\nThe `FROM scratch` + non-root pattern provides:\n\n- **No shell** — `docker exec` attacks are impossible\n- **No package manager** — no malware installation vector\n- **Read-only filesystem** — compatible with `readOnlyRootFilesystem: true`\n- **Non-root user** — UID 65534 (`nobody`)\n- **Static binary** — no shared libraries, no dynamic linker\n\n\u003CAside type=\"tip\">\n Embedded mode is recommended for production deployments where you don't need nginx-specific features. The gateway handles HTTP/2, compression, and caching headers natively.\n\u003C/Aside>\n\n## When to use embedded mode\n\n- You want the smallest possible container image\n- You're deploying a pure SPA with no server-side rendering\n- Security is a priority (minimal attack surface)\n- You don't need nginx-specific features (URL rewriting, basic auth, etc.)","src/content/docs/deployment/docker-embedded.mdx","5c9bf1a376dd1907","guides/development",{"id":195,"data":197,"body":203,"filePath":204,"digest":205,"deferredRender":16},{"title":198,"description":199,"editUrl":16,"head":200,"template":18,"sidebar":201,"pagefind":16,"draft":20},"Local Development","Three approaches for developing with REP locally — defaults, mock payload, or the CLI dev server.",[],{"hidden":20,"attrs":202},{},"import { Tabs, TabItem, Aside } from '@astrojs/starlight/components';\n\nDuring local development you typically don't have the REP gateway running. The SDK handles this gracefully — `rep.get()` returns `undefined` when no payload is present.\n\n## Option A: Default values (simplest)\n\nUse the second argument to `rep.get()`:\n\n```typescript\nconst apiUrl = rep.get('API_URL', 'http://localhost:3000');\n// In dev: returns 'http://localhost:3000'\n// In prod: returns the injected value\n```\n\nThis is the simplest approach and works with any framework. No extra configuration needed.\n\n## Option B: Mock payload in HTML\n\nAdd a `\u003Cscript id=\"__rep__\">` tag to your `index.html`:\n\n```html\n\u003C!-- Only in development — the gateway replaces this in production -->\n\u003Cscript id=\"__rep__\" type=\"application/json\">\n{\n \"public\": {\n \"API_URL\": \"http://localhost:3000\",\n \"FEATURE_FLAGS\": \"dark-mode,debug\"\n },\n \"_meta\": {\n \"version\": \"0.1.0\",\n \"injected_at\": \"2026-01-01T00:00:00Z\",\n \"integrity\": \"hmac-sha256:dev-mode-no-verification\",\n \"ttl\": 0\n }\n}\n\u003C/script>\n```\n\nThis gives you the full SDK experience (including `rep.verify()` and `rep.meta()`) without the gateway.\n\n\u003CAside type=\"caution\">\n Don't forget to remove this tag from your production HTML. In production, the gateway injects it automatically.\n\u003C/Aside>\n\n## Option C: CLI dev server (full fidelity)\n\nThe `rep dev` command runs a local gateway that reads your `.env` file and proxies to your dev server:\n\n\u003CTabs>\n \u003CTabItem label=\"With Vite\">\n ```bash\n # Terminal 1: Start Vite dev server\n npm run dev\n # → Vite running at http://localhost:5173\n\n # Terminal 2: Start REP gateway proxy\n rep dev --env .env.local --proxy http://localhost:5173\n # → Gateway at http://localhost:8080 → proxies to Vite\n ```\n\n Open `http://localhost:8080` (the gateway port), not `:5173`. The gateway injects variables into Vite's HTML responses.\n \u003C/TabItem>\n \u003CTabItem label=\"With static files\">\n ```bash\n # Build first\n npm run build\n\n # Serve from dist/ with REP injection\n rep dev --env .env.local --static ./dist\n ```\n \u003C/TabItem>\n\u003C/Tabs>\n\n### `.env.local` example\n\n```bash\nREP_PUBLIC_API_URL=http://localhost:3000\nREP_PUBLIC_FEATURE_FLAGS=dark-mode,debug\nREP_SENSITIVE_ANALYTICS_KEY=test-key-123\n```\n\n### CLI dev server options\n\n| Flag | Default | Description |\n|---|---|---|\n| `-e, --env \u003Cpath>` | `.env.local` | Path to .env file |\n| `-p, --port \u003Cnumber>` | `8080` | Gateway port |\n| `--proxy \u003Curl>` | — | Upstream proxy URL |\n| `--static \u003Cpath>` | — | Serve static files (embedded mode) |\n| `--hot-reload` | `false` | Enable hot reload |\n| `--gateway-bin \u003Cpath>` | auto-detected | Path to gateway binary |\n\n\u003CAside>\n When using proxy mode with Vite, access the site through the gateway port (8080), not Vite's port (5173). Vite's HMR WebSocket continues to work through the proxy for CSS and module updates.\n\u003C/Aside>\n\n## Using all CLI commands in development\n\nThe CLI provides a complete development workflow:\n\n```bash\n# 1. Validate your manifest\nrep validate --manifest .rep.yaml\n# ✓ Manifest is valid — 6 variables, 4 settings\n\n# 2. Generate TypeScript types\nrep typegen --manifest .rep.yaml --output src/rep.d.ts\n# ✓ Generated types for 3 public + 2 sensitive variables\n\n# 3. Start the dev server\nrep dev --env .env.local --proxy http://localhost:5173\n\n# 4. Before deployment: scan bundles for leaked secrets\nrep lint --dir ./dist\n# ✓ No secrets detected in 12 files\n```","src/content/docs/guides/development.mdx","d043d5b91dcc4045","guides/installation",{"id":206,"data":208,"body":214,"filePath":215,"digest":216,"deferredRender":16},{"title":209,"description":210,"editUrl":16,"head":211,"template":18,"sidebar":212,"pagefind":16,"draft":20},"Installation","Install the REP SDK, CLI, and gateway binary.",[],{"hidden":20,"attrs":213},{},"import { Tabs, TabItem, Aside } from '@astrojs/starlight/components';\n\n## SDK\n\nThe SDK is the only package required for your application code. Zero runtime dependencies, ~1.5KB gzipped.\n\n```bash\nnpm install @rep-protocol/sdk\n```\n\n## Framework adapters (optional)\n\nIf you're using React, Vue, or Svelte, install the corresponding adapter for hot-reload-aware hooks and stores:\n\n\u003CTabs>\n \u003CTabItem label=\"React\">\n ```bash\n npm install @rep-protocol/react @rep-protocol/sdk\n ```\n \u003C/TabItem>\n \u003CTabItem label=\"Vue\">\n ```bash\n npm install @rep-protocol/vue @rep-protocol/sdk\n ```\n \u003C/TabItem>\n \u003CTabItem label=\"Svelte\">\n ```bash\n npm install @rep-protocol/svelte @rep-protocol/sdk\n ```\n \u003C/TabItem>\n\u003C/Tabs>\n\n## CLI\n\nThe CLI provides `rep validate`, `rep typegen`, `rep lint`, and `rep dev` commands. It automatically downloads the correct gateway binary for your platform during installation.\n\n```bash\nnpm install -g @rep-protocol/cli\n```\n\nOr use without installing:\n\n```bash\nnpx @rep-protocol/cli validate\nnpx @rep-protocol/cli dev --proxy http://localhost:5173\n```\n\n## Gateway binary\n\nThe gateway is a standalone Go binary (~6MB). There are several ways to get it:\n\n### Via the CLI (recommended)\n\nThe `@rep-protocol/cli` package downloads the gateway binary automatically during `npm install`.\n\n### Docker image\n\n```bash\ndocker pull ghcr.io/ruachtech/rep/gateway:latest\n```\n\nOr use in a multi-stage build:\n\n```dockerfile\nCOPY --from=ghcr.io/ruachtech/rep/gateway:latest /usr/local/bin/rep-gateway /usr/local/bin/rep-gateway\n```\n\n### Direct download\n\nDownload from [GitHub Releases](https://github.com/ruachtech/rep/releases) for your platform:\n\n```bash\n# Linux amd64\ncurl -fsSL https://github.com/RuachTech/rep/releases/download/gateway/v0.1.2/rep-gateway_0.1.2_linux_amd64.tar.gz | tar -xz\nmv rep-gateway /usr/local/bin/\n\n# macOS arm64\ncurl -fsSL https://github.com/RuachTech/rep/releases/download/gateway/v0.1.2/rep-gateway_0.1.2_darwin_arm64.tar.gz | tar -xz\nmv rep-gateway /usr/local/bin/\n```\n\n### Build from source\n\nRequires Go >= 1.24.5:\n\n```bash\ncd gateway\nmake build\n# Binary at gateway/bin/rep-gateway\n```\n\n## Development prerequisites\n\nFor contributing to REP itself:\n\n| Tool | Version | Purpose |\n|---|---|---|\n| Node.js | >= 20.0.0 | TypeScript packages |\n| pnpm | >= 9.0.0 | Workspace management |\n| Go | >= 1.24.5 | Gateway development |\n\n```bash\ngit clone https://github.com/ruachtech/rep.git\ncd rep\npnpm install\npnpm run build\n```","src/content/docs/guides/installation.mdx","4de2b53e2c252e3e","guides/testing",{"id":217,"data":219,"body":225,"filePath":226,"digest":227,"deferredRender":16},{"title":220,"description":221,"editUrl":16,"head":222,"template":18,"sidebar":223,"pagefind":16,"draft":20},"Testing","Unit testing with mock payloads, integration testing with Docker, and E2E testing patterns.",[],{"hidden":20,"attrs":224},{},"import { Aside } from '@astrojs/starlight/components';\n\n## Unit testing\n\nCreate a helper that mocks the REP payload for your test environment:\n\n```typescript\n// test/helpers/mock-rep.ts\nexport function mockRepPayload(vars: Record\u003Cstring, string>) {\n // Remove any existing mock\n document.getElementById('__rep__')?.remove();\n\n const script = document.createElement('script');\n script.id = '__rep__';\n script.type = 'application/json';\n\n const payload = {\n public: vars,\n _meta: {\n version: '0.1.0',\n injected_at: new Date().toISOString(),\n integrity: 'hmac-sha256:test-mode',\n ttl: 0,\n },\n };\n\n script.textContent = JSON.stringify(payload);\n document.head.appendChild(script);\n}\n```\n\n### Using with Vitest\n\n```typescript\nimport { describe, it, expect, beforeEach, vi } from 'vitest';\nimport { mockRepPayload } from '../helpers/mock-rep';\n\ndescribe('Config-dependent component', () => {\n beforeEach(() => {\n // Reset module cache — SDK's _init() runs on import\n vi.resetModules();\n document.head.innerHTML = '';\n document.body.innerHTML = '';\n });\n\n it('reads API_URL from REP payload', async () => {\n mockRepPayload({ API_URL: 'https://api.test.com' });\n\n // Dynamic import gets a fresh SDK instance\n const { rep } = await import('@rep-protocol/sdk');\n expect(rep.get('API_URL')).toBe('https://api.test.com');\n });\n\n it('returns default when payload is absent', async () => {\n const { rep } = await import('@rep-protocol/sdk');\n expect(rep.get('API_URL', 'fallback')).toBe('fallback');\n });\n});\n```\n\n\u003CAside type=\"tip\">\n The SDK's `_init()` function runs on module load. Use `vi.resetModules()` and dynamic `import()` in each test to get a fresh SDK instance that reads the current DOM state.\n\u003C/Aside>\n\n### Vitest configuration\n\n```typescript\n// vitest.config.ts\nimport { defineConfig } from 'vitest/config';\n\nexport default defineConfig({\n test: {\n environment: 'jsdom',\n },\n});\n```\n\n## Integration testing\n\nUse Docker Compose to test with a real gateway:\n\n```yaml\n# docker-compose.test.yml\nservices:\n app:\n build: .\n environment:\n REP_PUBLIC_API_URL: \"http://api:3000\"\n REP_PUBLIC_FEATURE_FLAGS: \"all\"\n REP_SENSITIVE_ANALYTICS_KEY: \"test-key\"\n ports:\n - \"8080:8080\"\n\n api:\n image: your-api:test\n ports:\n - \"3000:3000\"\n```\n\n```bash\ndocker compose -f docker-compose.test.yml up -d\nnpx playwright test --base-url http://localhost:8080\ndocker compose -f docker-compose.test.yml down\n```\n\n## Health check testing\n\nVerify the gateway is running and configured correctly:\n\n```bash\ncurl -s http://localhost:8080/rep/health | jq\n```\n\nExpected output:\n```json\n{\n \"status\": \"healthy\",\n \"version\": \"0.1.0\",\n \"variables\": {\n \"public\": 3,\n \"sensitive\": 1,\n \"server\": 2\n },\n \"guardrails\": {\n \"warnings\": 0,\n \"blocked\": 0\n },\n \"uptime_seconds\": 42\n}\n```\n\n## Bundle scanning\n\nUse `rep lint` in CI to catch accidentally leaked secrets in build output:\n\n```bash\nrep lint --dir ./dist --strict\n```\n\nThis runs the same entropy and pattern detection as the gateway guardrails, but against your compiled JavaScript bundles. Minified code patterns are automatically filtered to avoid false positives, while real secrets in bundles are still detected. Use `--exclude` to skip specific files:\n\n```bash\nrep lint --dir ./dist --strict --exclude \"vendor/**,*.chunk.js\"\n```\n\nAdd it as a CI step to prevent deployment of bundles containing secrets. See the [CLI reference](/reference/cli/#rep-lint) for full details on minified file handling.","src/content/docs/guides/testing.mdx","c9bf1f440fd1d8b4","guides/manifest",{"id":228,"data":230,"body":236,"filePath":237,"digest":238,"deferredRender":16},{"title":231,"description":232,"editUrl":16,"head":233,"template":18,"sidebar":234,"pagefind":16,"draft":20},"Manifest File","Declare variables, types, and settings in .rep.yaml for validation and type generation.",[],{"hidden":20,"attrs":235},{},"import { Aside } from '@astrojs/starlight/components';\n\nThe `.rep.yaml` manifest is optional but powerful. It enables:\n\n- **Startup validation** — fail fast if a required variable is missing\n- **Type constraints** — enforce `url`, `number`, `enum`, `csv` shapes\n- **TypeScript types** — `rep typegen` generates typed `get()` / `getSecure()` overloads\n- **Documentation** — a single source of truth for every variable the app uses\n\n## Example manifest\n\n```yaml\nversion: \"0.1.0\"\n\nvariables:\n API_URL:\n tier: public\n type: url\n required: true\n description: \"Base URL for the backend REST API\"\n example: \"https://api.example.com\"\n\n FEATURE_FLAGS:\n tier: public\n type: csv\n required: false\n default: \"\"\n description: \"Comma-separated feature flags\"\n example: \"dark-mode,new-checkout\"\n\n ENV_NAME:\n tier: public\n type: enum\n required: true\n values: [\"development\", \"staging\", \"production\"]\n description: \"Current deployment environment\"\n\n ANALYTICS_WRITE_KEY:\n tier: sensitive\n type: string\n required: true\n description: \"Analytics service write key\"\n\n OAUTH_CLIENT_ID:\n tier: sensitive\n type: string\n required: true\n pattern: \"^[a-zA-Z0-9]{20,}$\"\n description: \"OAuth 2.0 client identifier\"\n\n UPSTREAM_AUTH_TOKEN:\n tier: server\n type: string\n required: false\n description: \"Bearer token for upstream proxying\"\n\nsettings:\n strict_guardrails: true\n hot_reload: true\n session_key_ttl: \"30s\"\n session_key_max_rate: 10\n allowed_origins:\n - \"https://app.example.com\"\n```\n\n## Variable fields\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `tier` | `public` / `sensitive` / `server` | Yes | Security classification |\n| `type` | see below | Yes | Value type constraint |\n| `required` | boolean | No | Whether the variable must be present at startup |\n| `default` | string | No | Default value if not provided |\n| `description` | string | No | Human-readable description |\n| `example` | string | No | Example value |\n| `pattern` | string | No | Regex pattern the value must match |\n| `values` | string[] | No | Allowed values (for `enum` type) |\n| `deprecated` | boolean | No | Mark as deprecated |\n| `deprecated_message` | string | No | Migration guidance for deprecated vars |\n\n## Supported types\n\n| Type | Validation |\n|---|---|\n| `string` | Any string value |\n| `url` | Must be a valid URL |\n| `number` | Must parse as a number |\n| `boolean` | Must be `true`, `false`, `1`, or `0` |\n| `csv` | Comma-separated values |\n| `json` | Must be valid JSON |\n| `enum` | Must match one of the `values` array entries |\n\n## Settings\n\n| Setting | Type | Default | Description |\n|---|---|---|---|\n| `strict_guardrails` | boolean | `false` | Exit on guardrail warnings |\n| `hot_reload` | boolean | `false` | Enable hot reload SSE |\n| `hot_reload_mode` | string | `signal` | `file_watch`, `signal`, or `poll` |\n| `hot_reload_poll_interval` | string | `30s` | Poll interval (Go duration) |\n| `session_key_ttl` | string | `30s` | Session key expiry |\n| `session_key_max_rate` | number | `10` | Max session key requests per minute per IP |\n| `allowed_origins` | string[] | `[]` | CORS allowed origins for session key endpoint |\n\n## Validating\n\n```bash\nrep validate --manifest .rep.yaml\n```\n\nOutput:\n```\n✓ Manifest is valid\n Version: 0.1.0\n Variables: 6 total\n - PUBLIC: 3\n - SENSITIVE: 2\n - SERVER: 1\n Settings configured: 4\n```\n\nUse in CI to catch configuration errors before deployment:\n\n```yaml\n- name: Validate REP manifest\n run: npx @rep-protocol/cli validate --manifest .rep.yaml\n```\n\n## Type generation\n\nGenerate TypeScript type definitions from your manifest:\n\n```bash\nrep typegen --manifest .rep.yaml --output src/rep.d.ts\n```\n\nThis creates typed overloads for `get()` and `getSecure()`:\n\n```typescript\ndeclare module \"@rep-protocol/sdk\" {\n export interface REP {\n get(key: \"API_URL\" | \"FEATURE_FLAGS\" | \"ENV_NAME\"): string | undefined;\n getSecure(key: \"ANALYTICS_WRITE_KEY\" | \"OAUTH_CLIENT_ID\"): Promise\u003Cstring>;\n }\n}\n```\n\n\u003CAside type=\"tip\">\n Run `rep typegen` as part of your build script or as a pre-commit hook to keep types in sync with the manifest.\n\u003C/Aside>\n\nFor the full schema reference, see [Manifest Schema Reference](/reference/manifest-schema/).","src/content/docs/guides/manifest.mdx","1677b8ba99702048","frameworks/angular",{"id":239,"data":241,"body":247,"filePath":248,"digest":249,"deferredRender":16},{"title":242,"description":243,"editUrl":16,"head":244,"template":18,"sidebar":245,"pagefind":16,"draft":20},"Angular","Use REP with Angular — Injectable RepService with Observable support.",[],{"hidden":20,"attrs":246},{},"import { Aside } from '@astrojs/starlight/components';\n\n\u003CAside>\n There is no published `@rep-protocol/angular` package. Angular integration uses the core SDK directly via a service pattern shown below.\n\u003C/Aside>\n\n## Installation\n\n```bash\nnpm install @rep-protocol/sdk\n```\n\n## Create a RepService\n\n```typescript\n// src/app/services/rep.service.ts\nimport { Injectable } from '@angular/core';\nimport { rep } from '@rep-protocol/sdk';\nimport { BehaviorSubject, Observable } from 'rxjs';\n\n@Injectable({ providedIn: 'root' })\nexport class RepService {\n get(key: string, defaultValue?: string): string | undefined {\n return rep.get(key, defaultValue);\n }\n\n getSecure(key: string): Promise\u003Cstring> {\n return rep.getSecure(key);\n }\n\n watch(key: string): Observable\u003Cstring | undefined> {\n const subject = new BehaviorSubject(rep.get(key));\n rep.onChange(key, (newVal) => subject.next(newVal));\n return subject.asObservable();\n }\n}\n```\n\n## Usage in components\n\n```typescript\n// src/app/components/config-display.component.ts\nimport { Component, OnInit } from '@angular/core';\nimport { RepService } from '../services/rep.service';\nimport { Observable } from 'rxjs';\n\n@Component({\n selector: 'app-config-display',\n template: `\n \u003Cdiv>\n \u003Cp>API: {{ apiUrl }}\u003C/p>\n \u003Cp>Flags: {{ flags$ | async }}\u003C/p>\n \u003Cp>Analytics: {{ analyticsKey ?? 'loading...' }}\u003C/p>\n \u003C/div>\n `,\n})\nexport class ConfigDisplayComponent implements OnInit {\n apiUrl: string | undefined;\n flags$: Observable\u003Cstring | undefined>;\n analyticsKey: string | null = null;\n\n constructor(private rep: RepService) {\n // Synchronous — available immediately\n this.apiUrl = this.rep.get('API_URL', 'http://localhost:3000');\n\n // Observable — updates on hot reload\n this.flags$ = this.rep.watch('FEATURE_FLAGS');\n }\n\n async ngOnInit() {\n // Async — encrypted, decrypted on demand\n this.analyticsKey = await this.rep.getSecure('ANALYTICS_KEY');\n }\n}\n```\n\n## How it works\n\n- `get()` calls `rep.get()` from the core SDK — synchronous, no loading state\n- `getSecure()` calls `rep.getSecure()` — fetches a session key, decrypts, caches\n- `watch()` wraps `rep.onChange()` into a `BehaviorSubject` for Angular's `async` pipe\n\n## Development mode\n\nWithout the gateway, `rep.get()` returns `undefined`. Use default values:\n\n```typescript\nthis.apiUrl = this.rep.get('API_URL', 'http://localhost:3000');\n```\n\nOr add a mock payload to your `index.html` during development:\n\n```html\n\u003Cscript id=\"__rep__\" type=\"application/json\">\n{\"public\":{\"API_URL\":\"http://localhost:3000\"},\"_meta\":{\"version\":\"0.1.0\",\"injected_at\":\"2026-01-01T00:00:00Z\",\"integrity\":\"hmac-sha256:dev\",\"ttl\":0}}\n\u003C/script>\n```","src/content/docs/frameworks/angular.mdx","12cc1a605389df2e","frameworks/react",{"id":250,"data":252,"body":258,"filePath":259,"digest":260,"deferredRender":16},{"title":253,"description":254,"editUrl":16,"head":255,"template":18,"sidebar":256,"pagefind":16,"draft":20},"React","Use REP with React — useRep() and useRepSecure() hooks with automatic hot reload.",[],{"hidden":20,"attrs":257},{},"import { Tabs, TabItem, Aside } from '@astrojs/starlight/components';\n\n## Installation\n\n```bash\nnpm install @rep-protocol/react @rep-protocol/sdk\n```\n\n## Basic usage\n\n```tsx\nimport { useRep, useRepSecure } from '@rep-protocol/react';\n\nfunction App() {\n // PUBLIC tier — synchronous, no loading state\n const apiUrl = useRep('API_URL', 'http://localhost:3000');\n const flags = useRep('FEATURE_FLAGS', '').split(',');\n\n // SENSITIVE tier — async, renders null until resolved\n const { value: analyticsKey, loading, error } = useRepSecure('ANALYTICS_KEY');\n\n if (loading) return \u003Cspan>Loading...\u003C/span>;\n if (error) return \u003Cspan>Config error: {error.message}\u003C/span>;\n\n return (\n \u003Cdiv>\n \u003Cp>API: {apiUrl}\u003C/p>\n \u003Cp>Analytics: {analyticsKey}\u003C/p>\n \u003C/div>\n );\n}\n```\n\n## Migration from Vite / CRA\n\n**Before:**\n```typescript\n// src/config.ts\nexport const API_URL = import.meta.env.VITE_API_URL;\nexport const FEATURE_FLAGS = import.meta.env.VITE_FEATURE_FLAGS?.split(',') ?? [];\n```\n\n**After:**\n```typescript\n// src/config.ts\nimport { rep } from '@rep-protocol/sdk';\n\nexport const API_URL = rep.get('API_URL', 'http://localhost:3000');\nexport const FEATURE_FLAGS = rep.get('FEATURE_FLAGS', '')?.split(',').filter(Boolean) ?? [];\n```\n\nOr use the codemod for automated migration:\n\n```bash\nnpx @rep-protocol/codemod --framework vite src/\n```\n\n## `useRep(key, defaultValue?)`\n\nReads a **PUBLIC** tier variable. Synchronous — no loading state, no Suspense.\n\n```tsx\nconst value = useRep('API_URL'); // string | undefined\nconst value = useRep('API_URL', 'fallback'); // string (never undefined)\n```\n\n- Returns the value from the injected payload immediately\n- Returns `defaultValue` (or `undefined`) if the variable is not present\n- Automatically re-renders when the variable changes via hot reload\n- Unsubscribes on unmount\n\n## `useRepSecure(key)`\n\nReads a **SENSITIVE** tier variable. Async — fetches a session key on first call.\n\n```tsx\nconst { value, loading, error } = useRepSecure('ANALYTICS_KEY');\n// value: string | null — null until resolved\n// loading: boolean — true while fetching\n// error: Error | null — set if fetch or decryption fails\n```\n\n- Starts with `{ value: null, loading: true, error: null }`\n- The decrypted value is cached by the SDK for the page lifetime\n- Re-fetches if the `key` prop changes\n\n## Hot reload\n\nBoth hooks subscribe to the gateway's SSE stream when `--hot-reload` is enabled. Components re-render automatically when config changes. If hot reload is not available, hooks still work — they just won't update after initial render.\n\n\u003CAside>\n `useRepSecure` subscribes to hot reload for re-rendering, but sensitive variable decryption requires a new session key — which means a full component remount for updated sensitive values.\n\u003C/Aside>\n\n## Development mode\n\nWithout the gateway running, `useRep()` returns `undefined`. Two approaches:\n\n\u003CTabs>\n \u003CTabItem label=\"Default values\">\n ```tsx\n const apiUrl = useRep('API_URL', 'http://localhost:3000');\n ```\n \u003C/TabItem>\n \u003CTabItem label=\"Mock payload\">\n Add to your `index.html` during development:\n ```html\n \u003Cscript id=\"__rep__\" type=\"application/json\">\n {\"public\":{\"API_URL\":\"http://localhost:3000\",\"FEATURE_FLAGS\":\"dark-mode\"},\"_meta\":{\"version\":\"0.1.0\",\"injected_at\":\"2026-01-01T00:00:00Z\",\"integrity\":\"hmac-sha256:dev\",\"ttl\":0}}\n \u003C/script>\n ```\n \u003C/TabItem>\n \u003CTabItem label=\"CLI dev server\">\n ```bash\n # Terminal 1: Vite dev server\n npm run dev\n\n # Terminal 2: REP gateway proxy\n npx @rep-protocol/cli dev --proxy http://localhost:5173\n ```\n \u003C/TabItem>\n\u003C/Tabs>\n\n## Requirements\n\n- React >= 16.8 (hooks support)\n- `@rep-protocol/sdk` as a peer dependency\n\nFor the full API reference, see [React Adapter Reference](/reference/adapters/react/).","src/content/docs/frameworks/react.mdx","d127b4157c710b2d","frameworks/vue",{"id":261,"data":263,"body":269,"filePath":270,"digest":271,"deferredRender":16},{"title":264,"description":265,"editUrl":16,"head":266,"template":18,"sidebar":267,"pagefind":16,"draft":20},"Vue","Use REP with Vue 3 — useRep() and useRepSecure() composables with reactive refs.",[],{"hidden":20,"attrs":268},{},"import { Tabs, TabItem, Aside } from '@astrojs/starlight/components';\n\n## Installation\n\n```bash\nnpm install @rep-protocol/vue @rep-protocol/sdk\n```\n\n## Basic usage\n\n```vue\n\u003Cscript setup lang=\"ts\">\nimport { useRep, useRepSecure } from '@rep-protocol/vue';\n\n// PUBLIC tier — synchronous, reactive Ref\nconst apiUrl = useRep('API_URL', 'http://localhost:3000');\nconst flags = useRep('FEATURE_FLAGS', '');\n\n// SENSITIVE tier — async, resolves after session key fetch\nconst analyticsKey = useRepSecure('ANALYTICS_KEY');\n\u003C/script>\n\n\u003Ctemplate>\n \u003Cdiv>\n \u003Cp>API: {{ apiUrl }}\u003C/p>\n \u003Cp>Analytics: {{ analyticsKey ?? 'loading...' }}\u003C/p>\n \u003C/div>\n\u003C/template>\n```\n\n## `useRep(key, defaultValue?)`\n\nReads a **PUBLIC** tier variable as a reactive `Ref`.\n\n```typescript\nconst value: Ref\u003Cstring | undefined> = useRep('API_URL');\nconst value: Ref\u003Cstring | undefined> = useRep('API_URL', 'fallback');\n```\n\n- Returns a `Ref` set immediately from the injected payload\n- Automatically updates when the variable changes via hot reload\n- Unsubscribes via `onUnmounted` — must be called inside `setup()`\n\n## `useRepSecure(key)`\n\nReads a **SENSITIVE** tier variable as a reactive `Ref`.\n\n```typescript\nconst analyticsKey: Ref\u003Cstring | null> = useRepSecure('ANALYTICS_KEY');\n```\n\n- Starts as `null`\n- Resolves once the session key fetch and decryption complete\n- Errors are swallowed (the SDK logs them); the ref stays `null`\n- The decrypted value is cached for the page lifetime\n\n\u003CAside type=\"caution\">\n `useRepSecure` does **not** subscribe to hot reload. Sensitive variable changes require a page reload to obtain a new session key.\n\u003C/Aside>\n\n## Hot reload\n\n`useRep` subscribes to the SSE stream on mount and updates the ref automatically. The subscription is cleaned up when the component unmounts.\n\n## Development mode\n\n\u003CTabs>\n \u003CTabItem label=\"Default values\">\n ```typescript\n const apiUrl = useRep('API_URL', 'http://localhost:3000');\n ```\n \u003C/TabItem>\n \u003CTabItem label=\"Mock payload\">\n Add to your `index.html`:\n ```html\n \u003Cscript id=\"__rep__\" type=\"application/json\">\n {\"public\":{\"API_URL\":\"http://localhost:3000\"},\"_meta\":{\"version\":\"0.1.0\",\"injected_at\":\"2026-01-01T00:00:00Z\",\"integrity\":\"hmac-sha256:dev\",\"ttl\":0}}\n \u003C/script>\n ```\n \u003C/TabItem>\n\u003C/Tabs>\n\n## Requirements\n\n- Vue >= 3.0\n- `@rep-protocol/sdk` as a peer dependency\n- Composables must be called from `setup()` for proper `onUnmounted` cleanup\n\nFor the full API reference, see [Vue Adapter Reference](/reference/adapters/vue/).","src/content/docs/frameworks/vue.mdx","b44bad1f5af5708c","frameworks/svelte",{"id":272,"data":274,"body":280,"filePath":281,"digest":282,"deferredRender":16},{"title":275,"description":276,"editUrl":16,"head":277,"template":18,"sidebar":278,"pagefind":16,"draft":20},"Svelte","Use REP with Svelte — repStore() and repSecureStore() as Svelte readable stores.",[],{"hidden":20,"attrs":279},{},"import { Tabs, TabItem, Aside } from '@astrojs/starlight/components';\n\n## Installation\n\n```bash\nnpm install @rep-protocol/svelte @rep-protocol/sdk\n```\n\n## Basic usage\n\n```svelte\n\u003Cscript lang=\"ts\">\n import { repStore, repSecureStore } from '@rep-protocol/svelte';\n\n // PUBLIC tier — synchronous, updates on hot reload\n const apiUrl = repStore('API_URL', 'http://localhost:3000');\n const flags = repStore('FEATURE_FLAGS', '');\n\n // SENSITIVE tier — starts as null, resolves after decryption\n const analyticsKey = repSecureStore('ANALYTICS_KEY');\n\u003C/script>\n\n\u003Cp>API: {$apiUrl}\u003C/p>\n\u003Cp>Analytics: {$analyticsKey ?? 'loading...'}\u003C/p>\n```\n\n## `repStore(key, defaultValue?)`\n\nReads a **PUBLIC** tier variable as a Svelte `Readable\u003Cstring | undefined>`.\n\n```typescript\nconst value: Readable\u003Cstring | undefined> = repStore('API_URL');\nconst value: Readable\u003Cstring | undefined> = repStore('API_URL', 'fallback');\n```\n\n- Synchronous initial value from the REP payload\n- Automatically updates when the variable changes via hot reload\n- **Lazy SSE:** the connection is established only when there is at least one subscriber, and closed when all subscribers unsubscribe\n\n## `repSecureStore(key)`\n\nReads a **SENSITIVE** tier variable as a `Readable\u003Cstring | null>`.\n\n```typescript\nconst value: Readable\u003Cstring | null> = repSecureStore('ANALYTICS_KEY');\n```\n\n- Starts as `null`\n- Resolves to the decrypted value once the session key fetch completes\n- Errors are swallowed (the SDK logs them); the store stays `null`\n\n\u003CAside type=\"caution\">\n `repSecureStore` does **not** support hot reload. Changes to sensitive variables require a page reload.\n\u003C/Aside>\n\n## Hot reload\n\n`repStore` subscribes to the SSE stream lazily — only when there's at least one subscriber. The store value updates automatically. When the last subscriber unsubscribes, the SSE connection is closed.\n\n## Development mode\n\n\u003CTabs>\n \u003CTabItem label=\"Default values\">\n ```typescript\n const apiUrl = repStore('API_URL', 'http://localhost:3000');\n ```\n \u003C/TabItem>\n \u003CTabItem label=\"Mock payload\">\n Add to your `index.html`:\n ```html\n \u003Cscript id=\"__rep__\" type=\"application/json\">\n {\"public\":{\"API_URL\":\"http://localhost:3000\"},\"_meta\":{\"version\":\"0.1.0\",\"injected_at\":\"2026-01-01T00:00:00Z\",\"integrity\":\"hmac-sha256:dev\",\"ttl\":0}}\n \u003C/script>\n ```\n \u003C/TabItem>\n\u003C/Tabs>\n\n## Requirements\n\n- Svelte >= 4 or Svelte 5\n- `@rep-protocol/sdk` as a peer dependency\n\nFor the full API reference, see [Svelte Adapter Reference](/reference/adapters/svelte/).","src/content/docs/frameworks/svelte.mdx","2af3ad44dd245c53","frameworks/vanilla",{"id":283,"data":285,"body":291,"filePath":292,"digest":293,"deferredRender":16},{"title":286,"description":287,"editUrl":16,"head":288,"template":18,"sidebar":289,"pagefind":16,"draft":20},"Vanilla JS","Use REP without a framework — plain JavaScript, ESM import, no build tool required.",[],{"hidden":20,"attrs":290},{},"## Installation\n\n```bash\nnpm install @rep-protocol/sdk\n```\n\nOr use directly from your bundled assets without npm.\n\n## Basic usage\n\n```html\n\u003Cscript type=\"module\">\n import { rep } from '@rep-protocol/sdk';\n\n // PUBLIC tier — synchronous\n const apiUrl = rep.get('API_URL');\n document.getElementById('api-url').textContent = apiUrl;\n\n // SENSITIVE tier — async\n const key = await rep.getSecure('ANALYTICS_KEY');\n initAnalytics(key);\n\u003C/script>\n```\n\n## With hot reload\n\n```html\n\u003Cscript type=\"module\">\n import { rep } from '@rep-protocol/sdk';\n\n const el = document.getElementById('feature-flags');\n el.textContent = rep.get('FEATURE_FLAGS');\n\n // Update the DOM when config changes\n rep.onChange('FEATURE_FLAGS', (newValue) => {\n el.textContent = newValue;\n });\n\u003C/script>\n```\n\n## Integrity verification\n\n```html\n\u003Cscript type=\"module\">\n import { rep } from '@rep-protocol/sdk';\n\n if (!rep.verify()) {\n console.error('REP payload missing or tampered with');\n // Handle gracefully — show fallback UI, disable sensitive features\n }\n\n const meta = rep.meta();\n if (meta) {\n console.log('REP version:', meta.version);\n console.log('Injected at:', meta.injectedAt);\n console.log('Integrity valid:', meta.integrityValid);\n }\n\u003C/script>\n```\n\n## Development mode\n\nWithout the gateway, `rep.get()` returns `undefined`. Two options:\n\n**Option A: Check and use fallbacks**\n\n```javascript\nconst apiUrl = rep.get('API_URL') ?? 'http://localhost:3000';\n```\n\n**Option B: Mock payload in HTML**\n\n```html\n\u003Cscript id=\"__rep__\" type=\"application/json\">\n{\n \"public\": {\n \"API_URL\": \"http://localhost:3000\",\n \"FEATURE_FLAGS\": \"dark-mode,debug\"\n },\n \"_meta\": {\n \"version\": \"0.1.0\",\n \"injected_at\": \"2026-01-01T00:00:00Z\",\n \"integrity\": \"hmac-sha256:dev-mode-no-verification\",\n \"ttl\": 0\n }\n}\n\u003C/script>\n```\n\n## No build tool required\n\nREP works without any build tool. If you have a static HTML site with inline `\u003Cscript type=\"module\">` tags, just import the SDK from a CDN or self-hosted path:\n\n```html\n\u003Cscript type=\"module\">\n import { rep } from '/assets/rep-sdk.esm.js';\n // Use rep.get(), rep.getSecure(), etc.\n\u003C/script>\n```\n\nThe gateway injects the `\u003Cscript id=\"__rep__\">` payload into your HTML regardless of how your JavaScript is loaded.","src/content/docs/frameworks/vanilla.mdx","4c01f5eb4764edf4","reference/codemod",{"id":294,"data":296,"body":302,"filePath":303,"digest":304,"deferredRender":16},{"title":297,"description":298,"editUrl":16,"head":299,"template":18,"sidebar":300,"pagefind":16,"draft":20},"Codemod","Reference for @rep-protocol/codemod — automated migration from Vite, CRA, and Next.js.",[],{"hidden":20,"attrs":301},{},"```bash\nnpm install -D @rep-protocol/codemod\n# or\nnpx @rep-protocol/codemod [options] [files...]\n```\n\n## Usage\n\n```bash\nrep-codemod [options] [files or directories...]\n```\n\n## Options\n\n| Flag | Default | Description |\n|---|---|---|\n| `-f, --framework \u003Cname>` | `vite` | Framework preset: `vite`, `cra`, `next` |\n| `--dry-run` | `false` | Preview changes without writing files |\n| `--extensions \u003Clist>` | `ts,tsx,js,jsx` | Comma-separated file extensions to process |\n\n## Framework presets\n\n### `--framework vite`\n\nTransforms `import.meta.env.VITE_*` to `rep.get('*')`:\n\n```typescript\n// Before\nconst apiUrl = import.meta.env.VITE_API_URL;\n\n// After\nimport { rep } from '@rep-protocol/sdk';\nconst apiUrl = rep.get('API_URL');\n```\n\nVite built-ins (`MODE`, `DEV`, `PROD`, `SSR`, `BASE_URL`) are left untouched.\n\n### `--framework cra`\n\nTransforms `process.env.REACT_APP_*` to `rep.get('*')`:\n\n```typescript\n// Before\nconst apiUrl = process.env.REACT_APP_API_URL;\n\n// After\nimport { rep } from '@rep-protocol/sdk';\nconst apiUrl = rep.get('API_URL');\n```\n\n### `--framework next`\n\nTransforms `process.env.NEXT_PUBLIC_*` to `rep.get('*')`:\n\n```typescript\n// Before\nconst apiUrl = process.env.NEXT_PUBLIC_API_URL;\n\n// After\nimport { rep } from '@rep-protocol/sdk';\nconst apiUrl = rep.get('API_URL');\n```\n\n## Examples\n\n```bash\n# Transform Vite project\nrep-codemod --framework vite src/\n\n# Dry run — preview changes\nrep-codemod --framework cra --dry-run src/components/\n\n# Specific files\nrep-codemod --framework next src/app/page.tsx src/lib/api.ts\n\n# JavaScript files only\nrep-codemod --framework vite --extensions js,jsx src/\n```\n\n## Behavior\n\n- **Idempotent** — running twice produces the same result\n- **Import management** — adds `import { rep } from '@rep-protocol/sdk'` if absent\n- **Non-destructive** — only prefixed variables are transformed\n- **Format-preserving** — original formatting and comments are preserved (via jscodeshift/recast)\n\n## Post-migration steps\n\n1. Remove framework-specific type augmentations (e.g., `vite-env.d.ts`)\n2. Run `rep typegen` to generate typed overloads\n3. Update container config to set `REP_PUBLIC_*` environment variables","src/content/docs/reference/codemod.mdx","7342cb325938aa8d","reference/cli",{"id":305,"data":307,"body":313,"filePath":314,"digest":315,"deferredRender":16},{"title":308,"description":309,"editUrl":16,"head":310,"template":18,"sidebar":311,"pagefind":16,"draft":20},"CLI Commands","Complete reference for the @rep-protocol/cli tool — validate, typegen, lint, dev.",[],{"hidden":20,"attrs":312},{},"```bash\nnpm install -g @rep-protocol/cli\n# or\nnpx @rep-protocol/cli [command]\n```\n\n## `rep validate`\n\nValidate a `.rep.yaml` manifest against the JSON schema.\n\n```bash\nrep validate [--manifest \u003Cpath>]\n```\n\n| Flag | Default | Description |\n|---|---|---|\n| `-m, --manifest \u003Cpath>` | `.rep.yaml` | Path to manifest file |\n\n**Example:**\n```bash\n$ rep validate --manifest .rep.yaml\n✓ Manifest is valid\n Version: 0.1.0\n Variables: 11 total\n - PUBLIC: 6\n - SENSITIVE: 3\n - SERVER: 2\n Settings configured: 6\n```\n\n## `rep typegen`\n\nGenerate TypeScript type definitions from a manifest. Creates strongly-typed overloads for `rep.get()` and `rep.getSecure()`.\n\n```bash\nrep typegen [--manifest \u003Cpath>] [--output \u003Cpath>]\n```\n\n| Flag | Default | Description |\n|---|---|---|\n| `-m, --manifest \u003Cpath>` | `.rep.yaml` | Path to manifest file |\n| `-o, --output \u003Cpath>` | `src/rep.d.ts` | Output path for generated types |\n\n**Generated output:**\n```typescript\ndeclare module \"@rep-protocol/sdk\" {\n export interface REP {\n get(key: \"API_URL\" | \"FEATURE_FLAGS\"): string | undefined;\n getSecure(key: \"ANALYTICS_KEY\"): Promise\u003Cstring>;\n // ... other methods\n }\n}\n```\n\n## `rep lint`\n\nScan built JavaScript bundles for accidentally leaked secrets. Uses the same guardrail detection as the gateway (Shannon entropy, known secret formats).\n\n```bash\nrep lint [--dir \u003Cpath>] [--pattern \u003Cglob>] [--exclude \u003Cpatterns>] [--strict]\n```\n\n| Flag | Default | Description |\n|---|---|---|\n| `-d, --dir \u003Cpath>` | `./dist` | Directory to scan |\n| `--pattern \u003Cglob>` | `**/*.{js,mjs,cjs}` | File pattern to scan |\n| `--exclude \u003Cpatterns>` | — | Comma-separated glob patterns to exclude (e.g., `\"*.min.js,vendor/**\"`) |\n| `--strict` | `false` | Exit with error code if warnings found |\n\n### Minified code handling\n\nThe linter filters out false positives from minified/bundled code while still detecting real secrets embedded in your bundles.\n\n**File-level skip:** Files with `.min.js` / `.min.mjs` / `.min.cjs` extensions are skipped entirely, as these are typically third-party vendor bundles. If your build pipeline produces application code with `.min.js` filenames, rename the output or run `rep lint` against the non-minified build.\n\n**String-level filtering:** For all other files (including Vite, webpack, and Rollup bundles), extracted string values are checked for JavaScript language constructs (`function`, `return`, `if`, `=>`, `===`, `&&`, `.method()`, `key:value`, etc.) and skipped if they look like compiled code. This means real secrets accidentally embedded in a bundle are still detected, while minified code noise is filtered out.\n\nIf you still get false positives, use `--exclude` to skip specific files or directories.\n\n**Example:**\n```bash\n$ rep lint --dir ./dist\n⚠ dist/main.js\n high_entropy:42: value has high entropy (5.23 bits/char) — may be a secret\n const key = \"sk_live_abc123...\"\n\n⚠ Found 1 potential secret(s) in 1 file(s)\n```\n\n```bash\n# Exclude vendor bundles\n$ rep lint --dir ./dist --exclude \"vendor/**,*.chunk.js\"\n```\n\n**Use cases:**\n- CI/CD pipeline step before deployment\n- Pre-commit hook\n- Regular audits of production bundles\n\n## `rep dev`\n\nRun a local development server with the REP gateway. Loads env vars from a file and starts the gateway.\n\n```bash\nrep dev [options]\n```\n\n| Flag | Default | Description |\n|---|---|---|\n| `-e, --env \u003Cpath>` | `.env.local` | Path to .env file |\n| `-p, --port \u003Cnumber>` | `8080` | Gateway port |\n| `--proxy \u003Curl>` | — | Upstream proxy URL (e.g., `http://localhost:5173`) |\n| `--static \u003Cpath>` | — | Serve static files (embedded mode) |\n| `--hot-reload` | `false` | Enable hot reload |\n| `--gateway-bin \u003Cpath>` | auto | Path to gateway binary |\n\n**Example workflows:**\n\n```bash\n# Proxy mode with Vite\nrep dev --env .env.local --proxy http://localhost:5173\n\n# Embedded mode with static files\nrep dev --env .env.local --static ./dist --port 8080\n```\n\n## Binary resolution\n\nThe CLI looks for the gateway binary in this order:\n\n1. Bundled binary (downloaded during `npm install`)\n2. Custom path via `--gateway-bin`\n3. `rep-gateway` in system `PATH`","src/content/docs/reference/cli.mdx","76ca3839f3ea47b4","reference/gateway-endpoints",{"id":316,"data":318,"body":324,"filePath":325,"digest":326,"deferredRender":16},{"title":319,"description":320,"editUrl":16,"head":321,"template":18,"sidebar":322,"pagefind":16,"draft":20},"Gateway Endpoints","Reference for /rep/health, /rep/session-key, and /rep/changes endpoints.",[],{"hidden":20,"attrs":323},{},"import { Aside } from '@astrojs/starlight/components';\n\n## `GET /rep/health`\n\nReturns gateway health status including variable counts and guardrail status.\n\n**Response:**\n```json\n{\n \"status\": \"healthy\",\n \"version\": \"0.1.0\",\n \"variables\": {\n \"public\": 3,\n \"sensitive\": 1,\n \"server\": 2\n },\n \"guardrails\": {\n \"warnings\": 0,\n \"blocked\": 0\n },\n \"uptime_seconds\": 3421\n}\n```\n\n**Use cases:**\n- Kubernetes liveness/readiness probes\n- Load balancer health checks\n- Monitoring dashboards\n\n**Kubernetes probe example:**\n```yaml\nlivenessProbe:\n httpGet:\n path: /rep/health\n port: 8080\n initialDelaySeconds: 5\nreadinessProbe:\n httpGet:\n path: /rep/health\n port: 8080\n initialDelaySeconds: 2\n```\n\nUse `--health-port` to serve the health endpoint on a separate port (e.g., `9090`) to keep it internal to the cluster.\n\n## `GET /rep/session-key`\n\nIssues a short-lived decryption key for SENSITIVE tier variables. Called by the SDK's `getSecure()` method.\n\n**Request requirements:**\n- Must include an `Origin` header matching configured allowed origins (if origins are configured)\n- If no allowed origins are configured, same-origin requests are permitted\n\n**Response:**\n```json\n{\n \"key\": \"{base64_encoded_derived_aes_key}\",\n \"expires_at\": \"2026-02-18T14:30:30.000Z\"\n}\n```\n\n| Field | Description |\n|---|---|\n| `key` | HKDF-derived AES-256 encryption key, base64-encoded |\n| `expires_at` | RFC 3339 timestamp — key expires 30 seconds after issuance |\n\n**Security constraints:**\n- Keys expire within 30 seconds\n- Rate-limited to 10 requests per minute per client IP\n- Not cacheable (`Cache-Control: no-store, no-cache, must-revalidate`)\n- CORS restricted to configured origins\n- All issuances are audit-logged (`rep.session_key.issued`)\n\n**Error responses:**\n- `429 Too Many Requests` — rate limit exceeded\n- `403 Forbidden` — origin not allowed\n- `404 Not Found` — no SENSITIVE variables configured\n\n\u003CAside type=\"caution\">\n The session key is the derived key, not the master key material. Even if intercepted, it cannot be used to derive the master key or generate new session keys.\n\u003C/Aside>\n\n## `GET /rep/changes`\n\nServer-Sent Events (SSE) stream that pushes configuration updates to connected clients. Only available when `--hot-reload` is enabled.\n\n**Event format:**\n\n```\nevent: rep:config:update\ndata: {\"key\": \"FEATURE_FLAGS\", \"tier\": \"public\", \"value\": \"dark-mode,ai-assist\"}\nid: 1708267830000\n\nevent: rep:config:delete\ndata: {\"key\": \"DEPRECATED_FLAG\", \"tier\": \"public\"}\nid: 1708267831000\n```\n\n**Event types:**\n\n| Event | Description |\n|---|---|\n| `rep:config:update` | A variable's value changed or a new variable was added |\n| `rep:config:delete` | A variable was removed |\n\n**Behavior:**\n- SSE has built-in reconnection — the browser automatically reconnects on disconnect\n- The `id` field allows replay of missed events\n- Returns `404 Not Found` if hot reload is not enabled\n- Only PUBLIC tier changes are broadcast (SENSITIVE changes require a page reload)","src/content/docs/reference/gateway-endpoints.mdx","164f5b359e1b3e23","reference/manifest-schema",{"id":327,"data":329,"body":335,"filePath":336,"digest":337,"deferredRender":16},{"title":330,"description":331,"editUrl":16,"head":332,"template":18,"sidebar":333,"pagefind":16,"draft":20},"Manifest Schema","Complete reference for the .rep.yaml manifest file format.",[],{"hidden":20,"attrs":334},{},"The manifest schema is published as JSON Schema at [`/schema/rep-manifest.schema.json`](/schema/rep-manifest.schema.json).\n\n## Top-level fields\n\n```yaml\nversion: \"0.1.0\" # Required — protocol version\nvariables: { ... } # Required — variable declarations\nsettings: { ... } # Optional — gateway settings\n```\n\n## Variable declaration\n\nEach variable is declared under the `variables` map using its **stripped** name (e.g., `API_URL`, not `REP_PUBLIC_API_URL`):\n\n```yaml\nvariables:\n API_URL:\n tier: public # Required: public, sensitive, or server\n type: url # Required: string, url, number, boolean, csv, json, enum\n required: true # Optional (default: false)\n default: \"\" # Optional — default value if not provided\n description: \"...\" # Optional — human-readable description\n example: \"...\" # Optional — example value\n pattern: \"^...\" # Optional — regex pattern the value must match\n values: [...] # Optional — allowed values (enum type only)\n deprecated: false # Optional — mark as deprecated\n deprecated_message: \"Use NEW_VAR instead\" # Optional\n```\n\n### Field reference\n\n| Field | Type | Required | Description |\n|---|---|---|---|\n| `tier` | `public` \\| `sensitive` \\| `server` | Yes | Security classification tier |\n| `type` | see types table | Yes | Value type constraint |\n| `required` | `boolean` | No | Must be present at startup (default: `false`) |\n| `default` | `string` | No | Default value when variable is absent |\n| `description` | `string` | No | Human-readable purpose |\n| `example` | `string` | No | Example value for documentation |\n| `pattern` | `string` | No | Regex the value must match |\n| `values` | `string[]` | No | Allowed values (for `enum` type) |\n| `deprecated` | `boolean` | No | Mark as deprecated |\n| `deprecated_message` | `string` | No | Migration guidance |\n\n### Supported types\n\n| Type | Validation | Example |\n|---|---|---|\n| `string` | Any string | `\"hello\"` |\n| `url` | Valid URL (RFC 3986) | `\"https://api.example.com\"` |\n| `number` | Parses as finite number | `\"42\"`, `\"3.14\"` |\n| `boolean` | `\"true\"`, `\"false\"`, `\"1\"`, `\"0\"` | `\"true\"` |\n| `csv` | Comma-separated string | `\"a,b,c\"` |\n| `json` | Valid JSON | `'{\"key\":\"val\"}'` |\n| `enum` | Matches `values` array | `\"production\"` |\n\n## Settings\n\n```yaml\nsettings:\n strict_guardrails: true\n hot_reload: true\n hot_reload_mode: \"signal\"\n hot_reload_poll_interval: \"30s\"\n session_key_ttl: \"30s\"\n session_key_max_rate: 10\n allowed_origins:\n - \"https://app.example.com\"\n```\n\n| Setting | Type | Default | Description |\n|---|---|---|---|\n| `strict_guardrails` | `boolean` | `false` | Fail on guardrail warnings |\n| `hot_reload` | `boolean` | `false` | Enable hot reload SSE |\n| `hot_reload_mode` | `string` | `signal` | `file_watch`, `signal`, or `poll` |\n| `hot_reload_poll_interval` | `string` | `30s` | Poll interval (Go duration format) |\n| `session_key_ttl` | `string` | `30s` | Session key expiry duration |\n| `session_key_max_rate` | `integer` | `10` | Max session key requests/min/IP |\n| `allowed_origins` | `string[]` | `[]` | CORS origins for session key endpoint |\n\n## Full example\n\nSee [`examples/.rep.yaml`](https://github.com/ruachtech/rep/blob/main/examples/.rep.yaml) for an annotated manifest with all tiers and types.","src/content/docs/reference/manifest-schema.mdx","5c443a4c90639bfb","reference/sdk",{"id":338,"data":340,"body":346,"filePath":347,"digest":348,"deferredRender":16},{"title":341,"description":342,"editUrl":16,"head":343,"template":18,"sidebar":344,"pagefind":16,"draft":20},"SDK API","Complete API reference for @rep-protocol/sdk.",[],{"hidden":20,"attrs":345},{},"import { Aside } from '@astrojs/starlight/components';\n\n`@rep-protocol/sdk` — Zero-dependency, framework-agnostic TypeScript SDK for reading REP-injected environment variables.\n\n```bash\nnpm install @rep-protocol/sdk\n```\n\n## `get(key)`\n\nRetrieve a PUBLIC tier variable. Synchronous — no network call, no promise.\n\n```typescript\nfunction get(key: string): string | undefined;\nfunction get(key: string, defaultValue: string): string;\n```\n\n| Parameter | Type | Description |\n|---|---|---|\n| `key` | `string` | Variable name (after prefix stripping, e.g. `'API_URL'`) |\n| `defaultValue` | `string` | Optional fallback if the variable is not present |\n\n**Returns:** The variable value, `defaultValue`, or `undefined`.\n\n```typescript\nimport { rep } from '@rep-protocol/sdk';\n\nconst apiUrl = rep.get('API_URL'); // string | undefined\nconst apiUrl = rep.get('API_URL', 'http://localhost'); // string (never undefined)\n```\n\n## `getSecure(key)`\n\nRetrieve a SENSITIVE tier variable. Fetches a session key, decrypts the blob, and caches all sensitive values.\n\n```typescript\nfunction getSecure(key: string): Promise\u003Cstring>;\n```\n\n| Parameter | Type | Description |\n|---|---|---|\n| `key` | `string` | Variable name (e.g. `'ANALYTICS_KEY'`) |\n\n**Returns:** `Promise\u003Cstring>` — the decrypted value.\n\n**Throws:** `REPError` if the session key endpoint is unreachable, the key has expired, or decryption fails.\n\n```typescript\nconst key = await rep.getSecure('ANALYTICS_KEY');\n```\n\n\u003CAside>\n The first `getSecure()` call fetches a session key and decrypts **all** sensitive variables at once. Subsequent calls for different keys return from the in-memory cache without network requests.\n\u003C/Aside>\n\n## `getAll()`\n\nRetrieve all PUBLIC tier variables as a frozen object.\n\n```typescript\nfunction getAll(): Readonly\u003CRecord\u003Cstring, string>>;\n```\n\n**Returns:** A frozen `Record\u003Cstring, string>` of all public variables. Empty object if no payload is present.\n\n```typescript\nconst allVars = rep.getAll();\nconsole.log(allVars.API_URL);\n```\n\n## `verify()`\n\nCheck whether the REP payload is present and its integrity is valid.\n\n```typescript\nfunction verify(): boolean;\n```\n\n**Returns:** `true` if the payload is present, parseable, and the SRI hash matches. `false` if missing, malformed, or tampered.\n\n```typescript\nif (!rep.verify()) {\n console.error('REP payload missing or tampered');\n}\n```\n\n## `meta()`\n\nReturns metadata about the current REP payload.\n\n```typescript\nfunction meta(): REPMeta | null;\n\ninterface REPMeta {\n version: string;\n injectedAt: Date;\n integrityValid: boolean;\n publicCount: number;\n sensitiveAvailable: boolean;\n hotReloadAvailable: boolean;\n}\n```\n\n**Returns:** `REPMeta` object, or `null` if no payload is present.\n\n```typescript\nconst m = rep.meta();\nif (m) {\n console.log('REP version:', m.version);\n console.log('Injected at:', m.injectedAt);\n console.log('Public vars:', m.publicCount);\n}\n```\n\n## `onChange(key, callback)`\n\nRegister a callback for when a specific variable changes via hot reload.\n\n```typescript\nfunction onChange(\n key: string,\n callback: (newValue: string, oldValue: string | undefined) => void\n): () => void;\n```\n\n**Returns:** An unsubscribe function. Call it to stop listening.\n\nThe SSE connection is established lazily on the first `onChange()` or `onAnyChange()` call. It is closed when all listeners have been removed.\n\n```typescript\nconst unsub = rep.onChange('FEATURE_FLAGS', (newValue, oldValue) => {\n console.log(`Changed: ${oldValue} → ${newValue}`);\n});\n\n// Later:\nunsub();\n```\n\n## `onAnyChange(callback)`\n\nRegister a callback for any variable change.\n\n```typescript\nfunction onAnyChange(\n callback: (key: string, newValue: string, oldValue: string | undefined) => void\n): () => void;\n```\n\n**Returns:** An unsubscribe function.\n\n```typescript\nconst unsub = rep.onAnyChange((key, newValue) => {\n console.log(`${key} updated to ${newValue}`);\n});\n```\n\n## `REPError`\n\nCustom error class thrown by SDK operations.\n\n```typescript\nclass REPError extends Error {\n name: 'REPError';\n}\n```\n\nThrown by `getSecure()` when the session key endpoint is unreachable, the key has expired, or decryption fails.\n\n## Import styles\n\nBoth named exports and a namespace object are available:\n\n```typescript\n// Named imports\nimport { get, getSecure, verify, onChange } from '@rep-protocol/sdk';\n\n// Namespace import (recommended)\nimport { rep } from '@rep-protocol/sdk';\nrep.get('API_URL');\n```\n\n## Initialization behavior\n\nOn import, the SDK synchronously:\n\n1. Locates `\u003Cscript id=\"__rep__\">` in the DOM\n2. Parses the JSON content\n3. Triggers async SRI verification (non-blocking)\n4. Freezes the `public` object\n5. Sets `_available` and `_tampered` internal flags\n\nNo network calls are made during initialization.","src/content/docs/reference/sdk.mdx","f26ece21c35cf013","reference/gateway-flags",{"id":349,"data":351,"body":357,"filePath":358,"digest":359,"deferredRender":16},{"title":352,"description":353,"editUrl":16,"head":354,"template":18,"sidebar":355,"pagefind":16,"draft":20},"Gateway Flags","All CLI flags and environment variables for configuring the REP gateway.",[],{"hidden":20,"attrs":356},{},"The gateway is configured via command-line flags or environment variables. Flags take precedence over env vars.\n\n## Command-line flags\n\n```\nrep-gateway [flags]\n```\n\n| Flag | Default | Description |\n|---|---|---|\n| `--mode` | `proxy` | Operating mode: `proxy` or `embedded` |\n| `--upstream` | `localhost:80` | Upstream server address (proxy mode only) |\n| `--port` | `8080` | Listen port |\n| `--static-dir` | `/usr/share/nginx/html` | Static file directory (embedded mode only) |\n| `--manifest` | — | Path to `.rep.yaml` manifest file |\n| `--env-file` | — | Path to `.env` file (env vars take precedence) |\n| `--strict` | `false` | Exit on guardrail warnings |\n| `--hot-reload` | `false` | Enable hot reload SSE endpoint |\n| `--hot-reload-mode` | `signal` | Detection mode: `file_watch`, `signal`, `poll` |\n| `--watch-path` | — | Path to watch for changes (file_watch mode) |\n| `--poll-interval` | `30s` | Config poll interval (poll mode) |\n| `--log-format` | `json` | Log format: `json` or `text` |\n| `--log-level` | `info` | Log level: `debug`, `info`, `warn`, `error` |\n| `--allowed-origins` | — | Comma-separated CORS origins for `/rep/session-key` |\n| `--tls-cert` | — | Path to TLS certificate |\n| `--tls-key` | — | Path to TLS private key |\n| `--health-port` | — | Separate port for health check endpoint |\n\n## Environment variables\n\nEvery flag can be set via environment variable with the `REP_GATEWAY_` prefix:\n\n```bash\nREP_GATEWAY_MODE=proxy\nREP_GATEWAY_UPSTREAM=localhost:80\nREP_GATEWAY_PORT=8080\nREP_GATEWAY_STRICT=true\nREP_GATEWAY_HOT_RELOAD=true\nREP_GATEWAY_HOT_RELOAD_MODE=signal\nREP_GATEWAY_LOG_FORMAT=json\nREP_GATEWAY_LOG_LEVEL=info\nREP_GATEWAY_ALLOWED_ORIGINS=https://app.example.com,https://staging.example.com\n```\n\n## Precedence order\n\n1. Command-line flags (highest)\n2. Environment variables (`REP_GATEWAY_*`)\n3. Manifest file settings (lowest)\n\n## Common configurations\n\n### Proxy mode (development)\n\n```bash\nrep-gateway \\\n --mode proxy \\\n --upstream localhost:5173 \\\n --port 8080 \\\n --hot-reload\n```\n\n### Embedded mode (production)\n\n```bash\nrep-gateway \\\n --mode embedded \\\n --static-dir /static \\\n --port 8080 \\\n --strict \\\n --log-format json \\\n --allowed-origins https://app.example.com\n```\n\n### Kubernetes sidecar\n\n```bash\nrep-gateway \\\n --mode proxy \\\n --upstream localhost:80 \\\n --port 8080 \\\n --strict \\\n --hot-reload \\\n --hot-reload-mode file_watch \\\n --watch-path /config \\\n --health-port 9090\n```","src/content/docs/reference/gateway-flags.mdx","9140bbf8b7a715f2","spec/conformance",{"id":360,"data":362,"body":368,"filePath":369,"digest":370,"deferredRender":16},{"title":363,"description":364,"editUrl":16,"head":365,"template":18,"sidebar":366,"pagefind":16,"draft":20},"Conformance","Requirements for REP-conformant gateway and SDK implementations.",[],{"hidden":20,"attrs":367},{},"An implementation is **REP-conformant** if it satisfies the requirements below. This page is extracted from REP-RFC-0001 Section 11.\n\n## Gateway conformance (MUST)\n\nA conformant gateway implementation MUST:\n\n1. Read only `REP_*` prefixed environment variables\n2. Classify variables into exactly three tiers based on prefix (`PUBLIC`, `SENSITIVE`, `SERVER`)\n3. Strip the classification prefix from variable names in the payload\n4. Reject startup if variable names collide after prefix stripping\n5. Run secret detection guardrails on PUBLIC tier variables\n6. Inject a `\u003Cscript id=\"__rep__\" type=\"application/json\">` block into HTML responses\n7. Compute and include an HMAC-SHA256 integrity token\n8. Encrypt SENSITIVE tier variables using AES-256-GCM\n9. Issue single-use, time-limited session keys via `/rep/session-key`\n10. Never transmit SERVER tier variables to the client under any circumstances\n\n## Client SDK conformance (MUST)\n\nA conformant SDK implementation MUST:\n\n1. Read from `\u003Cscript id=\"__rep__\">` synchronously on import\n2. Verify payload integrity on initialization (SRI hash)\n3. Expose `get()` as a synchronous function\n4. Expose `getSecure()` as an async function\n5. Make no network calls during initialization\n6. Freeze the public variable object to prevent mutation\n\n## Optional features (MAY)\n\nConformant implementations MAY implement:\n\n1. Hot reload via Server-Sent Events\n2. Manifest file validation at startup\n3. TypeScript type generation from manifest\n4. Framework-specific adapters (React hooks, Vue composables, Svelte stores)\n5. Codemod tooling for migration\n\n## Notes\n\n- \"MUST\", \"SHOULD\", and \"MAY\" follow [RFC 2119](https://tools.ietf.org/html/rfc2119) conventions\n- The reference implementation (gateway in Go, SDK in TypeScript) satisfies all MUST requirements and implements all optional features\n- Alternative implementations need only satisfy the MUST requirements to be conformant","src/content/docs/spec/conformance.mdx","a3553c0b066f5a7a","spec/rfc-0001",{"id":371,"data":373,"body":379,"filePath":380,"digest":381,"deferredRender":16},{"title":374,"description":375,"editUrl":16,"head":376,"template":18,"sidebar":377,"pagefind":16,"draft":20},"REP-RFC-0001","Core protocol specification — Runtime Environment Protocol v0.1.0.",[],{"hidden":20,"attrs":378},{},"import { Aside, LinkCard } from '@astrojs/starlight/components';\n\n```\nTitle: Runtime Environment Protocol (REP)\nVersion: 0.1.0\nStatus: Active\nAuthors: Olamide Adebayo (Ruach Tech)\nCreated: 2026-02-18\nLicense: CC BY 4.0\n```\n\n\u003CAside>\n This is the formal specification. For a practical introduction, see [How REP Works](/concepts/how-it-works/) and the [Quick Start](/quick-start/).\n\u003C/Aside>\n\n## Abstract\n\nThis document specifies the **Runtime Environment Protocol (REP)**, a standardised method for injecting environment variables into browser-hosted applications at container startup rather than at build time. REP introduces a three-tier security classification system, cryptographic integrity verification, and an optional hot-reload mechanism.\n\nREP operates at the infrastructure layer. It requires no build-tool plugins, no framework-specific adapters, and no changes to the application's build process.\n\n## Sections\n\nThe full specification covers 14 sections. Key topics are documented separately in the docs site:\n\n\u003CLinkCard title=\"Variable Classification\" href=\"/concepts/variable-classification/\" description=\"§3 — Three-tier system, classification rules, guardrails\" />\n\u003CLinkCard title=\"How REP Works\" href=\"/concepts/how-it-works/\" description=\"§4 — Gateway architecture, startup sequence, HTML injection\" />\n\u003CLinkCard title=\"SDK API Reference\" href=\"/reference/sdk/\" description=\"§5 — Core API, initialization behavior, type generation\" />\n\u003CLinkCard title=\"Manifest File\" href=\"/guides/manifest/\" description=\"§6 — .rep.yaml schema, supported types, settings\" />\n\u003CLinkCard title=\"Gateway Flags\" href=\"/reference/gateway-flags/\" description=\"§7 — CLI flags and environment variable configuration\" />\n\u003CLinkCard title=\"Wire Format\" href=\"/concepts/wire-format/\" description=\"§8 — Payload JSON, encrypted blob, HMAC integrity\" />\n\u003CLinkCard title=\"Deployment Patterns\" href=\"/deployment/docker-embedded/\" description=\"§9 — Docker, Kubernetes, sidecar patterns\" />\n\u003CLinkCard title=\"Migration\" href=\"/guides/migration/overview/\" description=\"§10 — Incremental adoption, codemod tool\" />\n\u003CLinkCard title=\"Conformance\" href=\"/spec/conformance/\" description=\"§11 — Gateway and SDK conformance requirements\" />\n\n## Design requirements\n\n| ID | Requirement |\n|---|---|\n| R1 | **Build-tool agnostic.** Must work with any frontend framework or bundler without build-time plugins. |\n| R2 | **Security-classified.** Must distinguish between public, sensitive, and server-only variables. |\n| R3 | **Integrity-verified.** The injected configuration must be verifiable by the client SDK. |\n| R4 | **Synchronously accessible.** Public variables must be available immediately on page load. |\n| R5 | **Zero application dependencies.** The client SDK must have zero runtime dependencies. |\n| R6 | **Minimal footprint.** Gateway under 5MB, SDK under 2KB gzipped. |\n| R7 | **Container-native.** Must integrate with Docker and Kubernetes via standard env vars. |\n| R8 | **Incrementally adoptable.** Must not require all-or-nothing migration. |\n| R9 | **Observable.** Must emit structured logs and metrics for injection events. |\n| R10 | **Hot-reloadable (optional).** Must support live config updates without page reload. |\n\n## Comparison with existing solutions\n\n| Feature | `envsubst` | `runtime-env-cra` | `@import-meta-env` | `react-env` | **REP** |\n|---|:---:|:---:|:---:|:---:|:---:|\n| Framework agnostic | Yes | No | Partial | No | **Yes** |\n| No build tool plugin | Yes | No | No | No | **Yes** |\n| Security classification | -- | -- | -- | -- | **Yes** |\n| Encrypted sensitive vars | -- | -- | -- | -- | **Yes** |\n| Integrity verification | -- | -- | -- | -- | **Yes** |\n| Secret leak detection | -- | -- | -- | -- | **Yes** |\n| Hot reload | -- | -- | -- | -- | **Yes** |\n| No Node.js in prod | Partial | No | No | No | **Yes** |\n| Formal specification | -- | -- | -- | -- | **Yes** |\n| `FROM scratch` compatible | -- | -- | -- | -- | **Yes** |\n\n## FAQ\n\n**Q: Why not use a service mesh / API gateway?**\nService meshes operate at L4/L7 for service-to-service communication. They don't inject configuration into HTML. REP is complementary.\n\n**Q: Why not use SSR frameworks that support runtime env vars?**\nSSR solves this for supported frameworks, but not all apps need SSR, it couples you to a specific framework, and many organisations have existing SPAs. REP works with any SPA.\n\n**Q: Isn't the SENSITIVE tier just security through obscurity?**\nPartially — see the [Security Model](/spec/security-model/) for an honest assessment. SENSITIVE raises the bar against casual exposure while making intentional access auditable. For true secrets, use the SERVER tier.\n\n---\n\nThe full source of REP-RFC-0001 is available at [`spec/REP-RFC-0001.md`](https://github.com/ruachtech/rep/blob/main/spec/REP-RFC-0001.md).","src/content/docs/spec/rfc-0001.mdx","f234ea27c39cfccb","spec",{"id":382,"data":384,"body":390,"filePath":391,"digest":392,"deferredRender":16},{"title":385,"description":386,"editUrl":16,"head":387,"template":18,"sidebar":388,"pagefind":16,"draft":20},"Specification Overview","REP formal specification documents — RFC, Security Model, and Conformance.",[],{"hidden":20,"attrs":389},{},"REP is defined by three specification documents. They are the authoritative reference for the protocol, its security properties, and its conformance requirements.\n\n## Documents\n\n| Document | Status | Version | Description |\n|---|---|---|---|\n| [REP-RFC-0001](/spec/rfc-0001/) | Active | 0.1.0 | Core protocol specification — variable classification, gateway architecture, SDK API, wire format, deployment patterns |\n| [Security Model](/spec/security-model/) | Active | 0.1.0 | Threat model, 7 threat analyses, hardening recommendations, known limitations |\n| [Conformance](/spec/conformance/) | Active | 0.1.0 | Requirements for conformant gateway and SDK implementations |\n\n## Versioning policy\n\nThe specification uses semantic versioning:\n\n- **Patch** (0.1.x): Clarifications, typo fixes, non-normative additions\n- **Minor** (0.x.0): New optional features, backwards-compatible extensions\n- **Major** (x.0.0): Breaking changes to the wire format, API surface, or security model\n\nThe current version (0.1.0) indicates the specification is active and subject to refinement based on implementation experience. Breaking changes are possible before 1.0.\n\n## License\n\nSpecification documents are licensed under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/). Reference implementations (gateway, SDK, CLI, adapters) are licensed under [Apache 2.0](https://www.apache.org/licenses/LICENSE-2.0).\n\n## JSON schemas\n\nMachine-readable schemas are published for integration and validation:\n\n- [Payload schema](/schema/rep-payload.schema.json) — validates the injected `\u003Cscript>` JSON\n- [Manifest schema](/schema/rep-manifest.schema.json) — validates `.rep.yaml` files\n\n## References\n\n- [The Twelve-Factor App — Factor III: Config](https://12factor.net/config)\n- [OCI Image Specification](https://github.com/opencontainers/image-spec)\n- [RFC 5869 — HKDF](https://tools.ietf.org/html/rfc5869)\n- [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto)\n- [Subresource Integrity (SRI)](https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity)\n- [Server-Sent Events](https://html.spec.whatwg.org/multipage/server-sent-events.html)\n- [Content Security Policy Level 3](https://www.w3.org/TR/CSP3/)","src/content/docs/spec/index.mdx","10b24beb25918f6e","spec/security-model",{"id":393,"data":395,"body":401,"filePath":402,"digest":403,"deferredRender":16},{"title":396,"description":397,"editUrl":16,"head":398,"template":18,"sidebar":399,"pagefind":16,"draft":20},"Security Model Specification","Formal threat model and security analysis for the Runtime Environment Protocol.",[],{"hidden":20,"attrs":400},{},"import { Aside, LinkCard } from '@astrojs/starlight/components';\n\n```\nDocument: REP Security Model\nVersion: 0.1.0\nStatus: Active\nAuthors: Olamide Adebayo (Ruach Tech)\nLicense: CC BY 4.0\n```\n\n\u003CAside>\n For a practical guide to REP's security properties, see [Security Model (Concepts)](/concepts/security-model/). This page is the formal specification document.\n\u003C/Aside>\n\n\u003CLinkCard title=\"Security Model (Concepts)\" href=\"/concepts/security-model/\" description=\"Practical guide — threat analysis, hardening, monitoring recommendations\" />\n\nThe concepts page contains the full content of this specification, reformatted for easier navigation. It covers:\n\n- Fundamental axiom and trust boundaries\n- All 7 threat analyses (T1-T7) with severity, mitigations, and residual risk\n- Variable classification decision tree with common misclassifications\n- Production hardening recommendations (gateway config, FROM scratch Dockerfile, CSP headers)\n- Monitoring and alerting setup\n- Known limitations\n\n---\n\nThe full source document is at [`spec/SECURITY-MODEL.md`](https://github.com/ruachtech/rep/blob/main/spec/SECURITY-MODEL.md).","src/content/docs/spec/security-model.mdx","3da28bb9be80115e","guides/migration/from-cra",{"id":404,"data":406,"body":412,"filePath":413,"digest":414,"deferredRender":16},{"title":407,"description":408,"editUrl":16,"head":409,"template":18,"sidebar":410,"pagefind":16,"draft":20},"From Create React App","Migrate from CRA's process.env.REACT_APP_* to REP.",[],{"hidden":20,"attrs":411},{},"## Automated migration\n\n```bash\nnpx @rep-protocol/codemod --framework cra src/\n```\n\n### What it transforms\n\n```typescript\n// Before\nconst apiUrl = process.env.REACT_APP_API_URL;\nconst flags = process.env.REACT_APP_FEATURE_FLAGS;\n\n// After\nimport { rep } from '@rep-protocol/sdk';\nconst apiUrl = rep.get('API_URL');\nconst flags = rep.get('FEATURE_FLAGS');\n```\n\nOnly `REACT_APP_*` prefixed variables are transformed. Other `process.env.*` access is left unchanged.\n\n### Preview first\n\n```bash\nnpx @rep-protocol/codemod --framework cra --dry-run src/\n```\n\n## Manual migration\n\n1. **Rename environment variables:**\n ```bash\n REACT_APP_API_URL → REP_PUBLIC_API_URL\n REACT_APP_ANALYTICS_KEY → REP_SENSITIVE_ANALYTICS_KEY\n ```\n\n2. **Update code:**\n ```typescript\n import { rep } from '@rep-protocol/sdk';\n const apiUrl = rep.get('API_URL', 'http://localhost:3000');\n ```\n\n3. **Install the SDK:**\n ```bash\n npm install @rep-protocol/sdk\n ```\n\n## Post-migration cleanup\n\n1. Remove `react-app-env.d.ts` (CRA's auto-generated type declarations)\n2. Remove `.env.production` and `.env.staging` files\n3. Run `rep typegen` for typed access\n4. Update your Dockerfile to include the REP gateway","src/content/docs/guides/migration/from-cra.mdx","e449d4ecb8e99f91","guides/migration/from-next",{"id":415,"data":417,"body":423,"filePath":424,"digest":425,"deferredRender":16},{"title":418,"description":419,"editUrl":16,"head":420,"template":18,"sidebar":421,"pagefind":16,"draft":20},"From Next.js","Migrate from Next.js NEXT_PUBLIC_* variables to REP.",[],{"hidden":20,"attrs":422},{},"import { Aside } from '@astrojs/starlight/components';\n\n\u003CAside type=\"caution\">\n REP is designed for **client-side** environment variables. Next.js server-side `process.env.*` (without `NEXT_PUBLIC_` prefix) should remain as-is — they're already server-only and don't need REP.\n\u003C/Aside>\n\n## Automated migration\n\n```bash\nnpx @rep-protocol/codemod --framework next src/\n```\n\n### What it transforms\n\n```typescript\n// Before\nconst apiUrl = process.env.NEXT_PUBLIC_API_URL;\nconst flags = process.env.NEXT_PUBLIC_FEATURE_FLAGS;\n\n// After\nimport { rep } from '@rep-protocol/sdk';\nconst apiUrl = rep.get('API_URL');\nconst flags = rep.get('FEATURE_FLAGS');\n```\n\nOnly `NEXT_PUBLIC_*` prefixed variables are transformed. Server-side `process.env.*` access is left unchanged.\n\n### Preview first\n\n```bash\nnpx @rep-protocol/codemod --framework next --dry-run src/\n```\n\n## Manual migration\n\n1. **Rename environment variables:**\n ```bash\n NEXT_PUBLIC_API_URL → REP_PUBLIC_API_URL\n NEXT_PUBLIC_ANALYTICS_KEY → REP_SENSITIVE_ANALYTICS_KEY\n ```\n\n2. **Update client-side code:**\n ```typescript\n import { rep } from '@rep-protocol/sdk';\n const apiUrl = rep.get('API_URL', 'http://localhost:3000');\n ```\n\n3. **Install the SDK:**\n ```bash\n npm install @rep-protocol/sdk\n ```\n\n## Post-migration cleanup\n\n1. Remove `NEXT_PUBLIC_*` entries from `.env.local`, `.env.production`, etc.\n2. Keep server-side `process.env.*` as-is (these are already server-only)\n3. Run `rep typegen` for typed access\n4. Update your Dockerfile to include the REP gateway\n\n\u003CAside>\n For Next.js static export (`next export` or `output: 'export'`), REP works like any other SPA. For SSR deployments, REP handles only the client-side variables — server-side config continues to use standard Node.js `process.env`.\n\u003C/Aside>","src/content/docs/guides/migration/from-next.mdx","1b5d96b155bfe5f1","guides/migration/from-vite",{"id":426,"data":428,"body":434,"filePath":435,"digest":436,"deferredRender":16},{"title":429,"description":430,"editUrl":16,"head":431,"template":18,"sidebar":432,"pagefind":16,"draft":20},"From Vite","Migrate from Vite's import.meta.env to REP with the automated codemod.",[],{"hidden":20,"attrs":433},{},"import { Aside } from '@astrojs/starlight/components';\n\n## Automated migration\n\n```bash\nnpx @rep-protocol/codemod --framework vite src/\n```\n\n### What it transforms\n\n```typescript\n// Before\nconst apiUrl = import.meta.env.VITE_API_URL;\nconst flags = import.meta.env.VITE_FEATURE_FLAGS;\n\n// After\nimport { rep } from '@rep-protocol/sdk';\nconst apiUrl = rep.get('API_URL');\nconst flags = rep.get('FEATURE_FLAGS');\n```\n\n### What it leaves alone\n\nVite built-in variables are **not** transformed:\n\n- `import.meta.env.MODE`\n- `import.meta.env.DEV`\n- `import.meta.env.PROD`\n- `import.meta.env.SSR`\n- `import.meta.env.BASE_URL`\n\n### Preview first\n\n```bash\nnpx @rep-protocol/codemod --framework vite --dry-run src/\n```\n\n## Manual migration\n\nIf you prefer to migrate manually:\n\n1. **Rename environment variables:**\n ```bash\n VITE_API_URL → REP_PUBLIC_API_URL\n VITE_FEATURE_FLAGS → REP_PUBLIC_FEATURE_FLAGS\n VITE_ANALYTICS_KEY → REP_SENSITIVE_ANALYTICS_KEY\n ```\n\n2. **Update code:**\n ```typescript\n // Before\n const apiUrl = import.meta.env.VITE_API_URL;\n\n // After\n import { rep } from '@rep-protocol/sdk';\n const apiUrl = rep.get('API_URL', 'http://localhost:3000');\n ```\n\n3. **Install the SDK:**\n ```bash\n npm install @rep-protocol/sdk\n ```\n\n## Post-migration cleanup\n\n1. Remove `vite-env.d.ts` `ImportMeta` type augmentations (if you had custom ones)\n2. Remove `.env.production` and `.env.staging` files from the project\n3. Remove `envPrefix` configuration from `vite.config.ts` (if customized)\n4. Run `rep typegen --manifest .rep.yaml --output src/rep.d.ts` for typed access\n5. Update your Dockerfile to include the REP gateway\n\n\u003CAside type=\"tip\">\n The codemod is idempotent — running it twice produces the same result. It's safe to re-run after making manual changes.\n\u003C/Aside>","src/content/docs/guides/migration/from-vite.mdx","8f5b5620a48c0aa9","reference/adapters/react",{"id":437,"data":439,"body":445,"filePath":446,"digest":447,"deferredRender":16},{"title":440,"description":441,"editUrl":16,"head":442,"template":18,"sidebar":443,"pagefind":16,"draft":20},"React Adapter API","API reference for @rep-protocol/react hooks.",[],{"hidden":20,"attrs":444},{},"```bash\nnpm install @rep-protocol/react @rep-protocol/sdk\n```\n\n## `useRep(key, defaultValue?)`\n\n```typescript\nfunction useRep(key: string): string | undefined;\nfunction useRep(key: string, defaultValue: string): string;\n```\n\nReads a PUBLIC tier variable. Synchronous, hot-reload-aware.\n\n| Parameter | Type | Description |\n|---|---|---|\n| `key` | `string` | Variable name (e.g., `'API_URL'`) |\n| `defaultValue` | `string` | Optional fallback value |\n\n**Returns:** `string | undefined` (or `string` if `defaultValue` provided).\n\n**Behavior:**\n- Reads from the injected payload immediately (no loading state)\n- Subscribes to hot reload in `useEffect`\n- Unsubscribes on unmount\n- Re-renders component when the variable changes\n\n## `useRepSecure(key)`\n\n```typescript\nfunction useRepSecure(key: string): {\n value: string | null;\n loading: boolean;\n error: Error | null;\n};\n```\n\nReads a SENSITIVE tier variable. Async — fetches a session key on first call.\n\n| Parameter | Type | Description |\n|---|---|---|\n| `key` | `string` | Variable name (e.g., `'ANALYTICS_KEY'`) |\n\n**Returns:** `{ value, loading, error }` state object.\n\n**Behavior:**\n- Initial state: `{ value: null, loading: true, error: null }`\n- Success: `{ value: '...', loading: false, error: null }`\n- Failure: `{ value: null, loading: false, error: Error }`\n- Decrypted value is cached for the page lifetime\n- Re-fetches if `key` changes\n- Cleans up on unmount (cancelled flag prevents state update after unmount)\n\n## Requirements\n\n- React >= 16.8\n- `@rep-protocol/sdk` peer dependency","src/content/docs/reference/adapters/react.mdx","6718145cd5b95e97","guides/migration/overview",{"id":448,"data":450,"body":456,"filePath":457,"digest":458,"deferredRender":16},{"title":451,"description":452,"editUrl":16,"head":453,"template":18,"sidebar":454,"pagefind":16,"draft":20},"Migration Overview","A four-phase approach to migrating from build-time env vars to REP.",[],{"hidden":20,"attrs":455},{},"import { Steps, Aside } from '@astrojs/starlight/components';\n\nREP is designed for incremental adoption. You don't need to migrate everything at once — you can start with a single variable and expand from there.\n\n## Migration phases\n\n\u003CSteps>\n\n1. **Infrastructure**\n\n Set up the gateway in your deployment pipeline:\n - [ ] Download or build the gateway binary\n - [ ] Add the gateway to your Dockerfile or Kubernetes deployment\n - [ ] Configure `REP_GATEWAY_*` settings\n - [ ] Verify with `curl /rep/health`\n\n2. **SDK adoption**\n\n Replace env var reads in your application code:\n - [ ] Install `@rep-protocol/sdk`\n - [ ] Replace `import.meta.env.VITE_*` / `process.env.REACT_APP_*` with `rep.get()`\n - [ ] Replace sensitive var reads with `await rep.getSecure()`\n - [ ] Add default values for local development\n - [ ] Run the codemod for automated migration (optional)\n\n3. **Build cleanup**\n\n Remove build-time env var configuration:\n - [ ] Remove `.env.production`, `.env.staging` etc. from the build\n - [ ] Remove `--build-arg` flags from Docker builds\n - [ ] Remove framework-specific env var type declarations\n - [ ] Run `rep typegen` to generate SDK type declarations\n - [ ] Update CI/CD to use environment-agnostic builds\n\n4. **Hardening**\n\n Enable production security features:\n - [ ] Create a `.rep.yaml` manifest with all variables declared\n - [ ] Enable `--strict` mode for guardrail enforcement\n - [ ] Configure `allowed_origins` for session key CORS\n - [ ] Add `rep validate` to CI\n - [ ] Add `rep lint` to CI to scan bundles for leaked secrets\n - [ ] Review variable classification with the [decision tree](/concepts/variable-classification/)\n\n\u003C/Steps>\n\n## Using the codemod\n\nFor automated migration, the codemod transforms env var access patterns:\n\n```bash\n# Vite projects\nnpx @rep-protocol/codemod --framework vite src/\n\n# Create React App projects\nnpx @rep-protocol/codemod --framework cra src/\n\n# Next.js projects\nnpx @rep-protocol/codemod --framework next src/\n```\n\nUse `--dry-run` to preview changes before applying:\n\n```bash\nnpx @rep-protocol/codemod --framework vite --dry-run src/\n```\n\nSee framework-specific migration guides:\n- [From Vite](/guides/migration/from-vite/)\n- [From Create React App](/guides/migration/from-cra/)\n- [From Next.js](/guides/migration/from-next/)\n\n## After migration\n\nThe codemod handles the code changes. You still need to:\n\n1. Remove framework-specific type augmentations (e.g., `vite-env.d.ts` `ImportMeta` overrides)\n2. Run `rep typegen` to generate typed SDK overloads\n3. Update container config to set `REP_PUBLIC_*` / `REP_SENSITIVE_*` environment variables\n4. Verify with a test deployment\n\n\u003CAside type=\"tip\">\n You can start without a manifest file. The gateway works with just naming conventions. Add `.rep.yaml` later when you want validation and type generation.\n\u003C/Aside>","src/content/docs/guides/migration/overview.mdx","25098723d72fadad","reference/adapters/svelte",{"id":459,"data":461,"body":467,"filePath":468,"digest":469,"deferredRender":16},{"title":462,"description":463,"editUrl":16,"head":464,"template":18,"sidebar":465,"pagefind":16,"draft":20},"Svelte Adapter API","API reference for @rep-protocol/svelte stores.",[],{"hidden":20,"attrs":466},{},"```bash\nnpm install @rep-protocol/svelte @rep-protocol/sdk\n```\n\n## `repStore(key, defaultValue?)`\n\n```typescript\nfunction repStore(key: string, defaultValue?: string): Readable\u003Cstring | undefined>;\n```\n\nReads a PUBLIC tier variable as a Svelte `Readable` store.\n\n| Parameter | Type | Description |\n|---|---|---|\n| `key` | `string` | Variable name |\n| `defaultValue` | `string` | Optional fallback value |\n\n**Returns:** `Readable\u003Cstring | undefined>`\n\n**Behavior:**\n- Synchronous initial value from the payload\n- SSE subscription is **lazy** — established only when the store has subscribers\n- Updates automatically on config changes via hot reload\n- SSE connection closes when all subscribers unsubscribe\n\n## `repSecureStore(key)`\n\n```typescript\nfunction repSecureStore(key: string): Readable\u003Cstring | null>;\n```\n\nReads a SENSITIVE tier variable as a `Readable` store.\n\n| Parameter | Type | Description |\n|---|---|---|\n| `key` | `string` | Variable name |\n\n**Returns:** `Readable\u003Cstring | null>`\n\n**Behavior:**\n- Starts as `null`\n- Resolves after session key fetch and decryption\n- Errors are swallowed (SDK logs them); store stays `null`\n- Does **not** support hot reload\n\n## Requirements\n\n- Svelte >= 4 or Svelte 5\n- `@rep-protocol/sdk` peer dependency","src/content/docs/reference/adapters/svelte.mdx","1fd7407bcd7cca40","reference/adapters/vue",{"id":470,"data":472,"body":478,"filePath":479,"digest":480,"deferredRender":16},{"title":473,"description":474,"editUrl":16,"head":475,"template":18,"sidebar":476,"pagefind":16,"draft":20},"Vue Adapter API","API reference for @rep-protocol/vue composables.",[],{"hidden":20,"attrs":477},{},"```bash\nnpm install @rep-protocol/vue @rep-protocol/sdk\n```\n\n## `useRep(key, defaultValue?)`\n\n```typescript\nfunction useRep(key: string, defaultValue?: string): Ref\u003Cstring | undefined>;\n```\n\nReads a PUBLIC tier variable as a reactive `Ref`.\n\n| Parameter | Type | Description |\n|---|---|---|\n| `key` | `string` | Variable name |\n| `defaultValue` | `string` | Optional fallback value |\n\n**Returns:** `Ref\u003Cstring | undefined>`\n\n**Behavior:**\n- Set immediately from the injected payload\n- Subscribes to hot reload on creation\n- Unsubscribes via `onUnmounted`\n- Must be called inside `setup()`\n\n## `useRepSecure(key)`\n\n```typescript\nfunction useRepSecure(key: string): Ref\u003Cstring | null>;\n```\n\nReads a SENSITIVE tier variable as a reactive `Ref`.\n\n| Parameter | Type | Description |\n|---|---|---|\n| `key` | `string` | Variable name |\n\n**Returns:** `Ref\u003Cstring | null>`\n\n**Behavior:**\n- Starts as `null`\n- Resolves after session key fetch and decryption\n- Errors are swallowed (SDK logs them); ref stays `null`\n- Does **not** subscribe to hot reload\n\n## Requirements\n\n- Vue >= 3.0\n- `@rep-protocol/sdk` peer dependency\n- Must be called from `setup()` for `onUnmounted` cleanup","src/content/docs/reference/adapters/vue.mdx","0c7046e6fbeddda7"] \ No newline at end of file diff --git a/docs/src/content/docs/deployment/docker-embedded.mdx b/docs/src/content/docs/deployment/docker-embedded.mdx index d3b8a7f..a0961c3 100644 --- a/docs/src/content/docs/deployment/docker-embedded.mdx +++ b/docs/src/content/docs/deployment/docker-embedded.mdx @@ -36,7 +36,7 @@ CMD ["--mode", "embedded", "--static-dir", "/static", "--port", "8080", "--stric Exactly two things: - Your built static files (`dist/`) -- The REP gateway binary (~3MB) +- The REP gateway binary (~6MB) No OS, no shell, no utilities, no package manager. Attack surface: near zero. diff --git a/docs/src/content/docs/examples/todo-react.mdx b/docs/src/content/docs/examples/todo-react.mdx index 8b60e59..7d38b7f 100644 --- a/docs/src/content/docs/examples/todo-react.mdx +++ b/docs/src/content/docs/examples/todo-react.mdx @@ -96,5 +96,5 @@ The example uses a 3-stage multi-stage build: 3. **Final image:** `FROM scratch` with just the gateway binary and static files diff --git a/docs/src/content/docs/guides/installation.mdx b/docs/src/content/docs/guides/installation.mdx index 566cb9e..6e38fc2 100644 --- a/docs/src/content/docs/guides/installation.mdx +++ b/docs/src/content/docs/guides/installation.mdx @@ -52,7 +52,7 @@ npx @rep-protocol/cli dev --proxy http://localhost:5173 ## Gateway binary -The gateway is a standalone Go binary (~3MB). There are several ways to get it: +The gateway is a standalone Go binary (~6MB). There are several ways to get it: ### Via the CLI (recommended) diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx index 9f098c4..64cf9e7 100644 --- a/docs/src/content/docs/index.mdx +++ b/docs/src/content/docs/index.mdx @@ -21,7 +21,7 @@ import { Card, CardGrid, Tabs, TabItem } from '@astrojs/starlight/components'; -
Hot reload and feature flags — no rebuild, no redeploy.
+Same frontend image, different environment, dynamic variables — no rebuild, no redeploy.
## The Problem @@ -68,7 +68,7 @@ REP operates at the **infrastructure layer** — no build-tool plugins, no frame