Current section
Files
Jump to
Current section
Files
lib/seo/llms/entry.ex
defmodule SEO.LLMs.Entry do
@moduledoc """
Represents a single resource entry in an llms.txt file.
Each entry belongs to a section and has a title, URL, optional description,
and optional markdown content (for serving the resource as markdown).
## Fields
- `:section` — which H2 section this entry belongs to (e.g., `"Docs"`, `"Articles"`, `"Optional"`)
- `:title` — the link text
- `:url` — the link target URL
- `:description` — optional text after the link in llms.txt
- `:content` — optional markdown body for serving the page as markdown.
Can be a string or a zero-arity function for lazy loading.
"""
defstruct [:section, :title, :url, :description, :content]
@type t :: %__MODULE__{
section: String.t() | nil,
title: String.t() | nil,
url: String.t() | nil,
description: String.t() | nil,
content: String.t() | (-> String.t()) | nil
}
@doc """
Build an Entry struct from attributes, optionally merging with defaults.
"""
@spec build(SEO.attrs(), SEO.config()) :: t() | nil
def build(attrs, default \\ nil) do
SEO.Utils.merge_defaults(__MODULE__, attrs, default)
end
@doc """
Group a list of entries by their `:section` field into the tuple format
that `SEO.LLMs.render/1` expects.
Returns a list of `{section_name, entries}` tuples where entries are
`{title, url}` or `{title, url, description}` tuples.
## Example
entries = [
%SEO.LLMs.Entry{section: "Docs", title: "API", url: "/api"},
%SEO.LLMs.Entry{section: "Docs", title: "Guide", url: "/guide", description: "Getting started"},
%SEO.LLMs.Entry{section: "Optional", title: "FAQ", url: "/faq"}
]
SEO.LLMs.Entry.group_by_section(entries)
#=> [{"Docs", [{"API", "/api"}, {"Guide", "/guide", "Getting started"}]},
#=> {"Optional", [{"FAQ", "/faq"}]}]
"""
@spec group_by_section([t()]) :: [SEO.LLMs.Provider.section()]
def group_by_section(entries) do
entries
|> Enum.reject(&is_nil/1)
|> Enum.group_by(& &1.section)
|> Enum.map(fn {section, section_entries} ->
{section, Enum.map(section_entries, &to_link/1)}
end)
end
defp to_link(%{title: t, url: u, description: nil}), do: {t, u}
defp to_link(%{title: t, url: u, description: d}), do: {t, u, d}
end