Skip to content
Kong Docs are moving soon! Our docs are migrating to a new home. You'll be automatically redirected to the new site in the future. In the meantime, view this page on the new site!
Kong Logo | Kong Docs Logo
  • Docs
    • Explore the API Specs
      View all API Specs View all API Specs View all API Specs arrow image
    • Documentation
      API Specs
      Kong Gateway
      Lightweight, fast, and flexible cloud-native API gateway
      Kong Konnect
      Single platform for SaaS end-to-end connectivity
      Kong AI Gateway
      Multi-LLM AI Gateway for GenAI infrastructure
      Kong Mesh
      Enterprise service mesh based on Kuma and Envoy
      decK
      Helps manage Kong’s configuration in a declarative fashion
      Kong Ingress Controller
      Works inside a Kubernetes cluster and configures Kong to proxy traffic
      Kong Gateway Operator
      Manage your Kong deployments on Kubernetes using YAML Manifests
      Insomnia
      Collaborative API development platform
  • Plugin Hub
    • Explore the Plugin Hub
      View all plugins View all plugins View all plugins arrow image
    • Functionality View all View all arrow image
      View all plugins
      AI's icon
      AI
      Govern, secure, and control AI traffic with multi-LLM AI Gateway plugins
      Authentication's icon
      Authentication
      Protect your services with an authentication layer
      Security's icon
      Security
      Protect your services with additional security layer
      Traffic Control's icon
      Traffic Control
      Manage, throttle and restrict inbound and outbound API traffic
      Serverless's icon
      Serverless
      Invoke serverless functions in combination with other plugins
      Analytics & Monitoring's icon
      Analytics & Monitoring
      Visualize, inspect and monitor APIs and microservices traffic
      Transformations's icon
      Transformations
      Transform request and responses on the fly on Kong
      Logging's icon
      Logging
      Log request and response data using the best transport for your infrastructure
  • Support
  • Community
  • Kong Academy
Get a Demo Start Free Trial
Contribution guidelines
  • Home icon
  • Style guide and contribution guidelines
  • Single-sourced versions
github-edit-pageEdit this page
report-issueReport an issue
  • Kong Gateway
  • Kong Konnect
  • Kong Mesh
  • Kong AI Gateway
  • Plugin Hub
  • decK
  • Kong Ingress Controller
  • Kong Gateway Operator
  • Insomnia
  • Kuma

  • Docs contribution guidelines
  • Contribution guidelines
  • Style guidelines
    • Style guide
    • Word choice and naming
    • Notes and other notices
    • Diagrams
    • Documenting user interfaces
    • Contribution templates
    • Plugin documentation
      • Documenting Kong-owned plugins
      • Documenting partner plugins
  • Markdown rules and formatting
    • Markdown rules
    • Reusable content
    • Variables
    • Single-sourced versions
    • Single-sourced plugins
    • Conditional rendering
  • Community
    • Welcome to the Kong Docs community
    • Community expectations
    • Hackathons
enterprise-switcher-icon Switch to OSS
On this pageOn this page
  • Single source an entire product
  • Single source specific files
  • Manage multiple releases and single sourcing
  • Render unlisted pages
  • See also

Single-sourced versions

We use a custom Jekyll plugin (single_source_generator.rb) to dynamically generate pages from a single source file.

Here’s how it works:

  1. Read all navigation files (app/_data/docs_nav_*.yml).
  2. If the file doesn’t contain generate: true at the top level, skip it.
  3. If it does, loop through all items in the navigation:
    • If assume_generated isn’t set at the top level, or it’s set to true, then all items will be generated.
    • If assume_generated is set to false, nothing will be generated by default. Any individual navigation entry that should be generated must be set to generate: true.
  4. Each file that should be generated goes through the following process:
  5. Build the base directory.

    This is app/_src/<product> by default, but if the src starts with a /, it is treated as a full path in app/_src/. For example, /shared/license would be app/_src/shared/license, while shared/license would be app/_src/<product>/shared/license.

  6. If src is set on the item, we’ll use that as the source file.
  7. If src is not set on the item:
    • If absolute_url is set, skip the item. We assume it’s generated another way (unless the url is equal to /<product>/, which is a special case and is always generated).
    • Else, use the url and set src to be url.
  8. Read app/_src/<product>/<src>.md or app/_src/<product>/<src>/index.md and generate a file at <product>/<version>/<url> using that content.

Single source an entire product

Setting generate: true at the top level of a nav file applies the generator to every path in the file.

The comments in the following example file describe what will be read, and what URL will be generated:

product: deck
release: 1.11.x
generate: true
items:
  - title: Introduction
    # Reads `src/deck/index.md` and writes `/deck/<release>/index.html`
    # This is a special case because absolute_url is true, but `/deck/` is equal to `/<product>/`
    # and we must always generate an index page
    url: /deck/
    absolute_url: true
    items:
      - text: Terminology
        # Reads `src/deck/terminology.md` and writes `/deck/<release>/terminology/index.html`
        url: /terminology
      - text: Architecture
        # Reads `src/deck/design-architecture.md` and writes `/deck/<release>/design-architecture/index.html`
        url: /design-architecture

  - title: Changelog
    icon: /assets/images/icons/documentation/icn-references-color.svg
    # Doesn't read any file as absolute_url is set to true
    url: https://github.com/kong/deck/blob/main/CHANGELOG.md
    absolute_url: true

  - title: Installation
    icon: /assets/images/icons/documentation/icn-deployment-color.svg
    url: /installation
    # Reads `src/deck/installation-guide.md` and writes `/deck/<release>/installation/index.html`
    src: installation-guide

Single source specific files

You may not want to update an entire release at once. In this instance, single sourcing specific files might be useful. You can set assume_generated: false at the top level, then use generate: true on individual items to enable this.

product: deck
release: 1.11.x
generate: true
# This line will make Jekyll read `app/<product>/<release>/<file>.md` by default
# unless `generate: true` is set on a specific item
assume_generated: false
items:
  - title: Introduction
    # Reads `app/deck/1.11.x/index.md` like normal
    url: /deck/
    absolute_url: true
    items:
      - text: Terminology
        # Reads `app/deck/1.11.x/terminology.md` like normal
        url: /terminology
      - text: Architecture
        # Reads `src/deck/design-architecture.md` and writes `/deck/<release>/design-architecture/index.html`
        url: /design-architecture
        generate: true

  - title: Installation
    icon: /assets/images/icons/documentation/icn-deployment-color.svg
    url: /installation
    # Reads `src/deck/installation-v3.md` and writes `/deck/<release>/installation/index.html`
    src: installation-v3
    generate: true

Manage multiple releases and single sourcing

If a page requires a major rewrite for a release, it doesn’t make sense to keep everything in a single file. In this instance, you can append the major version to the filename (for example, instructions-v3.md) and use the src parameter to point to a specific file:

product: deck
release: 1.11.x
generate: true
items:
  - title: Introduction
    url: /deck/
    absolute_url: true
    items:
      - text: Terminology
        # Reads `src/deck/terminology-v3.md` and writes `/deck/<release>/terminology/index.html`
        # This is how you can have multiple releases of a single source file when completely rewriting content
        url: /terminology
        src: terminology-v3

Render unlisted pages

In some cases, you may want to render a page within a version without adding it to the side navigation. You can do this by adding an unlisted section to the data file:

product: deck
release: 1.11.x
generate: true
items:
  - title: Introduction
    url: /deck/
    absolute_url: true
    items:
      - text: Terminology
        # Reads `src/deck/terminology-v3.md` and writes `/deck/<release>/terminology/index.html`
        # This is how you can have multiple release of a single source file when completely rewriting content
        url: /terminology
        src: terminology-v3
unlisted:
  # Read from src/deck/how-to/example.md. Rendered at /deck/how-to/example/
  # Not listed in the sidebar
  # Options such as 'generate' and 'src' are valid here too
  - url: /how-to/example

See also

  • Conditional rendering: Render content in a file based on version filters
  • Single-sourced plugins: Learn about how single sourcing is implemented for Kong plugin documentation
Thank you for your feedback.
Was this page useful?
Too much on your plate? close cta icon
More features, less infrastructure with Kong Konnect. 1M requests per month for free.
Try it for Free
  • Kong
    Powering the API world

    Increase developer productivity, security, and performance at scale with the unified platform for API management, service mesh, and ingress controller.

    • Products
      • Kong Konnect
      • Kong Gateway Enterprise
      • Kong Gateway
      • Kong Mesh
      • Kong Ingress Controller
      • Kong Insomnia
      • Product Updates
      • Get Started
    • Documentation
      • Kong Konnect Docs
      • Kong Gateway Docs
      • Kong Mesh Docs
      • Kong Insomnia Docs
      • Kong Konnect Plugin Hub
    • Open Source
      • Kong Gateway
      • Kuma
      • Insomnia
      • Kong Community
    • Company
      • About Kong
      • Customers
      • Careers
      • Press
      • Events
      • Contact
  • Terms• Privacy• Trust and Compliance
© Kong Inc. 2025