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

IContentService Pennington.Content

Discovers and provides content for the pipeline.

Properties

DefaultSectionLabel string
Default section label applied to discovered items that do not supply one via front matter.
SearchPriority int
Relative priority for ordering results in the search index (higher values rank first).

Methods

DiscoverAsync

#
public IAsyncEnumerable<DiscoveredItem> DiscoverAsync()

Discover all content items this service is responsible for.

Returns

IAsyncEnumerable<DiscoveredItem>

GetAffectedRoutes

#
public ContentChangeImpact GetAffectedRoutes(FileChangeNotification change)

Maps a file-change notification to the set of routes this service projects from that file, without mutating any cached state. Consulted by file-watched caches (SiteProjection, BuildHtmlCache) to invalidate only the affected entries instead of clearing wholesale. Default: None.

Parameters

change FileChangeNotification

Returns

ContentChangeImpact

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>>

GetIndexableEntriesAsync

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

Entries that should appear in the search index and llms.txt.

Default: returns GetContentTocEntriesAsync. That is correct when "shown in navigation" ≡ "discoverable via search" — the default holds for markdown, because MarkdownContentService's TOC entries already honor search: and llms: front-matter fields via ExcludeFromSearch / ExcludeFromLlms.

Override when the two sets diverge — for example, RazorPageContentService emits sidecar-less pages here (so users can search for them) without adding them to navigation (which would clutter the TOC with auto-titled entries).

Implementors of custom content services that build ContentTocItems directly: set ExcludeFromSearch and ExcludeFromLlms from your metadata's Search / Llms flags, or per-page opt-outs will be silently ignored.

Returns

Task<ImmutableList<ContentTocItem>>

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>

GetRedirectSourcesAsync

#
public Task<ImmutableList<DiscoveredItem>> GetRedirectSourcesAsync()

Redirect sources this service emits (each item's Source is a RedirectSource). Consumed by RedirectContentService to build the unified redirect map without iterating every service's DiscoverAsync — which would force services that have no redirects to pay the full cost of discovery just to return nothing. Default: empty. Services backed by front-matter records that implement IRedirectable override this.

Returns

Task<ImmutableList<DiscoveredItem>>

ParseContentAsync

#
public IAsyncEnumerable<ParsedItem> ParseContentAsync()

Discovers and parses this service's content with the service's own front-matter type, yielding ParsedItems (typed metadata + body). Consumers like LlmsTxtService use this instead of re-parsing with a foreign parser, which would mis-flag valid keys from other content types. Default: empty — services whose content is sourced elsewhere (Razor/API pages fetched as rendered HTML) opt out.

Returns

IAsyncEnumerable<ParsedItem>

Pennington.Content.IContentService

namespace Pennington.Content;

/// Discovers and provides content for the pipeline.
public interface IContentService
{
    /// 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()
; /// Maps a file-change notification to the set of routes this service projects from that file, without mutating any cached state. Consulted by file-watched caches (SiteProjection, BuildHtmlCache) to invalidate only the affected entries instead of clearing wholesale. Default: None.
public ContentChangeImpact GetAffectedRoutes(FileChangeNotification change)
; /// 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()
; /// Entries that should appear in the search index and llms.txt. Default: returns GetContentTocEntriesAsync. That is correct when "shown in navigation" ≡ "discoverable via search" — the default holds for markdown, because MarkdownContentService's TOC entries already honor search: and llms: front-matter fields via ExcludeFromSearch / ExcludeFromLlms.Override when the two sets diverge — for example, RazorPageContentService emits sidecar-less pages here (so users can search for them) without adding them to navigation (which would clutter the TOC with auto-titled entries).Implementors of custom content services that build ContentTocItems directly: set ExcludeFromSearch and ExcludeFromLlms from your metadata's Search / Llms flags, or per-page opt-outs will be silently ignored.
public Task<ImmutableList<ContentTocItem>> GetIndexableEntriesAsync()
; /// 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()
; /// Redirect sources this service emits (each item's Source is a RedirectSource). Consumed by RedirectContentService to build the unified redirect map without iterating every service's DiscoverAsync — which would force services that have no redirects to pay the full cost of discovery just to return nothing. Default: empty. Services backed by front-matter records that implement IRedirectable override this.
public Task<ImmutableList<DiscoveredItem>> GetRedirectSourcesAsync()
; /// Discovers and parses this service's content with the service's own front-matter type, yielding ParsedItems (typed metadata + body). Consumers like LlmsTxtService use this instead of re-parsing with a foreign parser, which would mis-flag valid keys from other content types. Default: empty — services whose content is sourced elsewhere (Razor/API pages fetched as rendered HTML) opt out.
public IAsyncEnumerable<ParsedItem> ParseContentAsync()
; /// Relative priority for ordering results in the search index (higher values rank first).
public int SearchPriority { get; }
}