Skip to main content

Customize portal content

Beta Feature

The Enterprise Portal is Beta. Features described on this page are subject to change.

The content template gives you a working portal out of the box. It includes install and upgrade pages for each install method, instance and update management, security reports, support bundles, and automation docs, and each page appears only to customers whose license allows it. You don't need to change anything to launch. Use this topic when you want to match your product's terminology, add your own documentation, or change the navigation.

This topic describes how to customize the content in the new Enterprise Portal. It covers the content template, the table of contents, MDX components, the KOTS and kURL pages, template variables, visibility rules, and downloadable assets. For every MDX component and its props, see MDX component reference.

For branding and theme customization, see Customize portal branding. To serve different content for different release versions, see Manage content versions.

Content template structure​

The default content template (replicatedhq/enterprise-portal-content) provides a working portal out of the box with the following structure:

your-content-repo/
├── pages/
│ ├── home.md
│ ├── installation/
│ │ ├── release-history.md
│ │ ├── linux.md
│ │ ├── kurl.md
│ │ ├── helm.md
│ │ └── kots.md
│ ├── updates/
│ │ ├── instances.md
│ │ ├── kots.md
│ │ └── kurl.md
│ ├── security.md
│ ├── support/
│ │ ├── bundles.md
│ │ ├── faq.md
│ │ └── contact.md
│ └── automation/
│ ├── api-reference.md
│ └── workflow-guide.md
├── toc.yaml
└── theme.yaml

The template's toc.yaml organizes content into Installation, Instances & Updates, Security, Support, and Automation. Instances & Updates contains the instance list plus the KOTS and kURL upgrade guides. Install method pages and upgrade guides use an entitlement gate. The KOTS existing-cluster page requires isKotsInstallEnabled only. The Linux (kURL) page requires isKurlInstallEnabled and isAirgapSupported, because the default kURL page is still downloads-only for air gap.

navigation:
- title: Installation
items:
- title: Release History
page: pages/installation/release-history.md
- title: Linux (Embedded Cluster)
page: pages/installation/linux.md
visible_when:
entitlements:
- isEmbeddedClusterDownloadEnabled
- title: Linux (kURL)
page: pages/installation/kurl.md
visible_when:
entitlements:
- isKurlInstallEnabled
- isAirgapSupported
- title: Existing Cluster (Helm)
page: pages/installation/helm.md
visible_when:
entitlements:
- isHelmInstallEnabled
- title: Existing Cluster (KOTS)
page: pages/installation/kots.md
visible_when:
entitlements:
- isKotsInstallEnabled

- title: Instances & Updates
items:
- title: Instances
page: pages/updates/instances.md
- title: Upgrade KOTS Applications
page: pages/updates/kots.md
visible_when:
entitlements:
- isKotsInstallEnabled
- title: Upgrade kURL Applications
page: pages/updates/kurl.md
visible_when:
entitlements:
- isKurlInstallEnabled

- title: Security
page: pages/security.md
visible_when:
entitlements:
- canViewSecurity

- title: Support
items:
- title: Support Bundles
page: pages/support/bundles.md
- title: FAQ
page: pages/support/faq.md
- title: Contact Support
page: pages/support/contact.md

- title: Automation
items:
- title: API Reference
page: pages/automation/api-reference.md
- title: Workflow Guide
page: pages/automation/workflow-guide.md

overrides:
home: pages/home.md

The template pages use built-in MDX components (see MDX component reference) to render interactive installation instructions, version selectors, support bundle uploads, and more. You can customize any page by editing the markdown and MDX, or replace the entire structure with your own. The template repository is the source of truth for the current template, so check it if this example differs.

Table of contents​

The toc.yaml file at the root of your repo defines the sidebar navigation. Each navigation item has a title and one of the following content types:

KeyWhat it does
pageRenders a markdown file from your repo (e.g. pages/getting-started.md)
linkOpens an external URL in a new tab instead of a page (see External links)
terraform_moduleGenerates docs from a Terraform module source URI (see Terraform Modules)
helm_chartGenerates reference docs from a Helm chart in your promoted release (see Helm Reference Docs)
itemsNests child navigation items to create expandable sections. Items can nest to any depth, with each child following the same structure

Every item also supports icon and visible_when. See Visibility.

The toc.yaml acts as an allowlist: pages that exist in your repo but are not listed in toc.yaml are not reachable through the portal navigation or direct URL. Omitting a page from toc.yaml hides it entirely. To keep the page in the repo and listed in the table of contents without publishing it, set hidden: true in the page frontmatter. See Hide unpublished pages.

note

The overrides.home page bypasses the table of contents allowlist and remains accessible even if it is not listed in toc.yaml. To hide the home landing page, set hidden: true or visible_when in its frontmatter. overrides.home cannot restore a hidden page or a child of a hidden parent.

Supported icon values: rocket, download, cloud, settings, wrench, life-buoy, file-text, star, book, shield, package, refresh-cw, database, key. If omitted, defaults to book.

Complete example​

The following toc.yaml shows all content types together:

navigation:
- title: Getting Started
icon: rocket
page: pages/getting-started.md

- title: Installation
icon: download
items:
- title: Requirements
page: pages/installation/requirements.md
- title: Helm Installation
page: pages/installation/helm.md
visible_when:
entitlements:
- isHelmInstallEnabled
- title: Air Gap Installation
page: pages/installation/airgap.md
visible_when:
entitlements:
- isAirgapSupported

- title: Infrastructure
icon: database
items:
- title: AWS Module
terraform_module: github.com/your-org/your-terraform//modules/aws?ref=v1.0.0
visible_when:
entitlements:
- isAWSEnabled

- title: Reference
icon: book
items:
- title: My App Chart
helm_chart:
name: my-app

overrides:
home: pages/getting-started.md

Nested navigation​

Navigation items can nest to any depth. Each child item follows the same structure and can contain its own items array:

navigation:
- title: Configuration
icon: settings
items:
- title: Required Values
page: pages/configuration/required-values.md
items:
- title: Authentication
page: pages/configuration/auth.md
- title: Networking
page: pages/configuration/networking.md
- title: Optional Values
page: pages/configuration/optional-values.md

In this example, Configuration expands to show Required Values and Optional Values. Required Values further expands to show Authentication and Networking. Each level is collapsible in the sidebar.

Any item with items can also have its own page, visible_when, and icon. If visible_when hides every child, the portal hides the parent too.

If a table of contents entry has a page with hidden: true, the portal drops that entry and every nested item, including nested helm_chart and terraform_module items. A section that is only a title (no page) cannot use hidden. For more information, see Hide unpublished pages.

Use link to add a navigation item that opens an external URL in a new tab instead of rendering a page from your content repo:

- title: Support
icon: life-buoy
items:
- title: Submit a Support Request
link: https://support.example.com
- title: Support Bundles
page: pages/support/bundles.md

Supported link values:

  • Fully-qualified http:// or https:// URLs
  • mailto: links, including query parameters (for example, mailto:[email protected]?subject=Help)
  • Bare external hostnames (for example, support.example.com or www.google.com/search?q=replicated), which the portal treats as https:// automatically

A link value must be a static URL. Template variables (\{\{ \}\}) and other dynamic values are not supported, and validation rejects relative or internal-looking paths. If a navigation item's link value fails validation, content sync (and local preview) fails with an error that names the offending item.

If an item specifies both link and page, link takes priority.

MDX components​

Enterprise Portal content supports MDX, which is markdown with embedded React components. The components render interactive UI elements, such as install commands, version selectors, and support bundle uploads, that adapt to each customer's license, entitlements, and instance state. For every component and its props, see MDX component reference.

Standard markdown links ([text](path)) use client-side navigation automatically. Link paths resolve relative to the current page's URL, so use a leading-slash absolute path such as [Configure values](/installation/values) to link reliably from any page. The portal adds the customer's selected version to the resolved route. For more information, see <ContentLink> in MDX component reference.

Customize the KOTS and kURL pages​

KOTS and kURL instances already appear on the Instances & Updates page with no setup. Embedded Cluster and Helm instances can expand into generated CLI upgrade steps. KOTS and kURL instances expand into target-aware Admin Console application-upgrade guidance, including an application bundle download for entitled air gap customers. The <InstancesAndUpdates /> component in the default template renders this page.

The default content template also ships dedicated install pages, already listed in toc.yaml:

  • Embedded Cluster: pages/installation/linux.md
  • Helm: pages/installation/helm.md
  • KOTS existing cluster: pages/installation/kots.md
  • kURL: pages/installation/kurl.md

You do not need to author a KOTS page from scratch. Start from the template page and customize it.

What the default KOTS page contains​

pages/installation/kots.md requires isKotsInstallEnabled. It includes:

  • An installation selector (<PendingInstallSelector>, <NewInstall>, <InstanceName>)
  • <NetworkAvailability installType="kots" /> and <VersionSelector installType="kots" />
  • <LicenseDownload /> for every network mode (online and proxy generated kubectl kots install commands require --license-file ./license.yaml)
  • Online and proxy installs: generated commands from <KotsInstallAssets />, then workstation CLI tools from <KotsDownloadAssets cliOnly={true} />, wrapped in <WhenNetwork mode="online,proxy">
  • Air gap installs: a documentation-style procedure wrapped in <WhenNetwork mode="airgap">, including:
    • Requirements for a private registry and two registry accounts (read-write for push-images, read-only for kots install). These are the customer's registry credentials, not portal or license credentials.
    • <KotsDownloadAssets />
    • Installing the downloaded KOTS CLI (not curl https://kots.io/install)
    • Example push-images and kots install --kotsadm-registry commands with documentation placeholders such as REGISTRY_HOST, RW_USERNAME, and RO_USERNAME
    • Admin Console steps to upload the license and .airgap bundle

The portal generates a command only when every value is something it knows (license, app slug, channel, version, artifact URL). It does not interpolate customer registry hostnames or passwords into generated KOTS air gap commands.

What to customize on the default KOTS page​

Common vendor edits:

  • Branding and product naming: Replace generic wording with your product name and support contact.
  • Admin Console URL: The default air gap procedure uses the port-forward URL (http://localhost:8800 or kubectl kots admin-console). If customers reach the Admin Console through an ingress or load balancer, replace that step with your URL.
  • Registry conventions: Document your registry hostname or host/namespace pattern, account naming, and any required prep (for example, creating the registry namespace before push).
  • Content around <KotsDownloadAssets />: Put your own steps before and after the download component. Pass stepNumber when you want the component to own the numbered step chrome, or wrap it in <InstallStep> and omit stepNumber so your surrounding copy owns the numbering. Do not do both.
  • Online CLI downloads: The default page already mounts <KotsDownloadAssets cliOnly={true} /> on the online/proxy branch. Lead that copy with Preflight and Support Bundle (not curl-dependent). Then cover the fallback. If the customer cannot run curl https://kots.io/install, they download the KOTS CLI, extract it, rename kots to kubectl-kots, put it on PATH, and run the kubectl kots install line from step 2. Do not enable air gap on the license only to get the KOTS CLI. Do not move the air gap <KotsDownloadAssets /> out of <WhenNetwork mode="airgap">. Leave the default KOTS air gap procedure as it is.
<InstallStep stepNumber={1} title="Your network and registry rules">
Harbor project, jump host, support contact, …
</InstallStep>

<InstallStep stepNumber={2} title="Download the installation assets">
<KotsDownloadAssets />
</InstallStep>

<InstallStep stepNumber={3} title="Push Admin Console images">
Your REGISTRY_HOST convention, then the docs-style command.
</InstallStep>

Installer page for kURL​

The default pages/installation/kurl.md page provides downloads for entitled air gap customers. Its frontmatter and toc.yaml entry require both isKurlInstallEnabled and isAirgapSupported.

For generated online or air gap install commands, add <NetworkAvailability installType="kurl" />, <VersionSelector installType="kurl" />, and <KurlInstallAssets />. <KurlInstallAssets /> adapts when Network Availability changes. You can also add a separate <KurlAirgapInstallAssets /> branch. Helm and Embedded Cluster pages use generated install assets the same way.

If you ship generated online kURL commands to online-only customers, drop isAirgapSupported from the page frontmatter visible_when and from the toc.yaml entry. Leave the default kURL page as it is.

If you add <KurlDownloadAssets /> to a page those customers can see, pass cliOnly={true}. They then get the optional CLI tools without the kURL installer tarball or the application air gap bundle.

Default KOTS and kURL upgrade guides​

The default template adds pages/updates/kots.md and pages/updates/kurl.md as children of Instances & Updates. In toc.yaml, give Instances & Updates child items only: an Instances item for pages/updates/instances.md, then the two guides. Do not put both page: and items: on the parent, or KOTS and kURL customers lose a sidebar link to the instance list. The KOTS page and its toc.yaml item use isKotsInstallEnabled. The kURL page and item use isKurlInstallEnabled. Each page uses the same entitlement in its frontmatter and navigation entry so a direct URL cannot bypass the navigation gate.

Do not add isAirgapSupported to the whole-page gate. Each guide wraps only its air gap download-and-upload subsection in \{\{#if entitlements.isAirgapSupported\}\}. Online customers still need the Admin Console procedure, while air gap customers also see how to transfer and upload the application bundle.

The default pages/updates/instances.md connects the panels to these vendor-owned procedures:

<InstancesAndUpdates
kotsGuideHref="/updates/kots"
kurlGuideHref="/updates/kurl"
/>

The default KOTS and kURL guides mount <AdminConsoleCommand /> for the reopen sample. With no namespace prop, KOTS uses the application slug and kURL uses default, which is where install.sh runs kotsadm:

<AdminConsoleCommand installType="kots" lead="Reopen the KOTS Admin Console by running" />

Set kotsNamespace on <InstancesAndUpdates /> and namespace on the matching <AdminConsoleCommand /> only if every customer's Admin Console runs in that namespace. One example is when your own install instructions tell customers to use it. Leave kurlNamespace unset unless you forked install.sh and every kURL customer's Admin Console runs in that namespace. These props do not change the namespace in the portal's KOTS install command. After you set one, the reopen command no longer tells the customer to substitute a different namespace. Vendors whose customers use different namespaces should leave the props unset.

The values must be DNS-1123 labels of at most 63 characters. Invalid namespace values keep the type default. A KOTS override does not change kURL cards, and a kURL override does not change KOTS cards.

<InstancesAndUpdates
kotsGuideHref="/updates/kots"
kurlGuideHref="/updates/kurl"
kotsNamespace="kotsadm"
/>

<AdminConsoleCommand installType="kots" namespace="kotsadm" lead="Reopen the KOTS Admin Console by running" />

Edit the guide pages to describe your Admin Console access, registry, support, and kURL cluster-maintenance requirements. You can point kotsGuideHref or kurlGuideHref to another content route, or remove the prop and page.

The default guides do not include kubectl kots upstream upgrade. Add that command only if every customer uses the same namespace, and include the app slug argument.

The kURL guide separates an application update from kURL/Kubernetes cluster maintenance. The application panel does not render the kURL installer bundle and does not offer install.sh as a command. Document when cluster maintenance has to happen, and provide a separately validated procedure.

Template variables​

Enterprise Portal content supports Mustache-style templating with \{\{ \}\} syntax for dynamic rendering. You can use template variables and MDX components together on the same page.

Available variables​

VariableDescription
\{\{ app.name \}\}Your application name
\{\{ app.slug \}\}URL-friendly app identifier
\{\{ customer.name \}\}Customer's name
\{\{ customer.email \}\}Customer's email
\{\{ customer.id \}\}Customer ID
\{\{ channel.name \}\}Release channel (Stable, Beta, etc.)
\{\{ channel.slug \}\}URL-friendly channel identifier
\{\{ release.version \}\}Newest release on the customer's channel. This is not the docs version the customer selected
\{\{ license.* \}\}Any field from the license object (e.g. \{\{ license.id \}\}, \{\{ license.expiresAt \}\})
\{\{ entitlements.* \}\}Any entitlement value, built-in or custom (see Conditionals)
\{\{ branding.title \}\}Portal title from theme.yaml
\{\{ branding.contact \}\}Support contact from theme.yaml
\{\{ branding.supportPortalLink \}\}Support portal link from theme.yaml
note

To vary content by the docs version the customer selected, use version branches. For more information, see Manage content versions.

Conditionals​

\{\{#if\}\}: Show content when a value is truthy. Supports nesting.

{{#if entitlements.isHAEnabled}}
## High Availability Setup
For production deployments, enable HA mode...
{{/if}}

A value fails this check when it is null, an empty string, false, "false", "0", or 0. Any other value passes.

\{\{#ifEquals\}\}: Show content when a value equals a specific string. Useful for per-customer or per-channel content.

{{#ifEquals channel.name "Stable"}}
You are on the Stable channel. Updates are less frequent but thoroughly tested.
{{/ifEquals}}

{{#ifEquals customer.name "Acme Corp"}}
## Acme-Specific Configuration
Your dedicated endpoint is acme.example.com
{{/ifEquals}}

Quote the comparison value with double or single quotes. Supports nesting.

Entitlements​

Entitlements are accessible as \{\{ entitlements.<name> \}\} for interpolation and \{\{#if entitlements.<name>\}\} for conditionals. There are two kinds:

  • Built-in flags: Set on the license through the Vendor Portal: isHelmInstallEnabled, isAirgapSupported, isEmbeddedClusterDownloadEnabled, isEmbeddedClusterMultiNodeEnabled, isKotsInstallEnabled, isKurlInstallEnabled, isHelmAirgapEnabled
  • Custom entitlements: Any that you define (e.g. isHAEnabled, isEnterpriseEnabled)

Example:

{{#if entitlements.isHelmInstallEnabled}}
## Helm Installation
Follow these steps to install using Helm...
{{/if}}

{{#if entitlements.isHAEnabled}}
## High Availability Setup
For production deployments, enable HA mode...
{{/if}}

Visibility​

Use visible_when to control which customers see which content. Every condition has to match. To keep a page unpublished for every customer, set hidden: true in the page frontmatter. hidden is not a license or entitlement gate. See Hide unpublished pages.

Apply visible_when on any navigation item in toc.yaml:

- title: Enterprise Features
page: pages/enterprise.md
visible_when:
entitlements:
- isEnterpriseEnabled
channel:
include: [Stable, Beta]
exclude: [Internal]
customer_type:
include: [paid]

The server evaluates all three filter types (entitlements, channel, and customer_type). It rejects unrecognized filter dimensions (fail closed).

To hide a page entirely, you can also omit it from toc.yaml. Pages not listed in the table of contents are not reachable through navigation or direct URL. See Table of contents. To keep the page listed in toc.yaml but unpublished, use hidden: true in the page frontmatter instead.

Per-user permissions​

In addition to license entitlements, you can gate content on per-user permissions by referencing them in the entitlements list:

- title: Security Reports
page: pages/security.md
visible_when:
entitlements:
- canViewSecurity

The following permissions are available:

PermissionDescription
canViewSecurityCan view Security Center (CVE reports, SBOMs). Resolves based on the customer's Security Center entitlement.
canInviteUserCan invite users to the portal team
canRemoveUserCan remove users from the portal team
canManageServiceAcctsCan create or revoke service accounts
canUploadBundlesCan upload support bundles

The portal places permissions in the entitlements namespace, so they work in both visible_when conditions and \{\{ entitlements.canViewSecurity \}\} template expressions. canViewSecurity is the most useful permission for content gating, because it follows whether the customer has Security Center. The other four permissions resolve to true for all portal users.

Custom license fields​

In addition to built-in entitlements, you can use your own custom license fields in visible_when conditions. Any custom license field you create in the Vendor Portal is automatically available in the entitlements list. This lets you gate content on a per-customer basis using fields you define.

For example, if you create a boolean custom license field called hasAdvancedReporting:

- title: Advanced Reporting
page: pages/advanced-reporting.md
visible_when:
entitlements:
- hasAdvancedReporting

Only customers whose license has hasAdvancedReporting set to true will see this page. Custom license fields also work in template expressions (\{\{ entitlements.hasAdvancedReporting \}\}).

For information about creating custom license fields, see Manage custom license fields.

License type visibility​

Use customer_type to show or hide content based on the customer's license type. Valid values are community, trial, and paid.

This is useful when you have different content needs for different tiers. For example, you might show upgrade prompts to trial users, or restrict advanced documentation to paid customers only.

# Show only to paid customers
- title: Production Deployment Guide
page: pages/production-deploy.md
visible_when:
customer_type:
include: [paid]

# Show to trial and community customers
- title: Upgrade to Paid
page: pages/upgrade.md
visible_when:
customer_type:
include: [trial, community]

Like channel, customer_type supports both include and exclude lists.

Page-level visibility (frontmatter)​

You can also apply visible_when or hidden: true in a page's YAML frontmatter. visible_when adds a per-page access gate on top of the navigation rules in toc.yaml. hidden: true keeps the page unpublished for every customer.

---
title: Embedded Cluster Installation Requirements
visible_when:
entitlements:
- isEmbeddedClusterDownloadEnabled
---

# Embedded Cluster Installation Requirements

Ensure your environment meets these requirements...

The same entitlements conditions available in toc.yaml work in frontmatter, including built-in entitlements, custom license fields, and per-user permissions. Use this when you want to keep the gating condition on the page itself rather than on its toc.yaml navigation entry.

Frontmatter visible_when is an additional gate, not a replacement for navigation. A page must still be reachable through the navigation (or declared as an overrides target) for a customer to access it directly. A page that is not referenced anywhere in toc.yaml is not accessible, regardless of its frontmatter.

Hide unpublished pages​

hidden controls whether you publish a page, not who can see it. Use visible_when to show a page to some customers and not others based on their license. Use hidden: true to keep a page out of every customer's portal until you are ready to publish it, regardless of license.

Set hidden: true in a page's YAML frontmatter when the page belongs in your content repo but is not ready for customers yet. For example, stage a product announcement, a new install guide, or a revised section with your live docs. Publish it by removing the flag when you are ready. Keep the page listed in toc.yaml while you hide it, so the navigation slot is already in place when you publish. Do not leave the draft in a stray branch or a file with no navigation entry. Local preview hides the page the same as production, so the preview sidebar omits it while hidden is on.

Put hidden on the markdown page, not on toc.yaml.

---
title: Q3 announcement
hidden: true
---

Keep the page listed in toc.yaml as a normal page entry:

- title: Q3 announcement
page: pages/announcements/q3.md

Customers do not see the page until you remove hidden or set it to false, then re-sync the content.

hidden: true marks unpublished content. It is not a license or entitlement gate. visible_when for built-in entitlements, custom license fields, and permissions still works the same way. hidden: true takes precedence over visible_when. Even if the customer would pass visible_when, the page stays unpublished. Entitlements cannot unhide it.

If a table of contents entry has a page with hidden: true, the portal drops that entry and every nested item. Nested items include child pages, nested helm_chart items, and terraform_module items. This matches visible_when on a parent, which also drops the children.

A section that is only a title (no page) cannot use hidden. Set hidden on each child page, or use visible_when on the table of contents entry.

overrides.home cannot restore a hidden page or a child of a hidden parent. To hide the home landing page, set hidden: true on that page.

Omitting a page from toc.yaml still hides it entirely. Use hidden when you want to keep the page in the table of contents and publish it later.

Downloadable assets​

You can distribute files (scripts, checklists, configuration templates, etc.) through Enterprise Portal by committing them to an assets/ directory in your content repo.

Repository structure​

your-content-repo/
├── assets/
│ ├── deploy.sh
│ └── onboarding-checklist.pdf
├── pages/
│ └── resources.md
└── toc.yaml

Any file committed to the assets/ directory is available for download. There are no restrictions on file type or size beyond what your git hosting provider allows (GitHub supports files up to ~100MB through raw content). The portal fetches assets directly from your git repo when a customer clicks a download link, so changes are available as soon as you push.

Linking to assets​

Use the \{\{asset "path"\}\} template tag in your markdown to generate a download link:

## Resources
- [Deployment Script]({{asset "assets/deploy.sh"}})
- [Onboarding Checklist]({{asset "assets/onboarding-checklist.pdf"}})

The tag expands to a URL that authenticates the customer with their session and serves the file directly. Assets are version-aware, so each content branch can have its own set of files.

The path inside the tag is relative to the repo root and must start with assets/.

note

Any asset referenced by an \{\{asset\}\} tag on a page that a customer can see is downloadable by that customer. The visibility of the referencing page controls asset access, not the file path or directory structure. A page with hidden: true does not authorize asset downloads. To limit an asset to specific customers, wrap the asset reference in \{\{#if entitlements.<name>\}\} or \{\{#ifEquals\}\}, or put the asset reference on a page that uses visible_when. Don't rely on \{\{#if\}\} over license, customer, or channel values to restrict a download. See the following example.

Per-customer asset delivery​

To deliver different assets to different customers, combine \{\{asset\}\} with template conditionals. The conditional controls which customers see the download link. With entitlements and ifEquals conditionals, only customers who can see the link can download the file:

## Resources

{{#ifEquals customer.name "Acme Corp"}}
- [Acme Deployment Guide]({{asset "assets/acme-deploy-guide.pdf"}})
- [Acme ArgoCD Values]({{asset "assets/acme-argocd-values.yaml"}})
{{/ifEquals}}

{{#ifEquals customer.name "Globex"}}
- [Globex CloudFormation Template]({{asset "assets/globex-cloudformation.yaml"}})
{{/ifEquals}}

{{#if entitlements.isAWSEnabled}}
- [AWS Deployment Script]({{asset "assets/deploy-aws.sh"}})
{{/if}}

- [Onboarding Checklist]({{asset "assets/onboarding-checklist.pdf"}})

In this example, only Acme Corp can download their deployment guide, and only customers with the isAWSEnabled entitlement can download the AWS script. The onboarding checklist is available to all customers because it is not wrapped in a conditional.

This lets you maintain one content repo with assets for all customers. Each customer only sees the downloads that apply to them. Unconditioned assets (like the onboarding checklist) appear for everyone.

This pattern works for any file type: Terraform modules, Argo manifests, Bicep templates, CloudFormation stacks, bash scripts, PDFs, or configuration templates.