Content
latent_space.services.content
¶
ContentLoadError
¶
Bases: RuntimeError
Raised when authored content on disk is malformed, invalid, or ambiguous.
Loading raises rather than skipping a bad file so a missing required field or a duplicate public identifier fails the process at load time instead of silently serving partial or wrong content (CLAUDE.md content conventions).
ContentService
¶
Read-only, in-memory view of validated site content.
Constructed once from already-loaded projects and chat entries: it excludes drafts, orders the survivors deterministically, and pre-renders project bodies and chat answers to sanitized HTML. Rendering up front keeps request handlers thin and makes any rendering failure surface at load time. Each accessor returns a fresh list of frozen response models, so callers can neither reorder the result nor mutate the cached content.
from_content_root(content_root)
classmethod
¶
Load, validate, and build the service from a content root directory.
published_project_detail(public_identifier)
¶
Return the published project with public_identifier, or None if there is none.
Drafts are absent from the index, so a draft public identifier also returns None.
load_chat_entries_from_directory(directory)
¶
Load and validate every chat-entry file in directory.
Each entry's public identifier is its filename stem, exactly as for projects (see
_public_identifier_from_filename).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
directory
|
Path
|
Directory scanned for chat-entry Markdown files. |
required |
Returns:
| Type | Description |
|---|---|
list[ChatEntry]
|
The validated chat entries, including drafts; an empty list when the |
list[ChatEntry]
|
directory does not exist. |
Raises:
| Type | Description |
|---|---|
ContentLoadError
|
On a malformed file, a schema validation failure, or a
frontmatter that declares its own |
load_posts_from_directory(directory)
¶
Load and validate every post file in directory.
A post is a link to writing published elsewhere: frontmatter metadata only. Any
Markdown body is ignored, since the canonical text lives at the post's external_url.
Each post's public identifier is its filename stem (see
_public_identifier_from_filename).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
directory
|
Path
|
Directory scanned for post Markdown files. |
required |
Returns:
| Type | Description |
|---|---|
list[Post]
|
The validated posts, including drafts; an empty list when the directory does not |
list[Post]
|
exist, since absent content is not an error. |
Raises:
| Type | Description |
|---|---|
ContentLoadError
|
On a malformed file, a schema validation failure, or a
frontmatter that declares its own |
load_projects_from_directory(directory)
¶
Load and validate every project file in directory.
Each project's public identifier is its filename stem (see _public_identifier_from_filename).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
directory
|
Path
|
Directory scanned for project Markdown files. |
required |
Returns:
| Type | Description |
|---|---|
list[Project]
|
The validated projects, including drafts; an empty list when the |
list[Project]
|
directory does not exist, since absent content is not an error. |
Raises:
| Type | Description |
|---|---|
ContentLoadError
|
On a malformed file, a schema validation failure, or a
frontmatter that declares its own |
parse_frontmatter_document(text)
¶
Split a Markdown-with-frontmatter document into metadata and body.
The document must open with a --- line, hold a YAML mapping, close the
block with another --- line, and then contain the Markdown body.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
text
|
str
|
Full document text, opening with a |
required |
Returns:
| Type | Description |
|---|---|
dict[str, object]
|
The parsed frontmatter mapping and the body text with surrounding |
str
|
whitespace stripped. |
Raises:
| Type | Description |
|---|---|
ContentLoadError
|
If the leading frontmatter block is missing, is not
terminated by a closing |
sort_chat_entries(entries)
¶
Order chat entries by ascending order, ties broken by ascending public_identifier.
sort_posts_newest_first(posts)
¶
Order posts for display, most recently published first.
Same ranking as projects: descending published_at, ties broken by ascending
public_identifier, so the order is total and independent of filesystem iteration
order.
sort_projects_newest_first(projects)
¶
Order projects for display, most recently published first.
Ranking rule: descending published_at; ties are broken by ascending public_identifier
so the ordering is total and independent of filesystem iteration order.
Implemented as a stable sort by public identifier followed by a stable reverse sort by
date, which leaves same-date projects in ascending-public-identifier order.