Resolves from config or an environment variable inside inline code, a fenced code block, or any other text node MDX lets through. An unconfigured name renders unchanged.
Variables
Build-time {{vars.NAME}} placeholders resolve from owndocs.config.json or
NEXT_PUBLIC_DOCS_VAR_* environment variables. lib/remark-vars.mjs rewrites
the token while the page is still an mdast tree, so the rendered HTML carries
the literal value and the browser never sees a placeholder.
Quick Start
One token in inline code, resolved from the vars object in
owndocs.config.json.
The API base URL is https://api.example.com.
The API base URL is `{{vars.apiUrl}}`.Adding Options
Several tokens in the same sentence each resolve on their own, and the same substitution runs inside a fenced code block, so a sample request ships with the live values already filled in.
Welcome to OwnDocs version 1.0.0. The API base URL is
https://api.example.com, and support@example.com reaches the support team.
curl https://api.example.com/v1/status \
-H "X-Brand: OwnDocs" \
-H "X-Version: 1.0.0"Welcome to `{{vars.brand}}` version `{{vars.version}}`. The API base URL is
`{{vars.apiUrl}}`, and `{{vars.supportEmail}}` reaches the support team.
```bash title="status.sh"
curl {{vars.apiUrl}}/v1/status \
-H "X-Brand: {{vars.brand}}" \
-H "X-Version: {{vars.version}}"
```Advanced
A leading backslash keeps a token literal, and the backslash itself is eaten during substitution. A token whose name is not configured stays on the page untouched, which turns a typo into something a reviewer can see rather than a silent blank.
Escaped, this stays a token: {{vars.apiUrl}}. Unconfigured, this one also
stays put: {{vars.missingKey}}.
Escaped, this stays a token: `\{{vars.apiUrl}}`. Unconfigured, this one also
stays put: `{{vars.missingKey}}`.Where substitution reaches
The plugin walks text, inlineCode, and code nodes only. In an MDX page
that comes down to two practical homes for a token: inline code and fenced code
blocks, including fences that carry a language and a title meta. Inline code
keeps working inside list items, blockquotes, and table cells.
Plain prose is the one that trips people up. MDX reads a bare pair of braces as a JavaScript expression and fails the compile before any remark plugin runs, so wrap a prose token in backticks and it works. Two other spots stay literal by design: a value passed to a component prop, and a link or image destination, which Next.js percent-encodes instead.
Snippets share the same variable context. components/Snippet.tsx calls
getDocsVars() and passes it into the same plugin, so a fragment in snippets/
that names {{vars.brand}} resolves identically on every page that embeds it.
Defining the variables
lib/owndocs-config.ts reads owndocs.config.json from the project root, then
layers environment variables on top. An environment variable wins when both
define the same name.
{
"vars": {
"apiUrl": "https://api.example.com",
"supportEmail": "support@example.com",
"version": "1.0.0",
"brand": "OwnDocs"
}
}NEXT_PUBLIC_DOCS_VAR_API_URL="https://api.staging.example.com"
NEXT_PUBLIC_DOCS_VAR_VERSION="1.1.0"The environment name drops the NEXT_PUBLIC_DOCS_VAR_ prefix, lowercases what
is left, and turns each underscore into a camel hump, so API_URL becomes
apiUrl and SUPPORT_EMAIL becomes supportEmail.
A missing owndocs.config.json is fine and simply yields no file-defined
variables. A file that is not valid JSON, or whose top level is not an object,
throws a named error and stops the build. Inside the vars object, a key that
does not match [a-zA-Z_][a-zA-Z0-9_]* is dropped, and only string, number, and
boolean values survive; each one is coerced to a string before substitution.
Nested objects, arrays, and null are ignored.
The merged result is cached in the module after the first read, so restart the
dev server after editing owndocs.config.json or the environment file.
Options
{{vars.NAME}}token\{{vars.NAME}}escapedKeeps the token literal. The backslash is consumed and never reaches the page. Write two backslashes to show the escaped form itself inside a code block.
varsobjectThe vars object in owndocs.config.json. Keys must match
[a-zA-Z_][a-zA-Z0-9_]*; values must be a string, number, or boolean.
NEXT_PUBLIC_DOCS_VAR_*envOne variable per environment entry. The suffix is lowercased and converted to camelCase, and the value overrides a matching key from the config file.