Site Settings

On this page

Site settings are global configuration values for your site: title, tagline, logo, social links, and display preferences. Administrators manage these through the admin interface, and you access them in your templates.

Querying Settings

Use getSiteSettings() to fetch all site settings:

---
import { getSiteSettings } from "emdash";

const settings = await getSiteSettings();
---

<html lang="en">
  <head>
    <title>{settings.title}</title>
    {settings.favicon && (
      <link rel="icon" href={settings.favicon.url} />
    )}
  </head>
  <body>
    <header>
      {settings.logo ? (
        <img src={settings.logo.url} alt={settings.logo.alt || settings.title} />
      ) : (
        <span class="site-title">{settings.title}</span>
      )}
      {settings.tagline && <p class="tagline">{settings.tagline}</p>}
    </header>
    <slot />
  </body>
</html>

Available Settings

EmDash provides these core settings:

interface SiteSettings {
	// Identity
	title: string;
	tagline?: string;
	logo?: MediaReference;
	favicon?: MediaReference;

	// URLs
	url?: string;

	// Display
	postsPerPage: number;
	dateFormat: string;
	timezone: string;

	// Social
	social?: {
		twitter?: string;
		github?: string;
		facebook?: string;
		instagram?: string;
		linkedin?: string;
		youtube?: string;
	};
}

interface MediaReference {
	mediaId: string;
	alt?: string;
	url?: string; // Resolved URL (read-only)
}

Fetching Individual Settings

Use getSiteSetting() to fetch a single setting by key:

import { getSiteSetting } from "emdash";

const title = await getSiteSetting("title");
// Returns: "My Site" or undefined

const logo = await getSiteSetting("logo");
// Returns: { mediaId: "...", url: "/_emdash/api/media/file/..." }

This is useful when you only need one or two values and want to avoid fetching everything.

Using Settings in Components

---
import { getSiteSettings, getMenu } from "emdash";

const settings = await getSiteSettings();
const menu = await getMenu("primary");
---

<header class="header">
  <a href="/" class="logo">
    {settings.logo ? (
      <img
        src={settings.logo.url}
        alt={settings.logo.alt || settings.title}
        width="150"
        height="50"
      />
    ) : (
      <span class="site-name">{settings.title}</span>
    )}
  </a>

  {menu && (
    <nav>
      {menu.items.map(item => (
        <a href={item.url}>{item.label}</a>
      ))}
    </nav>
  )}
</header>
---
import { getSiteSetting } from "emdash";

const social = await getSiteSetting("social");

const platforms = [
  { key: "twitter", label: "Twitter", baseUrl: "https://twitter.com/" },
  { key: "github", label: "GitHub", baseUrl: "https://github.com/" },
  { key: "facebook", label: "Facebook", baseUrl: "https://facebook.com/" },
  { key: "instagram", label: "Instagram", baseUrl: "https://instagram.com/" },
  { key: "linkedin", label: "LinkedIn", baseUrl: "https://linkedin.com/in/" },
  { key: "youtube", label: "YouTube", baseUrl: "https://youtube.com/@" },
] as const;
---

{social && (
  <div class="social-links">
    {platforms.map(({ key, label, baseUrl }) => (
      social[key] && (
        <a
          href={baseUrl + social[key]}
          rel="noopener noreferrer"
          target="_blank"
          aria-label={label}
        >
          {label}
        </a>
      )
    ))}
  </div>
)}

SEO Meta Tags

---
import { getSiteSettings } from "emdash";

interface Props {
  title?: string;
  description?: string;
  image?: string;
}

const settings = await getSiteSettings();
const {
  title,
  description = settings.tagline,
  image,
} = Astro.props;

const documentTitle = title
  ? `${title} | ${settings.title}`
  : settings.title;
const ogTitle = title ?? settings.title;
---

<title>{documentTitle}</title>
{description && <meta name="description" content={description} />}

<!-- Open Graph -->
<meta property="og:title" content={ogTitle} />
{description && <meta property="og:description" content={description} />}
{image && <meta property="og:image" content={image} />}
{settings.url && <meta property="og:url" content={settings.url + Astro.url.pathname} />}

<!-- Twitter -->
{settings.social?.twitter && (
  <meta name="twitter:site" content={settings.social.twitter} />
)}
<meta name="twitter:card" content={image ? "summary_large_image" : "summary"} />

Date Formatting

Use the dateFormat and timezone settings for consistent date display:

---
import { getSiteSetting } from "emdash";

interface Props {
  date: string;
}

const { date } = Astro.props;
const dateFormat = await getSiteSetting("dateFormat") || "MMMM d, yyyy";
const timezone = await getSiteSetting("timezone") || "UTC";

// Format using Intl.DateTimeFormat or a library like date-fns
const formatted = new Intl.DateTimeFormat("en-US", {
  timeZone: timezone,
  dateStyle: "long",
}).format(new Date(date));
---

<time datetime={date}>{formatted}</time>

Admin API

Fetch settings programmatically:

GET /_emdash/api/settings

Response:

{
	"title": "My EmDash Site",
	"tagline": "A modern CMS",
	"logo": {
		"mediaId": "med_123",
		"url": "/_emdash/api/media/file/abc123"
	},
	"postsPerPage": 10,
	"dateFormat": "MMMM d, yyyy",
	"timezone": "America/New_York",
	"social": {
		"twitter": "@handle",
		"github": "username"
	}
}

Update settings (partial updates supported):

POST /_emdash/api/settings
Content-Type: application/json

{
  "title": "New Site Title",
  "tagline": "Updated tagline"
}

Only the provided fields are changed. Omitted fields retain their current values.

Media References

The logo and favicon settings store media references. When you read them, EmDash resolves the url property automatically:

const logo = await getSiteSetting("logo");
// {
//   mediaId: "med_123",
//   alt: "Site logo",
//   url: "/_emdash/api/media/file/abc123"
// }

When updating via the API, provide only the mediaId:

{
	"logo": {
		"mediaId": "med_456",
		"alt": "New logo"
	}
}

API Reference

getSiteSettings()

Fetch all site settings with resolved media URLs.

Returns: Promise<Partial<SiteSettings>>

Returns a partial object. Unset values are undefined.

getSiteSetting(key)

Fetch a single setting by key.

Parameters:

  • key — The setting key (e.g., "title", "logo", "social")

Returns: Promise<SiteSettings[K] | undefined>

Type-safe: the return type matches the key you request.