Plinth reads configuration from plinth.toml (or the path in PLINTH_CONFIG). All fields have defaults — an empty file produces a working configuration.
Key Type Default Description
namestring "Plinth"Site name in header and page titles
taglinestring "Welcome to my website"Short tagline on the home page
descriptionstring "A personal website"Default meta description
langstring "en"HTML lang attribute
default_themestring "dark"Default colour theme ("dark" or "light")
animated_backgroundstring "flow-field"Home page background preset
Accepted animated_background values:
"none" disables the animated canvas and uses a static page background.
"flow-field" renders an Odysseus-style procedural particle flow field.
"constellation" renders drifting nodes with proximity lines.
"aurora-ribbons" renders translucent wave ribbons.
"orbital-trails" renders orbiting particles with fading trails.
"digital-rain" renders sparse terminal-style falling glyphs.
"topographic-waves" renders animated contour lines.
Key Type Default Description
namestring "Admin"Default author name for articles
emailstring ""Email shown in footer (empty = hidden)
Key Type Default Description
githubstring ""GitHub profile URL (empty = hidden)
gitlabstring ""GitLab profile URL
codebergstring ""Codeberg profile URL
mastodonstring ""Mastodon profile URL
blueskystring ""Bluesky profile URL
Key Type Default Description
project_namestring "Plinth"Project name in footer attribution
project_urlstring "https://codeberg.org/caniko/plinth"Project URL in footer
Navigation items (order matters). Each entry has:
Key Type Description
labelstring Link text
pathstring URL path
Default navigation:
[[site.nav]]
label = "Posts"
path = "/posts"
[[site.nav]]
label = "Projects"
path = "/projects"
[[site.nav]]
label = "About"
path = "/about"
Key Type Default Description
titlestring ""Home page title (empty = use site name)
descriptionstring ""Home page meta description
Key Type Default Description
titlestring "Posts"Blog listing page title
subtitlestring ""Subtitle below the title
descriptionstring ""Meta description
Key Type Default Description
titlestring "Projects"Portfolio page title
subtitlestring ""Subtitle below the title
descriptionstring ""Meta description
Key Type Default Description
titlestring "About Me"About page title
descriptionstring ""Meta description
Key Type Default Description
hoststring "127.0.0.1"Bind address
portu16 3000Bind port
Key Type Default Description
database_urlstring "postgres://plinth:plinth@localhost:5432/plinth"Postgres connection URL
Key Type Default Description
service_namestring "plinth"OTLP service name
log_levelstring "info"Rust log level (RUST_LOG format)
otlp_endpointstring ""OTLP endpoint URL (empty = disabled)
otlp_headersstring ""OTLP auth headers (comma-separated key=value)
Key Type Default Description
default_limitusize 10Default search result count
related_limitusize 5Default related articles count
min_similarityf32 0.5Minimum cosine similarity for opinion tracking
Key Type Default Description
words_per_minuteusize 200WPM for reading time calculation
vector_truncationusize 5000Max characters before generating embeddings
Key Type Default Description
blog_limitusize 50Max entries in /feeds/blog.xml
projects_limitusize 50Max entries in /feeds/projects.xml
activity_limitusize 50Max entries in /feeds/activity.xml
Controls how activity entries are scored for the ranked /activity page, the home strip, and the public API. Score is computed at read time, so changes take effect on the next request.
Key Type Default Description
strategystring "exponential""exponential", "linear", or "pure"
half_life_daysfloat 365.0Exponential ranking: impact * 0.5 ^ (age_days / half_life_days)
window_daysfloat 730.0Linear ranking: impact * max(0, 1 - age_days / window_days)
age uses the reference date coalesce(merged_at, closed_at, created_at). pure uses impact alone, with the most recent reference date as a tiebreaker. Results are ordered by score descending, then reference date descending.
Controls how the server fetches and refreshes activity metadata from code forges. Tokens are provided via environment variables only, never in this file. See Environment Variables .
Key Type Default Description
refresh_ttl_secsinteger 3600Refresh an entry in the background when its fetched_at is older than this many seconds
refresh_backoff_secsinteger 900Minimum seconds between refresh attempts for an entry that errored
github_base_urlstring "https://api.github.com"GitHub API base URL, overrideable for GitHub Enterprise or testing
codeberg_base_urlstring "https://codeberg.org/api/v1"Codeberg/Forgejo API base URL, overrideable for self-hosted Forgejo or testing
[ranking]
strategy = "exponential"
half_life_days = 365.0
window_days = 730.0
[forge]
refresh_ttl_secs = 3600
refresh_backoff_secs = 900
github_base_url = "https://api.github.com"
codeberg_base_url = "https://codeberg.org/api/v1"
# tokens via GITHUB_TOKEN / CODEBERG_TOKEN env vars, not here
Key Type Default Description
api_urlstring ""Immich server URL (empty = image proxy disabled)
Key Type Default Description
cache_max_ageu64 31536000Cache-Control max-age for proxied images (seconds)
Key Type Default Description
plausible_domainstring ""Site domain tracked by Plausible (empty = disabled)
plausible_script_urlstring ""URL to your Plausible script (e.g. https://plausible.example.com/js/script.js)
Both fields must be set for the Plausible <script> tag to be injected. This keeps analytics fully opt-in.
Key Type Default Description
enabledbool falseEnable donation links across the site
cta_textstring ""Custom text for end-of-article CTA (default: “If you found this useful, consider supporting my work.”)
Each entry defines a donation platform link:
Key Type Default Description
platformstring (required) Platform identifier: "kofi", "github_sponsors", "liberapay", or "custom"
urlstring (required) URL to your profile on the platform
labelstring ""Custom display label (empty = auto-generated from platform name)
When enabled, donation links appear in three places:
Header : A “Support” link with heart icon in the navigation bar
End of articles : A compact CTA after blog post content
Footer : A heart icon alongside social links
/support page : A dedicated page showing all configured platforms as cards
[donation]
enabled = true
cta_text = "If you found this useful, consider supporting my work."
[[donation.links]]
platform = "kofi"
url = "https://ko-fi.com/yourusername"
[[donation.links]]
platform = "github_sponsors"
url = "https://github.com/sponsors/yourusername"
[[donation.links]]
platform = "liberapay"
url = "https://liberapay.com/yourusername"
[site]
name = "My Site"
tagline = "Systems, science, and software"
description = "Personal website and blog"
lang = "en"
default_theme = "dark"
animated_background = "flow-field"
[site.author]
name = "Jane Doe"
email = "jane@example.com"
[site.social]
github = "https://github.com/janedoe"
mastodon = "https://fosstodon.org/@janedoe"
[site.footer]
project_name = "Plinth"
project_url = "https://codeberg.org/caniko/plinth"
[[site.nav]]
label = "Posts"
path = "/posts"
[[site.nav]]
label = "Projects"
path = "/projects"
[[site.nav]]
label = "About"
path = "/about"
[pages.blog]
title = "Blog"
subtitle = "Notes on software and systems"
[server]
host = "127.0.0.1"
port = 3000
[database]
database_url = "postgres://plinth:plinth@localhost:5432/plinth"
[observability]
log_level = "info"
[search]
default_limit = 10
[content]
words_per_minute = 200
[feeds]
blog_limit = 50
projects_limit = 50
activity_limit = 50
[ranking]
strategy = "exponential"
half_life_days = 365.0
window_days = 730.0
[forge]
refresh_ttl_secs = 3600
refresh_backoff_secs = 900
github_base_url = "https://api.github.com"
codeberg_base_url = "https://codeberg.org/api/v1"
[analytics]
plausible_domain = "example.com"
plausible_script_url = "https://plausible.example.com/js/script.js"
[donation]
enabled = true
[[donation.links]]
platform = "kofi"
url = "https://ko-fi.com/janedoe"
[[donation.links]]
platform = "github_sponsors"
url = "https://github.com/sponsors/janedoe"