{"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"replace-servers-url-in-different-environments","__idx":0},"children":["Replace servers URL in different environments"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Redocly allows you to use ",{"$$mdtype":"Tag","name":"Link","attributes":{"href":"/docs/cli/v2/custom-plugins/custom-decorators"},"children":["custom decorators"]}," to modify content in the API description during the bundling process."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can use this method to create multiple instances of an API description file from a single source, each with a different server. For example, you can have separate API descriptions configured with your mock server and your production server, or separate API files for each of your customers."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This page describes how to replace the server URL with a decorator for a given environment."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"prerequisites","__idx":1},"children":["Prerequisites"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"Link","attributes":{"href":"/docs/cli/v2/installation"},"children":["Install Redocly CLI"]}," version 2.x."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Use an editor for working with YAML and JavaScript files."," ","We use VS Code with the ",{"$$mdtype":"Tag","name":"Link","attributes":{"href":"https://redocly.com/docs/vscode"},"children":["Redocly extension"]}," installed."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"create-a-demo-folder-and-description-file","__idx":2},"children":["Create a demo folder and description file"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Create a working folder and a sample OpenAPI file that the decorator in the following sections uses as its input."]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Create a new folder and name it ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["replace-servers-demo"]},"."]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["replace-servers-demo"]}," folder, create an ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["original.yaml"]}," file with the following content:"]}]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"openapi: 3.1.0\ninfo:\n  version: 1.0.0\n  title: Custom decorators demo\n  description: The servers URL is replaced by the decorator during the `bundle` process.\nservers:\n  - url: 'https://example.com/api/v1'\npaths:\n  /status:\n    get:\n      summary: Get status\n      operationId: getStatus\n      security: []\n      responses:\n        '204':\n          description: Status OK\n        '400':\n          description: Status not OK\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"ol","attributes":{"start":3},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Save the file."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"create-a-custom-plugin","__idx":3},"children":["Create a custom plugin"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["A plugin is the container that registers a decorator with Redocly CLI."," ","Create the plugin file first and wire up the decorator it depends on; the decorator itself is added in the next section."]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["replace-servers-demo"]}," folder, create a folder called ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["plugins"]},"."]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["plugins"]}," folder, create a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["plugin.js"]}," file with this code:"]}]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"js","header":{"controls":{"copy":{}}},"source":"import ReplaceServersURL from './decorators/replace-servers-url.js';\n\n/** @type {import('@redocly/cli').DecoratorsConfig} */\nconst decorators = {\n  oas3: {\n    'replace-servers-url': ReplaceServersURL,\n  },\n};\n\nexport default function replaceServersUrlPlugin() {\n  return {\n    id: 'plugin',\n    decorators,\n  };\n}\n","lang":"js"},"children":[]},{"$$mdtype":"Tag","name":"ol","attributes":{"start":3},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Save the file."]}]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["plugins"]}," folder and the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["plugin.js"]}," file can be renamed."," ","In that case, the import path above, and the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["plugins"]}," entry in the Redocly configuration file, must ",{"$$mdtype":"Tag","name":"Link","attributes":{"href":"#configure-the-plugin-for-use"},"children":["match the new names"]},"."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"add-a-decorator","__idx":4},"children":["Add a decorator"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The decorator is the function that modifies the API description."," ","It accepts a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["serverUrl"]}," parameter from the Redocly configuration file and overwrites the URL on every ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Server"]}," node in the document."]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Inside the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["plugins"]}," folder, create a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["decorators"]}," folder."]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["decorators"]}," folder, create a ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["replace-servers-url.js"]}," file with this code:"]}]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"js","header":{"controls":{"copy":{}}},"source":"/** @type {import('@redocly/cli').OasDecorator} */\nexport default function ReplaceServersURL({ serverUrl }) {\n  return {\n    Server: {\n      leave(Server) {\n        if (serverUrl) {\n          Server.url = serverUrl;\n        }\n      },\n    },\n  };\n}\n","lang":"js"},"children":[]},{"$$mdtype":"Tag","name":"ol","attributes":{"start":3},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Save the file."]}]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["decorators"]}," folder can be renamed.In that case, keep the import path in the ",{"$$mdtype":"Tag","name":"Link","attributes":{"href":"#create-a-custom-plugin"},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["plugin.js"]}," file"]}," in sync with the new name."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"configure-the-plugin-for-use","__idx":5},"children":["Configure the plugin for use"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Register the plugin in the ",{"$$mdtype":"Tag","name":"Link","attributes":{"href":"/docs/cli/v2/configuration"},"children":["Redocly configuration file"]}," and create one API entry per environment."," ","Each API entry passes a different ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["serverUrl"]}," value to the same decorator, producing multiple outputs from a single source file."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"apis:\n  sample@v1-backend:\n    root: original.yaml\n    decorators:\n      plugin/replace-servers-url:\n        serverUrl: 'https://backend.example.com/v1'\n  sample@v1-proxy:\n    root: original.yaml\n    decorators:\n      plugin/replace-servers-url:\n        serverUrl: 'https://proxy.example.com/v1'\nplugins:\n  - './plugins/plugin.js'\nextends:\n  - recommended\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"verify-the-output","__idx":6},"children":["Verify the output"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"check-the-configuration-for-the-backend-server","__idx":7},"children":["Check the configuration for the \"backend\" server"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Run the following command to bundle the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["original.yaml"]}," API with the \"backend\" server URL."]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"shell","header":{"controls":{"copy":{}}},"source":"npx @redocly/cli@latest bundle sample@v1-backend\n","lang":"shell"},"children":[]},{"$$mdtype":"Tag","name":"ol","attributes":{"start":2},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Verify that the output shows the correct server URL."]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"openapi: 3.1.0\ninfo:\n  version: 1.0.0\n  title: Custom decorators demo\n  description: The servers URL is replaced by the decorator during the `bundle` process.\nservers:\n  - url: https://backend.example.com/v1\n# ...\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"check-the-configuration-for-the-proxy-server","__idx":8},"children":["Check the configuration for the \"proxy\" server"]},{"$$mdtype":"Tag","name":"ol","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Run the following command to bundle the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["original.yaml"]}," API with the \"proxy\" server URL."]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"shell","header":{"controls":{"copy":{}}},"source":"npx @redocly/cli@latest bundle sample@v1-proxy\n","lang":"shell"},"children":[]},{"$$mdtype":"Tag","name":"ol","attributes":{"start":2},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["Verify that the output shows the correct server URL."]}]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"yaml","header":{"controls":{"copy":{}}},"source":"openapi: 3.1.0\ninfo:\n  version: 1.0.0\n  title: Custom decorators demo\n  description: The servers URL is replaced by the decorator during the `bundle` process.\nservers:\n  - url: https://proxy.example.com/v1\n# ...\n","lang":"yaml"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"summary","__idx":9},"children":["Summary"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["In this tutorial you have created a plugin and a decorator that replace the server URL with one of the URLs defined in the Redocly configuration file."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You now have two API description files, each configured to send requests to different servers."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"whats-next","__idx":10},"children":["What's next?"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You can reuse the code from your demo files and modify it to fit your API documentation."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For more custom plugins, configuration, and other resources, see the ",{"$$mdtype":"Tag","name":"Link","attributes":{"href":"https://github.com/Redocly/redocly-cli-cookbook"},"children":["Redocly CLI Cookbook"]},"."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["For the latest Redocly news and articles, visit our ",{"$$mdtype":"Tag","name":"Link","attributes":{"href":"https://redocly.com/blog/"},"children":["blog"]},"."]}]},"frontmatter":{},"tagList":["admonition"],"title":"Replace servers URL in different environments","lastModified":"2026-05-18T14:03:00.000Z"}