Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions docs/_docset.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ cross_links:
exclude:
- '_*.md'
- '!_search.md'
# API landing templates (see api.*.template): not standalone TOC pages; including them causes "Could not find … in navigation" during serve/build.
- '*-api-overview.md'
subs:
a-global-variable: "This was defined in docset.yml"
serverless-short: Serverless
Expand Down Expand Up @@ -51,8 +49,8 @@ suppress:
api:
elasticsearch: elasticsearch-openapi.json
kibana:
spec: kibana-openapi.json
template: kibana-api-overview.md
- file: kibana-api-overview.md
- spec: kibana-openapi.json
dashboard: dashboard-openapi.json

toc:
Expand Down
55 changes: 39 additions & 16 deletions docs/configure/content-set/api-explorer.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,37 +27,60 @@ Each product key produces its own section of API documentation. For example, `el

The `api` key is only valid in `docset.yml`. You can't use it in `toc.yml` files.

### Advanced configuration with templates
### Advanced configuration with intro and outro pages

When you specify a `template` file, `docs-builder` uses your custom Markdown file as the API landing page instead of generating an automatic overview:
You can add custom Markdown content before and after the auto-generated API documentation using a sequence format:

```yaml
api:
kibana:
spec: kibana-openapi.json
template: kibana-api-overview.md
- file: kibana-intro.md
- spec: kibana-openapi.json
- file: kibana-additional-notes.md
```

Template files:
This configuration creates a navigation structure where:

- Must be Markdown files with `.md` extension
- Can use standard Markdown, substitutions
1. **Intro pages** (before the first `spec`) appear at the top of the sidebar
2. **Generated API content** (operations, tags, types) appears in the middle
3. **Outro pages** (after the spec) appear at the bottom

:::{note}
They must be explicitly excluded if they are not used in your table of contents.
Otherwise `docs-builder` treats them like normal pages and navigation can fail at build or serve time.
Add a glob (or explicit paths) under `exclude:` in `docset.yml` that matches your template filenames.
For example, exclude `*-api-overview.md`.
:::
#### Intro and outro page features:

#### Template example
- **Full Myst support**: Intro/outro pages support the full range of Myst Markdown features including cross-links, substitutions, and directives
- **Automatic exclusion**: No need to add intro/outro files to the `exclude:` list - they're automatically excluded from normal HTML generation
- **URL collision detection**: Build fails if intro/outro page names conflict with reserved API Explorer segments (`types/`, `tags/`) or operation names

Here's a sample template file (`kibana-api-overview.md`):
#### Multiple intro/outro pages

You can include multiple intro and outro pages:

```yaml
api:
kibana:
- file: introduction.md
- file: getting-started.md
- spec: kibana-openapi.json
- file: examples.md
- file: troubleshooting.md
```

#### Sample intro page

Here's a sample intro page (`kibana-intro.md`):

```markdown
# Kibana APIs

Welcome to the Kibana API documentation.
Welcome to the Kibana API documentation. These APIs allow you to manage Kibana programmatically.

## Before you begin

Make sure you have:

- A running Kibana instance
- Valid authentication credentials
- Understanding of RESTful API principles
```
Comment thread
lcawl marked this conversation as resolved.

## Place your spec files
Expand Down
23 changes: 20 additions & 3 deletions docs/configure/content-set/navigation.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,17 +96,34 @@ exclude:

### `api`

Maps product names to OpenAPI specification files to enable the [API Explorer](api-explorer.md). Paths are relative to the folder containing `docset.yml`. Only valid in `docset.yml`, not in `toc.yml` files.
Configures API Explorer sections for your content set using OpenAPI specification files and optional intro/outro pages. Paths are relative to the folder containing `docset.yml`. Only valid in `docset.yml`, not in `toc.yml` files.

#### Basic configuration

```yaml
api:
elasticsearch: elasticsearch-openapi.json
kibana: kibana-openapi.json
```

Each key becomes a sub-path of the generated API docs: `elasticsearch` → `/api/elasticsearch/`, `kibana` → `/api/kibana/`.
#### Advanced configuration with intro/outro pages

```yaml
api:
kibana:
- file: kibana-intro.md
- spec: kibana-openapi.json
- file: kibana-outro.md
```

Each product key becomes a sub-path of the generated API docs: `elasticsearch` → `/api/elasticsearch/`, `kibana` → `/api/kibana/`.

The sequence format allows you to add custom Markdown content:
- **Intro pages** (before the first `spec`) appear at the top of the API navigation
- **Generated content** (operations, tags, types) appears in the middle
- **Outro pages** (after specs) appear at the bottom

See [API Explorer](api-explorer.md) for full configuration details.
See [API Explorer](api-explorer.md) for full configuration details and examples.

### `toc`

Expand Down
9 changes: 4 additions & 5 deletions docs/kibana-api-overview.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# Kibana APIs

Welcome to the Kibana API documentation. This page provides an overview of the available Kibana APIs.

## Kibana spaces
---
navigation_title: Spaces
---
# Kibana spaces

Spaces enable you to organize your dashboards and other saved objects into meaningful categories.
You can use the default space or create your own spaces.
Expand Down
2 changes: 0 additions & 2 deletions src/Elastic.ApiExplorer/ApiRenderContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,4 @@ StaticFileContentHashProvider StaticFileContentHashProvider
public required INavigationItem CurrentNavigation { get; init; }
public required IMarkdownStringRenderer MarkdownRenderer { get; init; }

/// <summary>When set, the API root index uses this model instead of <see cref="Landing.ApiLanding"/>.</summary>
public TemplateLanding? TemplateLandingPage { get; init; }
}
12 changes: 11 additions & 1 deletion src/Elastic.ApiExplorer/ApiViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ public HtmlString RenderMarkdown(string? markdown)

protected virtual IReadOnlyList<ApiTocItem> GetTocItems() => [];

/// <summary>When set, drives <see cref="GlobalLayoutViewModel.Title"/> for this page (e.g. intro/outro markdown). Does not affect <see cref="GlobalLayoutViewModel.HeaderTitle"/> which stays as the API product name.</summary>
protected virtual string? LayoutPageTitle => null;

private string? GetGitHubDocsUrl()
{
var repo = BuildContext.Git.RepositoryName;
Expand All @@ -61,11 +64,18 @@ public HtmlString RenderMarkdown(string? markdown)
public ApiLayoutViewModel CreateGlobalLayoutModel()
{
var rootPath = BuildContext.SiteRootPath ?? GetDefaultRootPath(BuildContext.UrlPathPrefix);
var docTitle = Document.Info?.Title ?? "API Documentation";
var pageTitle = LayoutPageTitle;
var documentTitle = pageTitle is not null
? $"{pageTitle} | {docTitle}"
: docTitle;

return new()
{
DocsBuilderVersion = ShortId.Create(BuildContext.Version),
DocSetName = "Api Explorer",
Description = "",
Title = documentTitle,
CurrentNavigationItem = CurrentNavigationItem,
Previous = null,
Next = null,
Expand All @@ -81,7 +91,7 @@ public ApiLayoutViewModel CreateGlobalLayoutModel()
BuildType = BuildContext.BuildType,
TocItems = GetTocItems(),
// Header properties for isolated mode
HeaderTitle = Document.Info?.Title ?? "API Documentation",
HeaderTitle = docTitle,
HeaderVersion = Document.Info?.Version ?? "1.0",
GitBranch = BuildContext.Git.Branch != "unavailable" ? BuildContext.Git.Branch : null,
GitCommitShort = BuildContext.Git.Ref is { Length: >= 7 } r && r != "unavailable" ? r[..7] : null,
Expand Down
8 changes: 8 additions & 0 deletions src/Elastic.ApiExplorer/Landing/LandingView.cshtml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@inherits RazorSliceHttpResult<Elastic.ApiExplorer.Landing.LandingViewModel>
@using Elastic.ApiExplorer
@using Elastic.ApiExplorer.Landing
@using Elastic.ApiExplorer.Operations
@using Elastic.ApiExplorer.Schemas
Expand Down Expand Up @@ -85,6 +86,13 @@
<td><code>@schemaItem.Model.SchemaId</code></td>
</tr>
}
else if (navigationItem is SimpleMarkdownNavigationItem markdownPage)
{
<tr>
<td class="api-name"><a href="@markdownPage.Url">@(markdownPage.NavigationTitle)</a></td>
<td>Additional documentation</td>
</tr>
}
else
{
throw new Exception($"Unexpected type: {navigationItem.GetType().FullName}");
Expand Down
10 changes: 10 additions & 0 deletions src/Elastic.ApiExplorer/Landing/MarkdownPageView.cshtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@inherits RazorSliceHttpResult<Elastic.ApiExplorer.Landing.MarkdownPageViewModel>
@using Elastic.ApiExplorer
@using Elastic.ApiExplorer.Landing
@implements IUsesLayout<Elastic.ApiExplorer._Layout, ApiLayoutViewModel>
@functions {
public ApiLayoutViewModel LayoutModel => Model.CreateGlobalLayoutModel();
}
<section id="elastic-docs-v3">
@Model.BodyHtml
</section>
20 changes: 20 additions & 0 deletions src/Elastic.ApiExplorer/Landing/MarkdownPageViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Licensed to Elasticsearch B.V under one or more agreements.
// Elasticsearch B.V licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information

using Microsoft.AspNetCore.Html;

namespace Elastic.ApiExplorer.Landing;

/// <summary>
/// View model for intro/outro markdown pages in the API Explorer layout.
/// </summary>
public class MarkdownPageViewModel(ApiRenderContext context) : ApiViewModel(context)
{
public required string PageTitle { get; init; }

public required HtmlString BodyHtml { get; init; }

/// <inheritdoc />
protected override string? LayoutPageTitle => PageTitle;
}
39 changes: 0 additions & 39 deletions src/Elastic.ApiExplorer/Landing/TemplateLanding.cs

This file was deleted.

21 changes: 0 additions & 21 deletions src/Elastic.ApiExplorer/Landing/TemplateLandingView.cshtml

This file was deleted.

28 changes: 0 additions & 28 deletions src/Elastic.ApiExplorer/Landing/TemplateLandingViewModel.cs

This file was deleted.

Loading
Loading