Skip to content

CTA: register default templates on docset.yml and toc.yml - #3716

Open
bmorelli25 wants to merge 4 commits into
mainfrom
cta-paths
Open

CTA: register default templates on docset.yml and toc.yml#3716
bmorelli25 wants to merge 4 commits into
mainfrom
cta-paths

Conversation

@bmorelli25

@bmorelli25 bmorelli25 commented Jul 23, 2026

Copy link
Copy Markdown
Member

Background

The right-gutter CTA card can now be customized per page via cta frontmatter (see #3602).

Why is something more needed?

elastic/docs-content-internal#1475 requests adding a custom "Get started free" CTA and onboarding_token to all solution-specific pages under solutions/observability/, solutions/security/, and solutions/search. Doing this in frontmatter alone means editing ~600 files. Over time as new pages are added, folks will inevitably forget the frontmatter and we'll end up with an inconsistent mix of CTAs.

The proposed solution

Register a default CTA on the navigation file that owns a section. Templates still live in docset.yml; default_cta on docset.yml or a nested toc.yml selects which template applies to every page listed in that file.

# docset.yml
cta:
  observability:
    button:
      label: Get started free
      url: https://cloud.elastic.co/serverless-registration?onboarding_token=observability
toc:
  - toc: solutions/observability
# solutions/observability/toc.yml
default_cta: observability
toc:
  - file: index.md
  - file: apps/apm.md

Resolution order for a page:

  1. An explicit, known cta frontmatter id (unchanged, always wins)
  2. The default_cta registered for the page via its navigation file
  3. The built-in trial default

This makes the docs-content side of #1475 a small change across docset.yml plus a few section toc.yml files. Pages that already carry cta frontmatter (e.g. the monitor-kubernetes / monitor-aws pages from elastic/docs-content#7135) keep their more specific CTA automatically.

Details: inheritance, edge cases, and one behavior change
  • Navigation ownership. Defaults follow the nav tree, not URL path prefixes. New pages added to a section's toc.yml pick up its default_cta automatically.
  • Nested overrides. A nested toc.yml can set its own default_cta; pages under it use that value instead of the parent navigation file's default.
  • Conflicts are build errors. The same page registered with two different defaults, or a default_cta that doesn't match a template in docset.yml, fails the build rather than resolving silently.
  • Behavior change for unknown frontmatter ids. Previously an unknown cta id warned and fell back straight to the default trial card. It still warns, but is now ignored, so a navigation default covering the page applies instead. The section CTA is more relevant than the generic card, and the warning still points at the typo.
  • Isolated builds. A navigation-registered default resolves to a named, non-default template, so it renders in isolated builds too (same as explicit frontmatter) — contributors can preview it. The built-in default remains assembler-only.

Docs for the new key are added to docs/configure/content-set/cta.md and docs/configure/content-set/navigation.md.

Test plan

  • 8 unit tests in ConfigurationFileCtaTests covering precedence, nested toc overrides, docset-level defaults, unknown template errors, and duplicate registration errors
  • Manually verify a docset with default_cta on a section toc.yml renders the scoped CTA on pages in that nav file and the default elsewhere

Docsets can now apply a right-gutter CTA template to an entire path
subtree by listing docset-relative prefixes under a template's 'paths'
key, instead of adding 'cta' frontmatter to every page. Resolution
order: explicit frontmatter id, then the longest matching path prefix,
then the built-in trial default. An unknown frontmatter id warns and is
ignored so path scopes still apply. A path claimed by two templates is
a build error.

Co-authored-by: Cursor <cursoragent@cursor.com>
@bmorelli25

Copy link
Copy Markdown
Member Author

@elastic/docs-engineering I have this proposal for you. If it's too far from your vision LMK and we can close this.

@Mpdreamz

Copy link
Copy Markdown
Member

drive by comment, would registering the default cta in toc.yml suffice?

@bmorelli25 bmorelli25 changed the title CTA: allow scoping templates to path subtrees via paths CTA: register default templates on docset.yml and toc.yml Aug 6, 2026
bmorelli25 and others added 2 commits August 6, 2026 14:34
Replace cta.<name>.paths in docset.yml with default_cta on docset.yml and nested toc.yml so section owners register defaults alongside their nav trees.

Co-authored-by: Cursor <cursoragent@cursor.com>
Resolve docs conflict: navigation reference moved to docs/documentation/isolated/configure/index.md; port default_cta docs there and drop deleted configure/content-set/navigation.md.

Co-authored-by: Cursor <cursoragent@cursor.com>
@bmorelli25

Copy link
Copy Markdown
Member Author

I've realigned this PR with your suggestion 👍

@Mpdreamz Mpdreamz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left this open a long time sorry @bmorelli25 !

One nit.

/// <param name="relativePath">The page's docset-root-relative source path, used for toc default lookup.</param>
/// <param name="warning">Set when <paramref name="id"/> is unknown, so the caller can report it.</param>
public Cta ResolveCta(string? id, out string? warning)
public Cta ResolveCta(string? id, string? relativePath, out string? warning)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks mostly good to me, mind writing out Cta fully e.g the return type being CallToAction in c#, using the abbreviation in config files is good though.

Cta is a pre-existing type but nice to clean up now, then all methods and variables become e.g ResolveCallToAction, the property CallToActions not Ctas.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — renamed the Cta record to CallToAction, the Ctas property to CallToActions, ResolveCta to ResolveCallToAction, and ValidateCta to ValidateCallToAction across all C# source files, Razor templates, and tests. The cta abbreviation is preserved in YAML config keys (default_cta, the cta: map in docset.yml) as you suggested.

@Mpdreamz

Copy link
Copy Markdown
Member

@copilot resolve the merge conflicts in this pull request

Co-authored-by: Mpdreamz <245275+Mpdreamz@users.noreply.github.com>

Copilot AI commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

Merge conflicts are already resolved in the branch (commit f82d151 is a merge commit bringing in main). The branch is clean and up to date.

Copilot AI requested a review from Mpdreamz August 31, 2026 16:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants