# `PhoenixKit.Modules.Sitemap.Sources.Source`
[🔗](https://github.com/BeamLabEU/phoenix_kit/blob/v2.15.1/lib/modules/sitemap/sources/source.ex#L1)

Behaviour for sitemap data sources.

Each source module must implement this behaviour to provide URL entries
for sitemap generation.

## Required Callbacks

- `source_name/0` - Unique atom identifier for the source
- `enabled?/0` - Whether this source is active
- `collect/1` - Collect URL entries from this source

## Optional Callbacks

- `sitemap_filename/0` - Custom filename for the module's sitemap file
- `sub_sitemaps/1` - Split into multiple sub-sitemap files (e.g., per-blog, per-entity-type)
- `sitemap_settings_schema/0` - Declare source-specific settings for the admin UI

# `settings_field`

```elixir
@type settings_field() :: %{
  key: String.t(),
  type: :boolean | :string | :integer,
  label: String.t(),
  help: String.t() | nil,
  default: term()
}
```

Describes one source-specific setting for the admin settings UI.

- `key` - the `PhoenixKit.Settings` key this field reads/writes
- `type` - controls both the input widget and how the stored string is
  parsed (`:boolean` -> toggle, `:string` -> text input, `:integer` -> number input)
- `label` - field label shown to the admin
- `help` - optional helper text shown below the label
- `default` - value used when the setting has never been saved

# `collect`

```elixir
@callback collect(opts :: keyword()) :: [PhoenixKit.Modules.Sitemap.UrlEntry.t()]
```

Collects all URL entries from this source.

# `enabled?`

```elixir
@callback enabled?() :: boolean()
```

Checks if this source is enabled and should be included in sitemap.

# `sitemap_filename`
*optional* 

```elixir
@callback sitemap_filename() :: String.t()
```

Returns the base filename for this source's sitemap file (without .xml extension).

Default: `"sitemap-#{source_name()}"`

# `sitemap_settings_schema`
*optional* 

```elixir
@callback sitemap_settings_schema() :: [settings_field()]
```

Declares source-specific settings for the sitemap admin settings page.

Optional. A source that implements this returns a list of field
descriptors; the settings page renders one input per field (grouped
under the source's name), reads/writes each through `PhoenixKit.Settings`
using its `key` and `default`, and invalidates the sitemap cache on save
— the same way the page's built-in settings work.

Only add this for settings that don't already have a UI. Don't
reimplement fields the core sitemap settings page already exposes (e.g.
the built-in `sitemap_include_*` toggles).

## Example

    def sitemap_settings_schema do
      [
        %{
          key: "sitemap_entities_include_index",
          type: :boolean,
          label: "Include entity index pages",
          help: "Adds the /entities listing page alongside individual entries",
          default: true
        }
      ]
    end

# `source_name`

```elixir
@callback source_name() :: atom()
```

Returns the unique name/identifier for this source.

# `sub_sitemaps`
*optional* 

```elixir
@callback sub_sitemaps(opts :: keyword()) ::
  [{String.t(), [PhoenixKit.Modules.Sitemap.UrlEntry.t()]}] | nil
```

Returns a list of sub-sitemaps for sources that produce multiple files.

Return `nil` for a single file, or a list of `{group_name, entries}` tuples
for per-group splitting (e.g., per-blog, per-entity-type).

Each group will be saved as `sitemap-{source}-{group_name}.xml`.

# `get_settings_schema`

```elixir
@spec get_settings_schema(module()) :: [settings_field()]
```

Returns the settings schema for a source module.

Calls the optional `sitemap_settings_schema/0` callback if implemented,
otherwise returns `[]` (no source-specific settings to render).

# `get_sitemap_filename`

```elixir
@spec get_sitemap_filename(module()) :: String.t()
```

Returns the sitemap filename for a source module.

Calls the optional `sitemap_filename/0` callback if implemented,
otherwise returns `"sitemap-#{source_name()}"`.

# `get_sub_sitemaps`

```elixir
@spec get_sub_sitemaps(
  module(),
  keyword()
) :: [{String.t(), [PhoenixKit.Modules.Sitemap.UrlEntry.t()]}] | nil
```

Returns sub-sitemaps for a source module, or nil if not implemented.

# `safe_collect`

```elixir
@spec safe_collect(
  module(),
  keyword()
) :: [PhoenixKit.Modules.Sitemap.UrlEntry.t()]
```

Safely collects entries from a source, handling errors gracefully.

# `valid_source?`

```elixir
@spec valid_source?(module()) :: boolean()
```

Helper function to check if a source module is valid.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
