Skip to content

Site Configuration

The site configuration is the core configuration file of the Firefly theme, controlling basic site information, theme colors, page toggles and other global settings.

Config File

src/config/siteConfig.ts

Basic Information

PropertyTypeDefaultDescription
titlestring"Firefly"Site title
subtitlestring"Demo site"Site subtitle
site_urlstring-Site URL
descriptionstring-Site description for <meta name="description">
keywordsstring[]-Site keywords for <meta name="keywords">
langstring"zh_CN"Site language: zh_CN, zh_TW, en, ja, ru
ts
export const siteConfig: SiteConfig = {
  title: "Firefly",
  subtitle: "Demo site",
  site_url: "https://firefly.cuteleaf.cn",
  description: "A beautiful Astro blog theme...",
  keywords: ["Firefly", "Astro", "Blog"],
  lang: "zh_CN",
};

Theme Color

PropertyTypeDefaultDescription
themeColor.huenumber165Theme color hue (0-360). Red: 0, Cyan: 200, Teal: 250, Pink: 345
themeColor.fixedbooleanfalseHide theme color picker from visitors
themeColor.defaultModestring"system"Default mode: "light", "dark", "system"

Page Width

PropertyTypeDefaultDescription
pageWidthnumber100Maximum page width in rem. Larger values make the content area wider
ts
// Page width (unit: rem)
// Increase the value to make the content area wider
pageWidth: 100,

Card Style

PropertyTypeDefaultDescription
card.borderbooleanfalseEnable card border and shadow for a 3D effect
card.followThemebooleanfalseWhether card background follows theme hue in light mode
ts
card: {
  border: false,
  followTheme: false,
},
PropertyTypeDefaultDescription
navbar.logoobject-Navbar logo, see below
navbar.titlestring"Firefly"Navbar title
navbar.widthFullbooleanfalseWhether navbar takes full width
navbar.menuAlignstring"center"Desktop menu alignment: "left" or "center"
navbar.followThemebooleanfalseWhether navbar icon and title follow theme color
navbar.stickyNavbarbooleantrueKeep navbar fixed at the top and always visible

Logo supports four types:

  1. Astro icon library: { type: "icon", value: "material-symbols:home-pin-outline" }
  2. public directory image (no optimization): { type: "image", value: "/assets/images/logo.webp", alt: "Logo" }
  3. src directory image (auto-optimized, recommended): { type: "image", value: "assets/images/logo.webp", alt: "Logo" }
  4. Remote image: { type: "url", value: "https://example.com/logo.png", alt: "Logo" }
ts
navbar: {
  logo: {
    type: "image",
    value: "assets/images/firefly.png",
    alt: "🍀",
  },
  title: "Firefly",
  widthFull: false,
  menuAlign: "center",
  followTheme: false,
  stickyNavbar: true,
},

Favicon

ts
favicon: [
  {
    src: "/favicon/favicon.ico",
    // theme: "light",  // Optional: 'light' | 'dark'
    // sizes: "32x32",  // Optional: icon size
  },
],

Date & Timezone

PropertyTypeDefaultDescription
siteStartDatestring-Site start date (YYYY-MM-DD), used for uptime counter
timezonestring"Asia/Shanghai"IANA timezone string for date formatting

Admonitions

PropertyTypeDefaultDescription
rehypeCallouts.themestring"github"Theme: "github", "obsidian", "vitepress"

TIP

Restart the dev server after changing this setting.

Post Settings

PropertyTypeDefaultDescription
showLastModifiedbooleantrueShow "last modified" card at the bottom of posts
outdatedThresholdnumber30Days threshold for showing the "last modified" card
sharePosterbooleantrueEnable share poster generation
generateOgImagesbooleanfalseGenerate OpenGraph images (increases build time)

Post List Layout

PropertyTypeDefaultDescription
postListLayout.defaultModestring"list"Default layout: "list" or "grid"
postListLayout.mobileDefaultModestring-Mobile default layout: "list" or "grid". If not set, it follows defaultMode
postListLayout.showTagsbooleantrueShow tags in post list cards
postListLayout.descriptionLinesnumber2Number of lines for post excerpts. Set to 0 to disable truncation
postListLayout.allowSwitchbooleantrueAllow users to switch layout
postListLayout.grid.masonrybooleanfalseEnable masonry layout
postListLayout.grid.columnWidthnumber320Minimum card width in grid mode (px). The browser automatically calculates column count based on container width

Pagination

PropertyTypeDefaultDescription
pagination.postsPerPagenumber10Posts per page

Page Toggles

PropertyTypeDefaultDescription
pages.friendsbooleantrueFriends page toggle
pages.sponsorbooleantrueSponsor page toggle
pages.guestbookbooleantrueGuestbook page toggle (requires comment system)
pages.bangumibooleantrueBangumi page toggle
categoryBarbooleantrueCategory navigation bar on homepage and archive page

Bangumi

PropertyTypeDefaultDescription
bangumi.userIdstring-Bangumi user ID

TIP

Bangumi data is fetched at build time. During dev only one page of data is fetched; build fetches all data.

Analytics

PropertyTypeDefaultDescription
analytics.googleAnalyticsIdstring""Google Analytics ID
analytics.microsoftClarityIdstring""Microsoft Clarity ID
analytics.umamiAnalytics.websiteIdstring""Umami website ID
analytics.umamiAnalytics.scriptUrlstring"https://cloud.umami.is/script.js"Umami script URL (supports self-hosted Umami)
analytics.umamiAnalytics.trackOutboundLinksbooleantrueAutomatically add Umami outbound click events to external links
analytics.umamiAnalytics.collectWebVitalsbooleanfalseEnable data-performance="true" to collect Core Web Vitals
analytics.umamiAnalytics.replay.enabledbooleanfalseEnable Umami session replay
analytics.umamiAnalytics.replay.sampleRatenumber0.15Replay sampling rate from 0 to 1; for example, 0.15 records 15% of sessions
analytics.umamiAnalytics.replay.maskLevel"moderate" | "strict""moderate"Privacy masking level; moderate masks inputs, strict also masks all page text
analytics.umamiAnalytics.replay.maxDurationnumber300000Maximum recording length in milliseconds, default 5 minutes
analytics.umamiAnalytics.replay.blockSelectorstring""CSS selector for elements to fully exclude from recording; omitted when empty
analytics.la51Analytics.Idstring""51la analytics ID
analytics.la51Analytics.sdkUrlstring""Custom SDK URL (leave empty to use default)
analytics.la51Analytics.ckstring""Data separation identifier for multiple statistics IDs
analytics.la51Analytics.autoTrackbooleanfalseEnable event analysis
analytics.la51Analytics.hashModebooleanfalseEnable hash route mode
analytics.la51Analytics.screenRecordbooleantrueEnable session recording
ts
analytics: {
  googleAnalyticsId: "",
  microsoftClarityId: "",
  umamiAnalytics: {
    websiteId: "",
    scriptUrl: "https://cloud.umami.is/script.js",
    trackOutboundLinks: true,
    collectWebVitals: false,
    replay: {
      enabled: false,
      sampleRate: 0.15,
      maskLevel: "moderate",
      maxDuration: 300000,
      blockSelector: "",
    },
  },
  la51Analytics: {
    Id: "",
    sdkUrl: "",
    ck: "",
    autoTrack: false,
    hashMode: false,
    screenRecord: true,
  },
},

If you use a self-hosted Umami instance, set analytics.umamiAnalytics.scriptUrl to your own script endpoint.

Image Optimization

PropertyTypeDefaultDescription
imageOptimization.formatsstring"webp"Output format: "avif", "webp", "both" (recommended)
imageOptimization.qualitynumber85Compression quality (1-100), recommended 70-85
imageOptimization.noReferrerDomainsstring[][]Domains requiring anti-hotlinking handling, supports wildcard *

WARNING

Astro can only optimize images in the src directory. More images means longer build times.

Anti-Hotlinking (Referrer Policy)

Some image hosts or CDNs (e.g. Bilibili CDN) enforce hotlink protection by checking the Referer request header, causing 403 errors when their images are embedded in your blog.

By configuring noReferrerDomains, Firefly will automatically add a referrerpolicy="no-referrer" attribute to <img> tags matching the specified domains, preventing the browser from sending the Referer header and bypassing hotlink protection.

ts
imageOptimization: {
  formats: "webp",
  quality: 85,
  noReferrerDomains: [
    "i0.hdslb.com",     // Bilibili CDN
    "i1.hdslb.com",
    "i2.hdslb.com",
    "*.bilibili.com",   // Wildcard support
  ],
},

TIP

  • Only applies to external images starting with http:// or https://, local images are not affected
  • Only affects <img> tags with matching domains, does not change referrer behavior for other links
  • Images with alt text in Markdown will still generate <figcaption> as expected