Freestruct.config.yml Reference
Complete reference for freestruct.config.yml options
Overview
freestruct.config.yml is the central configuration file for Freestruct. It defines your site’s SEO settings that get injected into every page.
NOTE: before v0.6.0 the file was named
ssr-config.yml. Both names are read (the legacy name participates in the same upward search), but new installs should usefreestruct.config.yml.
Example
outputDir: _site
site:
url: https://example.com
name: My Docs
description: Documentation for my project
twitter:
username: "@janedev"
card: summary
og:
image: /assets/og-image.png
locale: en_US
type: website
Output Directory
The output directory from your SSG build.
outputDir: _site # Jekyll
outputDir: public # Hugo, Gatsby
outputDir: build # Docusaurus
Generate Options
generateSitemap
Generate sitemap.xml automatically (default: true).
generateSitemap: true # generates sitemap.xml
generateSitemap: false # skip sitemap generation
generateRobots
Generate robots.txt automatically (default: true).
generateRobots: true # generates robots.txt
generateRobots: false # skip robots.txt
generate404
Generate 404.html automatically (default: true). If a custom 404.html already exists in the output directory, Freestruct will use it instead of generating one.
generate404: true # generates 404.html (or uses custom)
generate404: false # skip 404 page generation
generateFeed
Generate RSS feed (feed.xml).
generateFeed: true # generates feed.xml (on by default)
generateFeed: false # skip feed generation
readingTime
Inject estimated reading time into each page.
readingTime: true # injects reading time meta (on by default)
readingTime: false # skip reading time
lastModified
Inject last-modified timestamp.
lastModified: true # injects current timestamp (on by default)
lastModified: false # skip
lazyLoad
Add loading=”lazy” to images.
lazyLoad: true # adds lazy loading (on by default)
lazyLoad: false # skip
linkCheck
Check internal links for broken references.
linkCheck: true # check and warn (on by default)
linkCheck: false # skip link checking
searchIndex
Generate search.json for client-side search.
searchIndex: true # generates search.json (on by default)
searchIndex: false # skip search index
generateNav
Generate navigation from docs folder structure (default: true). Set false to use SSG menu.
generateNav: true # auto-generate from folder (default)
generateNav: false # use SSG built-in menu
Cache Busting Options
cacheBusting
Configuration for the cache busting system.
cacheBusting:
hash: true # generate build hash (default: true)
assetQueryParam: true # add ?v=hash to assets (default: true)
hashInCanonicalUrl: false # add ?v=hash to canonical (default: false)
runHooks
Security: Disabled by default. Enable to run purge commands defined in cacheBusting.purge.
# Must be explicitly enabled
runHooks: true # allow purge commands to execute
runHooks: false # default - no commands run
When enabled, you can define purge commands:
cacheBusting:
purge:
- name: cloudflare
command: "curl -X DELETE https://api.cloudflare.com/..."
runHooks: true # required to enable
Path Options
basePath
Optional base path to strip from canonical URLs (for subpath deployments).
basePath: /myproject # Strip /myproject from URLs
preserveExistingMeta
Whether to preserve existing meta tags or replace them entirely.
preserveExistingMeta: true # default - only add missing tags
preserveExistingMeta: false # remove existing SEO first, then inject fresh
Site Options
site
Site-level information.
| Key | Required | Description |
|---|---|---|
url |
Yes | Full URL of your site |
name |
Yes | Site name |
description |
No | Default site description |
author
Optional author identity, shipped as a schema.org Person under
"founder" on the injected Organization JSON-LD block.
author:
name: Jane Doe
url: https://janedoe.dev
| Key | Required | Description |
|---|---|---|
name |
Yes (to ship founder) |
Author name |
url |
No | Author URL (GitHub, personal site, etc.) |
No author configured: the Organization JSON-LD carries no founder key.
jsonLd
Custom structured data, appended after the built-in Organization and WebSite JSON-LD blocks. Takes a single object or an array of objects:
jsonLd:
- "@type": BreadcrumbList
itemListElement:
- "@type": ListItem
position: 1
- Ships through the same missing-only gate as the built-ins: a page that
already carries
application/ld+jsonkeeps its own and receives no extra blocks. - Serialization neutralizes
<(as\u003c) so a value cannot close the script tag early. - A non-object entry is skipped with a loud
[freestruct] config warningline; nothing dies silently.
Meta Options
Twitter Card meta tags.
| Key | Required | Description |
|---|---|---|
username |
No | Twitter handle (include @). Omit the whole twitter block without one: twitter:site and twitter:creator then stay out of the injected head (card type and twitter:title still inject) |
card |
No | Card type: summary, summary_large_image, app, player |
twitter:description ships alongside twitter:title on every page (same
value as og:description), and twitter:image ships whenever an
og.image (or per-page ogImage) is configured.
og
Open Graph meta tags.
| Key | Required | Description |
|---|---|---|
image |
No | OG image path (absolute or relative to site url) |
locale |
No | Locale (default: en_US) |
type |
No | Content type: website, article, book, profile |
og.image is optional: with no image configured (and no per-page override),
no og:image or twitter:image tag ships at all - a bare image tag pointing
at the site root is a broken social card, not a fallback. Relative image
paths are joined onto site.url; absolute HTTP(S) values pass through
unchanged. Values that reach the head are HTML-attribute-escaped first.
Template Placeholders
Available placeholders in inject-brand.html:
| Placeholder | Description |
|---|---|
| `` | Page title |
| `` | Page description |
| `` | Full page URL |
| `` | Canonical URL |
| `` | Site base URL |
| `` | Site name |
| `` | Site description |
| `` | Twitter handle |
| `` | Twitter card type |
| `` | OG image path |
| `` | OG/Twitter image as a full URL (relative values joined onto the site url) |
| `` | OG content type |
| `` | OG locale |
Per-Page Options
For page-specific SEO, add a data comment to the built page:
<!-- freestruct: {"title": "My Page", "ogType": "article", "ogImage": "/images/post.jpg"} -->
| Key | Effect |
|---|---|
title |
Replaces the page part of the og/twitter title composition (the site name suffix still applies) |
description |
Replaces the injected description (og and twitter) |
ogType |
Replaces the injected og:type value |
ogImage |
Per-page og image; relative values join onto site.url like og.image |
twitterCard |
Replaces the injected twitter:card value |
publishedTime |
Ships article:published_time with the og injection |
author |
Ships article:author with the og injection |
section |
Ships article:section with the og injection |
Ground rules:
- Missing-only wins: a page that already ships its own description, Open
Graph or Twitter tags keeps them, and overrides aimed at those groups are
skipped with a loud
[freestruct] page warningline (they never die silently). article:published_time,article:authorandarticle:sectionride the Open Graph injection: they ship only when freestruct actually injects og tags on that page.- Unknown keys in the comment warn; malformed JSON in the comment warns and the whole comment is ignored.
- Attribute values are HTML-escaped before they land in the head.
Source Attribution
Injected HTML includes a source comment:
<!-- injected by freestruct: https://github.com/dhaupin/freestruct -->
Environment Overrides
You can override config values via environment variables:
FREESTRUCT_URL=https://staging.example.com npx freestruct
Related
- Getting Started - First-run installation and quick start
- Configuration - The high-level overview of every feature
- Troubleshooting - When a config key misbehaves