This documentation is also published as Markdown for efficient machine reading: the whole site is indexed at /llms.txt, and every page has a clean Markdown copy under /_llms/. These are generated from the same source and cost far fewer tokens to read than this rendered HTML.

Skip to main content Skip to navigation

TaxonomyContentService Pennington.Taxonomy

Walks every other registered IContentService's ContentRecords, selects those whose Metadata is a TFrontMatter, projects keys via SelectKey or SelectKeys, and exposes the result as the taxonomy's index plus one route per term. Because it reads records rather than re-parsing markdown files, any content service — markdown or custom — participates as long as it projects records of the taxonomy's front-matter type.

The service emits its routes with EndpointSource — the canonical HTML is produced by the sibling MapTaxonomy endpoints, mirroring the pattern documented in how-to/content-services/custom-content-service.md. As a consequence the routes do not appear in sitemap.xml; they do appear in navigation, search, and cross-references through GetContentTocEntriesAsync and GetCrossReferencesAsync.

The service caches its computed term list in an AsyncLazy and subscribes to IFileWatcher so any change anywhere in the watched content tree drops the cache and the next request rebuilds it.

Properties

BaseUrl string
The configured base URL (e.g. /cuisine) — exposed so endpoint mapping can find it.
DefaultSectionLabel string
Default section label applied to discovered items that do not supply one via front matter.
IndexPage Type
The Razor component to render the index page.
IndexUrl string
The fully-resolved index URL with leading and trailing slashes.
SearchPriority int
Relative priority for ordering results in the search index (higher values rank first).
TermPage Type
The Razor component to render each per-term page.

Constructors

TaxonomyContentService

#
public TaxonomyContentService`2(TaxonomyOptions<TFrontMatter, TKey> options, IServiceProvider serviceProvider, IFileWatcher fileWatcher, TimeProvider clock = null)

Creates the service and subscribes to file-change notifications for hot reload.

Parameters

options TaxonomyOptions<TFrontMatter, TKey>
serviceProvider IServiceProvider
fileWatcher IFileWatcher
clock TimeProvider

Methods

DiscoverAsync

#
public IAsyncEnumerable<DiscoveredItem> DiscoverAsync()

Discover all content items this service is responsible for.

Returns

IAsyncEnumerable<DiscoveredItem>

GetContentTocEntriesAsync

#
public Task<ImmutableList<ContentTocItem>> GetContentTocEntriesAsync()

Navigation entries for table of contents.

Returns

Task<ImmutableList<ContentTocItem>>

GetContentToCopyAsync

#
public Task<ImmutableList<ContentToCopy>> GetContentToCopyAsync()

Static files to copy to output (images, downloads, etc.)

Returns

Task<ImmutableList<ContentToCopy>>

GetCrossReferencesAsync

#
public Task<ImmutableList<CrossReference>> GetCrossReferencesAsync()

Cross-references for xref resolution.

Returns

Task<ImmutableList<CrossReference>>

GetRecordsAsync

#
public IAsyncEnumerable<ContentRecord> GetRecordsAsync()

Projects this service's routable content as ContentRecords — the discovery seam consumed by taxonomy, search faceting, and structured-data emission.

Default: bridges from DiscoverAsync, yielding one record per discovered item that carries Metadata and is neither a RedirectSource (transport, not content) nor an LlmsOnlySource (no human-facing URL). A service that attaches typed metadata to its discovered items — as MarkdownContentService does — therefore participates with no extra code. Override only to project records that do not flow through DiscoverAsync, or to suppress records entirely.

A service that emits routable content from DiscoverAsync but leaves Metadata unset projects no records, and so silently sits out of taxonomy, search faceting, and structured data. Set the metadata (or override this) to opt in.

Returns

IAsyncEnumerable<ContentRecord>

GetTermsAsync

#
public Task<ImmutableList<TaxonomyTerm<TFrontMatter, TKey>>> GetTermsAsync()

Returns the cached term list, computing it on first access. Used both by the discovery pipeline and by the live HTTP endpoints.

Returns

Task<ImmutableList<TaxonomyTerm<TFrontMatter, TKey>>>

TermUrl

#
public string TermUrl(string slug)

Builds the per-term URL for the given slug.

Parameters

slug string

Returns

string

TryGetTermAsync

#
public Task<TaxonomyTerm<TFrontMatter, TKey>> TryGetTermAsync(string slug)

Looks up a single term by its slug. Returns null when not found.

Parameters

slug string

Returns

Task<TaxonomyTerm<TFrontMatter, TKey>>

Pennington.Taxonomy.TaxonomyContentService

namespace Pennington.Taxonomy;

/// Walks every other registered IContentService's ContentRecords, selects those whose Metadata is a TFrontMatter, projects keys via SelectKey or SelectKeys, and exposes the result as the taxonomy's index plus one route per term. Because it reads records rather than re-parsing markdown files, any content service — markdown or custom — participates as long as it projects records of the taxonomy's front-matter type. The service emits its routes with EndpointSource — the canonical HTML is produced by the sibling MapTaxonomy endpoints, mirroring the pattern documented in how-to/content-services/custom-content-service.md. As a consequence the routes do not appear in sitemap.xml; they do appear in navigation, search, and cross-references through GetContentTocEntriesAsync and GetCrossReferencesAsync.The service caches its computed term list in an AsyncLazy and subscribes to IFileWatcher so any change anywhere in the watched content tree drops the cache and the next request rebuilds it.
public class TaxonomyContentService
{
    /// The configured base URL (e.g. /cuisine) — exposed so endpoint mapping can find it.
    
public string BaseUrl { get; }
/// Default section label applied to discovered items that do not supply one via front matter.
public string DefaultSectionLabel { get; }
/// Discover all content items this service is responsible for.
public IAsyncEnumerable<DiscoveredItem> DiscoverAsync()
; /// Navigation entries for table of contents.
public Task<ImmutableList<ContentTocItem>> GetContentTocEntriesAsync()
; /// Static files to copy to output (images, downloads, etc.)
public Task<ImmutableList<ContentToCopy>> GetContentToCopyAsync()
; /// Cross-references for xref resolution.
public Task<ImmutableList<CrossReference>> GetCrossReferencesAsync()
; /// Projects this service's routable content as ContentRecords — the discovery seam consumed by taxonomy, search faceting, and structured-data emission. Default: bridges from DiscoverAsync, yielding one record per discovered item that carries Metadata and is neither a RedirectSource (transport, not content) nor an LlmsOnlySource (no human-facing URL). A service that attaches typed metadata to its discovered items — as MarkdownContentService does — therefore participates with no extra code. Override only to project records that do not flow through DiscoverAsync, or to suppress records entirely.A service that emits routable content from DiscoverAsync but leaves Metadata unset projects no records, and so silently sits out of taxonomy, search faceting, and structured data. Set the metadata (or override this) to opt in.
public IAsyncEnumerable<ContentRecord> GetRecordsAsync()
; /// Returns the cached term list, computing it on first access. Used both by the discovery pipeline and by the live HTTP endpoints.
public Task<ImmutableList<TaxonomyTerm<TFrontMatter, TKey>>> GetTermsAsync()
; /// The Razor component to render the index page.
public Type IndexPage { get; }
/// The fully-resolved index URL with leading and trailing slashes.
public string IndexUrl { get; }
/// Relative priority for ordering results in the search index (higher values rank first).
public int SearchPriority { get; }
/// Creates the service and subscribes to file-change notifications for hot reload.
public TaxonomyContentService`2(TaxonomyOptions<TFrontMatter, TKey> options, IServiceProvider serviceProvider, IFileWatcher fileWatcher, TimeProvider clock = null)
; /// The Razor component to render each per-term page.
public Type TermPage { get; }
/// Builds the per-term URL for the given slug.
public string TermUrl(string slug)
; /// Looks up a single term by its slug. Returns null when not found.
public Task<TaxonomyTerm<TFrontMatter, TKey>> TryGetTermAsync(string slug)
; }