The developer story as typed data: the profile plus every portfolio entry, materialised from a finished build token.
This is the seam the views stand on — timeline, story pages, and the
CV all consume %Portfolio{}, never raw documents, so the shape of
an entry is a named struct with real fields, not a frontmatter map.
Summary
Functions
Every entry across collections, for taxonomy and freshness scans.
True when the document belongs to a portfolio collection.
The portfolio narrowed to entries carrying one tag.
Builds the typed portfolio from a build token; entries come out newest-first within their collection.
True when the site carries any portfolio content at all.
Every tag used by any portfolio entry, sorted.
Types
@type t() :: %Cherry.Portfolio{ education: [Cherry.Portfolio.Education.t()], oss: [Cherry.Portfolio.OpenSource.t()], positions: [Cherry.Portfolio.Position.t()], profile: Cherry.Portfolio.Profile.t() | nil, projects: [Cherry.Portfolio.Project.t()], talks: [Cherry.Portfolio.Talk.t()] }
Functions
Every entry across collections, for taxonomy and freshness scans.
@spec entry_document?(Cherry.Content.Document.t()) :: boolean()
True when the document belongs to a portfolio collection.
The portfolio narrowed to entries carrying one tag.
@spec from_build(Cherry.Build.t()) :: t()
Builds the typed portfolio from a build token; entries come out newest-first within their collection.
True when the site carries any portfolio content at all.
Every tag used by any portfolio entry, sorted.