pub struct SsgConfig {Show 20 fields
pub site_name: String,
pub content_dir: PathBuf,
pub output_dir: PathBuf,
pub template_dir: PathBuf,
pub theme: Option<String>,
pub serve_dir: Option<PathBuf>,
pub base_url: String,
pub site_title: String,
pub site_description: String,
pub language: String,
pub i18n: Option<I18nConfig>,
pub listings: Vec<ListingConfig>,
pub cdn_prefix: Option<String>,
pub og_image: Option<String>,
pub image: ImageConfig,
pub edge_headers: EdgeHeadersConfig,
pub agents: Option<AgentsConfig>,
pub transitions: bool,
pub no_taxonomy_pages: bool,
pub security: SecurityConfig,
}Expand description
Core configuration for the static site generator.
Fields§
§site_name: StringName of the site.
content_dir: PathBufDirectory containing content files.
output_dir: PathBufDirectory for generated output files.
template_dir: PathBufDirectory containing template files.
Defaults to templates, so a config that names a theme
instead does not have to repeat a path it is about to have
resolved for it. apply_theme treats this default as “unset”.
theme: Option<String>Name of a theme to take templates and assets from.
A theme is a directory holding a layout set — _layouts/ for
the published SSG themes, templates/ for a project-shaped one.
Setting this resolves template_dir for you, so a project using
a theme does not have to hand-write a path into someone else’s
tree. An explicit template_dir still wins: naming both is how
you override one layout without forking the theme.
Resolution is by crate::theme::resolve, which searches the
config file’s own directory first and reports every path it
tried when a name does not resolve.
serve_dir: Option<PathBuf>Optional directory for development server files.
base_url: StringBase URL of the site.
site_title: StringTitle of the site.
site_description: StringDescription of the site.
language: StringLanguage code for the site.
i18n: Option<I18nConfig>Optional i18n configuration for multi-locale sites.
Present only with the i18n feature (on by default): the type
comes from the ssg-i18n crate, which that feature pulls in.
listings: Vec<ListingConfig>Named, filtered, paginated listings (#587).
Absent means none, which is the behaviour every site had before:
/page/N/ over every dated page and nothing else.
cdn_prefix: Option<String>Optional CDN prefix for markdown images.
og_image: Option<String>Optional site-wide fallback og:image (a URL or site-relative
path). Used by generated pages that have no per-page image of
their own — currently the taxonomy/tag pages emitted by
crate::taxonomy::TaxonomyPlugin, which bypass the
SeoPlugin transform chain (#586) and so never see the
front-matter-derived og:image that regular content pages get.
Absent ⇒ no og:image tag on those pages.
image: ImageConfigOptional image-pipeline tunables (issue #521).
edge_headers: EdgeHeadersConfigEdge-runtime header emitter config (issue #550). Absent /
empty targets disables the emitter.
agents: Option<AgentsConfig>Agentic-discovery emitters: agents.txt, ai-plugin.json, and
the MCP registry (issue #552). All three are opt-in per the
[agents] section of ssg.toml. Absent ⇒ no files written.
transitions: boolOpt-in View Transitions + lazy-nav client (issue #547).
When true, the build emits _transitions/ssg-transitions.js
and injects a small <script> + <style> block into every
page so same-origin navigations animate via the View
Transitions API (Chromium/Safari) or fall back to a plain
reload in non-supporting browsers (Firefox stable as of
2026-06). Persistent <header> / <footer> roots get
view-transition-name so they don’t animate across boundaries.
Defaults to false to keep zero-JS sites zero-JS.
no_taxonomy_pages: boolSkip generating taxonomy (tag / category / topic) pages.
Defaults to false, so a build that does not ask for this is
unchanged. Sites that curate their own taxonomy — a canonical
vocabulary, a minimum-article threshold, hand-translated slugs —
need to own /tags/ outright: emitting a page per raw
front-matter term contradicts that curation, and on a
multi-locale corpus it multiplies the URL surface with thin
pages. Opting out is cheaper and more honest than deleting the
output afterwards.
security: SecurityConfigSecurity tunables (v0.0.47 plan §3 item 2.3): the [security]
section of ssg.toml. Currently holds the SRI digest
algorithm; absent ⇒ SHA-384.
Implementations§
Source§impl SsgConfig
impl SsgConfig
Sourcepub fn i18n_locales(&self) -> Vec<String>
pub fn i18n_locales(&self) -> Vec<String>
The configured locales, or empty when multi-locale support is unavailable or unconfigured.
The i18n feature is the only thing in the crate that knows
where these come from. Callers ask this instead of reaching for
the field, so disabling the feature does not scatter cfg
branches through every plugin that cares about locales.
Sourcepub fn i18n_locale_set(&self) -> Option<Vec<String>>
pub fn i18n_locale_set(&self) -> Option<Vec<String>>
Every declared locale including the default, or None when no
i18n configuration is reachable at all.
The None case is load-bearing and distinct from an empty list:
callers use it to choose between strict matching against a
declared set and a heuristic. Collapsing the two would make an
undeclared de/ directory look like a locale page.
Sourcepub fn i18n_default_locale(&self) -> Option<String>
pub fn i18n_default_locale(&self) -> Option<String>
The configured default locale, or None when multi-locale
support is unavailable, unconfigured, or set to an empty string.
Sourcepub fn from_matches(matches: &ArgMatches) -> Result<Self, CliError>
pub fn from_matches(matches: &ArgMatches) -> Result<Self, CliError>
Creates a configuration by merging the default values with any command-line arguments.
§Arguments
matches- Parsed command-line arguments from Clap.
§Errors
Returns a CliError if:
- A path fails validation (e.g., directory traversal or symlink).
- A URL is malformed.
- The language is incorrectly formatted.
§Examples
let matches = cli.build().get_matches();
let config = SsgConfig::from_matches(&matches)?;Sourcepub fn discover_config_file() -> Option<PathBuf>
pub fn discover_config_file() -> Option<PathBuf>
Finds a configuration file when --config was not given.
Search order, first match wins:
./ssg.toml— the name the documentation and every example use./config.toml— the name issue #730 was reported against$SSG_CONFIG— an explicit path, for CI and wrapper scripts
The environment variable is checked last so a file in the project cannot be silently overridden by a stale variable in the shell.
Sourcepub fn discover_config_file_in(dir: &Path) -> Option<PathBuf>
pub fn discover_config_file_in(dir: &Path) -> Option<PathBuf>
Self::discover_config_file rooted at an explicit directory.
Taking the directory as a parameter keeps this testable without
set_current_dir, which is process-wide: changing it from a test
leaks into every other test resolving a relative path, in parallel.
Sourcepub fn from_subcommand_matches(sub_m: &ArgMatches) -> Result<Self, CliError>
pub fn from_subcommand_matches(sub_m: &ArgMatches) -> Result<Self, CliError>
Subcommand variant: subcommand parsers re-use the same
--config / --content / --output / --template / --serve flag
names but omit the legacy --new (project scaffolding is its
own command). The override logic is identical otherwise, so we
just delegate through a thin shim that skips the missing
--new lookup.
§Errors
Returns CliError under the same conditions as
Self::from_matches.
Sourcepub fn from_file(path: &Path) -> Result<Self, CliError>
pub fn from_file(path: &Path) -> Result<Self, CliError>
Loads configuration from a TOML or JSON file, enforcing a maximum file size limit.
The format is chosen by file extension: .json is parsed as JSON,
anything else as TOML. Parsing every file as TOML meant a .json
config — the form ssg.schema.json describes, and the form
--config config/ssg.json invites — failed on its opening brace
with “invalid key-value pair, expected key”, which reads as a
malformed file rather than an unsupported format.
§Arguments
path- The path of the config file to be read.
§Errors
Returns a CliError if:
- The file cannot be read or exceeds
MAX_CONFIG_SIZE. - The file is malformed for its format.
- Any fields fail validation afterward.
§Examples
let config = SsgConfig::from_file(Path::new("config.toml"))?;
let config = SsgConfig::from_file(Path::new("config/ssg.json"))?;Sourcepub fn apply_theme(&mut self, base: &Path) -> Result<(), CliError>
pub fn apply_theme(&mut self, base: &Path) -> Result<(), CliError>
Resolves theme into template_dir, relative to base.
A no-op when no theme is named. An explicitly configured
template_dir wins: naming both is how a project overrides one
layout without forking the theme.
base is the directory of the config file, so a themes/
beside ssg.toml resolves whatever the working directory
happens to be — a build must not depend on where it was invoked
from.
§Errors
CliError::ValidationError when the name does not resolve,
carrying every path searched and the names that do exist.
Sourcepub fn validate(&self) -> Result<(), CliError>
pub fn validate(&self) -> Result<(), CliError>
Validates the configuration’s URLs and paths.
§Examples
use ssg::cmd::SsgConfig;
let cfg = SsgConfig::default();
assert!(cfg.validate().is_ok());§Errors
Returns CliError::ValidationError when site_name is empty,
or path/URL safety checks fail.
Sourcepub fn builder() -> SsgConfigBuilder
pub fn builder() -> SsgConfigBuilder
Returns a fresh SsgConfigBuilder for fluent construction.
§Examples
use ssg::cmd::SsgConfig;
let cfg = SsgConfig::builder()
.site_name("My Site".into())
.build()
.expect("valid config");
assert_eq!(cfg.site_name, "My Site");Trait Implementations§
Source§impl<'de> Deserialize<'de> for SsgConfig
impl<'de> Deserialize<'de> for SsgConfig
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Auto Trait Implementations§
impl Freeze for SsgConfig
impl RefUnwindSafe for SsgConfig
impl Send for SsgConfig
impl Sync for SsgConfig
impl Unpin for SsgConfig
impl UnsafeUnpin for SsgConfig
impl UnwindSafe for SsgConfig
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more