Module Options

All configuration is declared under the swiftConfig key in nuxt.config.ts. The framework reads these options during Nuxt module initialization and enables the corresponding features on demand.

Options Overview

OptionTypeDefaultDescription
theme{ mode: 'system' | 'toggle' | 'dark' | 'light', default?: 'auto' | 'light' | 'dark', toggleStates?: 2 | 3 }{ mode: 'toggle', default: 'auto', toggleStates: 3 }Single-knob theme mode. system=follow OS (no switcher) / toggle=user-switchable (mounts useTheme() + SwThemeSwitch) / dark / light=fixed single theme ({ mode: 'light' } / { mode: 'dark' })
i18nboolean | { enabled: boolean, defaultLocale: string, locales: string[] }{ enabled: true, defaultLocale: 'zh-CN', locales: ['zh-CN'] }i18n. Enables @nuxtjs/i18n and auto-registers locale files. Defaults to zh-CN only; multi-locale projects pick more locales via the cli wizard or pass an explicit locales array
pwabooleantruePWA master switch (Service Worker + manifest). Boolean only — manifest content goes in the top-level pwa.manifest of nuxt.config.ts
addToHomescreenboolean | AddToHomescreenOptionsfollows pwaAdd-to-home-screen guide behaviour. ⚠️ Does nothing when pwa is false (the guide has its own hard gate)
authboolean | { enabled?: boolean, deviceLogin?: boolean, guardedPaths: string[], guestPaths: string[] }{ deviceLogin: true, guardedPaths: ['/mine'], guestPaths: ['/login', '/register'] }Route guard + client auth init. false = disable site-wide (docs / no-backend); deviceLogin: false = only turn off /login/device
obfuscatebooleanprocess.env.NODE_ENV === 'production'JS obfuscation (client bundle only). Enabled in production by default; set false for debugging
websocketbooleantrueWebSocket plugin. Registers $ws when enabled
errorHandlerboolean | { enabled?: boolean, endpoint?: string, toast?: boolean }{ enabled: true, endpoint: '/_error-report', toast: false }Captures Vue runtime errors + unhandledrejection and reports
stylesboolean | { reset?: boolean, responsive?: boolean, modal?: boolean, toast?: boolean }{ reset: true, responsive: true, modal: true, toast: true }CSS base-layer injection. tokens always injected; the theme layer is assembled per theme.mode (see theme details below)
systemInfoboolean | { enabled?: boolean, endpoint?: string, ignorePaths?: string[], onError?: 'throw' | 'silent', clientRefreshTtl?: number }true (clientRefreshTtl defaults to 300)/system/info fetch. false = disable entirely; object supports custom endpoint + path-level skip + SSR failure policy (onError, defaults to 'throw') + client refetch reuse window (clientRefreshTtl seconds, 0 = refetch on every full page load)
suppressConsolebooleantrueDisables console.log/warn in production. false keeps output
image{ provider?: string, providers?: object, originRules?: array }{ provider: 'noop', providers: {}, originRules: [] }SwImage external-image provider routing (noop / cf-image / oss-aliyun / cos-tencent / qiniu / imgproxy). Image quality is hardcoded in the framework (quality=80) — not configurable here, and not a SwImage prop
manualChunksRecord<string, string[]>{}Appends Vite custom chunk-split rules. Key = chunk name, value = array of package-name fragments
request{ timeout?: number, uploadTimeout?: number, headers?: Record<string, string>, mock?: { enabled?: boolean, builtins?: boolean, systemInfo?: object }, transport?: 'base64' | 'binary' }{}$request globals: request timeout (default 20s), upload timeout (default 600s), global headers, dev-time request mock (mock) and encrypted-payload transport encoding (transport, default 'base64'). See ### request below and Dev request mock
seo{ aiBotPolicy?: 'allow' | 'disallow', sitemap?: { exclude?: string[], mandatorySources?: string[] } }{ aiBotPolicy: 'allow', sitemap: { exclude: [] } }SEO suite is permanently enabled. aiBotPolicy controls AI training bots (GPTBot/ClaudeBot/CCBot/PerplexityBot) crawl access; sitemap.exclude appends private-path exclusions to sitemap.xml (glob, merged with framework defaults, not replacing). siteUrl is locked via NUXT_PUBLIC_SITE_URL, not exposed here. See ### seo below
ad{ showLabel?: boolean }{ showLabel: true }SwAd* ad family config. showLabel is the site-wide default of the "Ad" compliance badge — components without an explicit showAdLabel follow it; an explicit component prop always wins. See ### ad below
trackerboolean | { enabled?: boolean, autoPageView?: boolean, heartbeatInterval?: number }{ enabled: true, autoPageView: true, heartbeatInterval: 30000 }Unified tracking foundation (group WebSDK / self-hosted channel). Auto-degrades silently when config is missing — no need to turn it off manually. See ### tracker below
apiDocs{ source: 'yapi' | 'openapi', url: string, project?: string | number, pathVars?: Record<string,string> }noneAPI doc source for pnpm generate-api (build tooling only — the runtime module never reads it). Configure source / url (plus project for yapi) here when you wire the backend; the token goes to API_DOCS_TOKEN in .env. Not part of swift.config.json, which only holds what sw create can decide at creation time. See Codegen
guardsRecord<guardName, 'error' | 'warn' | 'off'>all errorEscape hatch for build-time guards: downgrade one when it misfires so the build unblocks immediately (a line still goes to the build log — never silent). Not part of swift.config.json, and the CLI does not manage it — write it in swiftConfig inside nuxt.config.ts. See the "escape hatch guards" section of Rendering strategies

Array defaults are replaced, not concatenated (framework#384): arrays such as auth.guardedPaths / auth.guestPaths / i18n.locales are replaced wholesale as soon as you set them explicitly in swiftConfig (including an empty array []) — the defaults are never merged back in. The one exception is seo.sitemap.exclude, which is appended to framework's private-path defaults on the sitemap module side (see ### seo below).

Internally framework uses the moduleDependencies API (@nuxt/kit 4.x) to register submodules (pinia / vueuse / fonts / scripts / sitemap / schema-org / robots, plus i18n / pwa when enabled). Transparent to consumers.

Configuration Examples

Docs Site Configuration (used by this site)

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@swift-web/framework'],

  swiftConfig: {
    theme: { mode: 'toggle', default: 'auto', toggleStates: 3 },

    i18n: {
      enabled: true,
      defaultLocale: 'zh-CN',
      locales: ['zh-CN', 'zh-TW', 'en'],
    },

    pwa: true,

    // the docs site has no auth backend (no /login/device) → auth: false disables it site-wide
    auth: false,

    websocket: false,

    // docs site has no error-report backend
    errorHandler: false,

    // docs site has no /system/info backend → disable the fetch
    systemInfo: false,
  },
})

Typical Business Project Configuration

export default defineNuxtConfig({
  modules: ['@swift-web/framework'],

  swiftConfig: {
    theme: { mode: 'light' },
    i18n: { enabled: false },
    pwa: false,

    auth: {
      guardedPaths: ['/mine', '/profile', '/settings', '/orders'],
      guestPaths: ['/login', '/register'],
    },

    websocket: false,

    errorHandler: {
      enabled: true,
      endpoint: '/_error-report',
    },

    // systemInfo: true (default; framework fetches /system/info on SSR)
  },
})

Option Details

theme

theme is a single-knob config: one mode field decides three things at once — "which token set to load", "which color-scheme to declare", and "whether a switcher is provided".

modeTokens loadedcolor-schemeSwitcher
'system'light + darkdark in dark contexts (follows OS)❌ none
'toggle'light + darkdark in dark contexts✅ mounts useTheme() + SwThemeSwitch
'dark'fixed darkdark❌
'light' (starter default)fixed lightlight❌
  • default (toggle only): the switcher's initial state — 'auto' (follow OS) / 'light' / 'dark', default 'auto'
  • toggleStates (toggle only): the switcher form — 3 = tri-state (auto / light / dark cycle, can return to follow-system at any time) / 2 = two-state (light / dark only, simpler, but cannot return to follow-system once toggled), default 3

In toggle mode the framework reads the localStorage theme preference on startup and writes it to the html[data-theme] attribute; switch it with useTheme() or the built-in SwThemeSwitch component.

Fixed dark / light declare color-scheme unconditionally (injecting color-scheme-dark.css / color-scheme-light.css respectively) — so native UI (scrollbars, form controls) follows the site, avoiding "a dark page with light scrollbars".

system / toggle, by contrast, declare it contextually: color-scheme: dark is emitted only while dark is active (@media (prefers-color-scheme: dark) or [data-theme='dark']); in a light context nothing is declared and the browser default (normal, which renders the same as light) applies. So "always declared" holds only for the two fixed modes — don't infer that every mode ships a color-scheme.

theme only accepts the object form. For a fixed single-theme site, write { mode: 'light' } or { mode: 'dark' } directly.

i18n

Enables @nuxtjs/i18n and auto-registers the locale files for the languages listed in locales (files placed in the i18n/locales/ directory). Set to false for Chinese-only projects to skip the i18n runtime.

pwa

Integrates @vite-pwa/nuxt and generates the Service Worker + Web App Manifest — enables "Add to Home Screen" and basic offline access. Set to false for projects that don't need PWA. The addToHomescreen sub-option controls "Add to Home Screen" prompt-card timing.

auth

Route guard config + framework client-side auto device login. Three forms:

  • false — Disable site-wide (docs / demo / no-backend projects where /login/device doesn't exist). Framework skips auth.client.ts device login; global login/guest middleware naturally no-ops.
  • true or undefined (default) — Uses default guardedPaths: ['/mine'] + guestPaths: ['/login', '/register'].
  • Object { enabled?, deviceLogin?, guardedPaths, guestPaths } — Custom paths; enabled: false is equivalent to setting the top-level option to false but keeps path declarations.
  • deviceLogin: false — Only turns off the anonymous /login/device login; username / QR / register and remember-me credential renewal keep working. For sites that don't want to pay one backend request per new device. The gate lives in useUserStore().autoLogin() alone: the startup plugin, the systemInfo fallback and the 401 / 2002 re-login all go through it. Before turning it off, check: public backend endpoints must accept requests without a token; guests have no user_id, so tracking / error reports carry no userId and guest-level endpoints that rely on a device identity stop working.
// Docs / demo / no-backend project
swiftConfig: {
  auth: false,
  systemInfo: false,
}

// Standard business project
swiftConfig: {
  auth: {
    guardedPaths: ['/mine', '/orders', '/settings'],
    guestPaths: ['/login', '/register'],
  },
}

Used with the framework's built-in global middleware (login.global.ts / guest.global.ts):

  • guardedPaths: Path prefixes requiring login (prefix-matched)
  • guestPaths: Paths inaccessible to logged-in users — accessing them redirects to the home page

⚠️ Build-time validation (#166): with auth enabled, runtimeConfig.public.deviceKey / tokenKey must be non-empty strings or the build fails immediately — an empty cookie name crashes the whole site client-side during hydration (invisible to SSR/curl). Sites without an auth backend should set auth: false to skip the check.

errorHandler

When enabled, the framework registers a Vue global error handler and an unhandledrejection listener on the client. On error, it sends a POST request to endpoint with the error details as JSON.

Two kinds are not reported: unhandled rejections whose name is AbortError (playback interrupted by pause() or a source change, AbortController cancellations — intentional, not failures), and errors whose stack script URLs are all browser-extension URLs (chrome-extension:// etc.). Errors without a stack are still reported.

  • false: disables the entire error-monitoring stack
  • true or an object { enabled, endpoint, toast } (all fields optional): enabled; the object form customizes the report endpoint (default /_error-report) and the error toast

Toast decoupled from reporting (#282, v0.97.0): toast controls whether end users see a visible "Something went wrong — we've been notified" prompt. It defaults to false — report silently (matching the default behaviour of industry SDKs such as Sentry / Bugsnag; on a content site, popping a dialog for one irrelevant third-party script error is pure noise). To keep the old toast behaviour, opt in explicitly:

// swift.config.json
"errorHandler": { "enabled": true, "toast": true }

Either way, Vue errors are still visible in the console during dev; this switch only gates the POST reporting layer.

⚠️ When customizing endpoint, keep it out of /api/. The starter template — and every project derived from it — proxies all of /api/** to the business backend via routeRules['/api/**'], and that proxy returns before the router is reached, so a local handler under /api/ is never hit: error payloads (userId / stack / route / ua) get proxied to the backend, take a 404, and are silently swallowed. The symptom is "error monitoring is on but nothing ever arrives, with no error to go on." The default /_error-report already sits outside /api/; implement the endpoint under server/routes/, not server/api/. Same constraint applies to sitemap source endpoints.

systemInfo

Controls whether framework fetches /system/info during SSR, the endpoint to use, and which paths to skip.

  • true (default, equivalent to { enabled: true, onError: 'throw' }): framework auto-fetches /system/info on SSR and writes to systemStore (via framework request util; SSR-side deviceId is auto-empty)
  • false: don't fetch at all (no-backend scenarios like pure static docs sites)
  • { enabled?: boolean, endpoint?: string, ignorePaths?: string[], onError?: 'throw' | 'silent', clientRefreshTtl?: number }: custom endpoint + path-level skip + SSR failure policy + client refetch reuse window
// Disable entirely (e.g. docs site with no backend)
swiftConfig: {
  systemInfo: false,
}

// Custom endpoint + path-level skip
swiftConfig: {
  systemInfo: {
    endpoint: '/api/system/info',     // defaults to '/system/info'
    ignorePaths: ['/preview', '/embed'],
  },
}

// Tolerate SSR fetch failure (flaky backend; accept client-side SEO field hydration)
swiftConfig: {
  systemInfo: { onError: 'silent' },
}

// Client refetch reuse window: full page loads within 10 minutes in the same tab don't hit the backend; 0 = refetch every time
swiftConfig: {
  systemInfo: { clientRefreshTtl: 600 },
}

clientRefreshTtl — reuse window for the client-side refetch (seconds, default 300)

After a full page load, framework refetches /system/info in the background on the client so that ops changes (ads / announcements) don't have to wait for the page cache to expire. The result is stored in sessionStorage with a timestamp (key prefixed with cachePrefix); full page loads inside the window reuse it without a request, and 0 restores "refetch on every full page load". Without a refetch, the whole session uses the systemInfo baked into the entry page's payload, so its freshness equals the entry page's cache TTL; in-app (SPA) navigation never refetched anyway. On an ISR home page this request used to be the largest per-page-view backend cost; a config change shows up on new full page loads after at most clientRefreshTtl seconds, and a tab the user opens manually counts as a new session and refetches immediately (a tab opened via target="_blank" copies the opener's sessionStorage and stays inside the window).

onError — SSR fetch failure policy

Behavior when the /system/info fetch fails during SSR. Defaults to 'throw':

  • 'throw' (default, recommended) — fail-fast: throws createError({ statusCode: 503, fatal: true }), Nuxt renders error.vue. Surfaces problems immediately in dev; triggers 5xx monitoring alerts in production and prevents empty-shell HTML from being indexed by crawlers.
  • 'silent' — tolerate failure: only console.error + a state flag; pages keep rendering with empty systemInfo, and the client silently re-fetches in the background. Suited to "high-SLA backend + SEO fields can be hydrated client-side"; the cost is hidden bugs in dev, empty-shell SEO loss in production, and no monitoring trigger.

Client-side fetch failures are not governed by onError — they always console.error and never navigate to error.vue.

The device is established entirely client-side, so the SSR-side cookie has no deviceId. If the backend requires a non-empty deviceId, the SSR fetch is bound to fail → the default 'throw' triggers a 503. This is the expected fail-fast behavior. Fixes: let the backend accept an empty deviceId for public endpoints, explicitly set onError: 'silent', or use systemInfo: false.

obfuscate

JS obfuscation toggle. Enabled by default in production (process.env.NODE_ENV === 'production'); the client build artifact is processed through javascript-obfuscator, modestly increasing bundle size and dramatically reducing readability. Disabled automatically during debug / dev. Set explicitly to false when you need to debug production builds with readable code.

Only the client bundle is obfuscated: server code never ships to users (zero benefit), and obfuscating the SSR output breaks Nitro's static tracing of dynamic import chunks, causing Cannot find module 500s at runtime.

websocket

Whether to register the framework's built-in $ws instance (with auto-reconnect). Default true. Set to false to skip plugin registration and trim client bundle size if your project doesn't use WebSocket.

styles

CSS base-layer injection. The framework ships six CSS layers:

  • tokens.css — always injected (CSS variables are the single source of truth, no toggle)
  • theme.css — injected when theme.mode is system / toggle (both light + dark tokens); fixed dark / light modes inject the corresponding color-scheme declaration instead
  • reset.css — gated by styles.reset (default true)
  • responsive.css — gated by styles.responsive (default true); provides .sw-container + .sw-show-mobile / .sw-hide-mobile / .sw-hide-tablet / .sw-hide-desktop responsive utility classes (see Styling & Tokens)
  • modal.css — gated by styles.modal (default true); SwModal default skin (--sw-modal-* mapped to semantic tokens)
  • toast.css — gated by styles.toast (default true); SwToast default skin (--sw-toast-* mapped to semantic tokens)
// Disable framework reset (e.g. when using Tailwind preflight)
styles: { reset: false, responsive: true }

// Skip entirely (project ships its own complete base style)
styles: false

suppressConsole

Whether to suppress console.log / console.warn in production (console.error is always preserved) to reduce information leakage. Default true. Set false when you need to keep output for production troubleshooting. No effect during dev.

image

SwImage external-image provider routing. Only affects <SwImage> rendering of external URLs; does NOT affect:

  • Encrypted images (.bnc suffix, handled by decrypt-image)
  • Local images (/images/*, handled natively by Nuxt static)
image: {
  provider: 'noop',                              // Default handler: noop / cf-image / oss-aliyun / cos-tencent / qiniu / imgproxy
  providers: {
    'cf-image': { baseURL: 'https://cdn.example.com' },
  },
  originRules: [
    { match: '^https://(oss|img)\\.example\\.com/', use: 'oss-aliyun' },
  ],
}

Image quality (quality) is hardcoded to 80 in the framework and not configurable; display dimensions are derived from <SwImage>'s ratio prop (width / height are <img> attributes computed internally from ratio, not props). See the SwImage docs for the full prop list.

manualChunks

Vite Rollup custom chunk-split rules. Key = output chunk name, value = an array of package-name fragments to match.

manualChunks: {
  'vendor-charts': ['echarts', 'chart.js'],
  'vendor-rich-editor': ['@tiptap/'],
}

Best for splitting "only-used-on-a-few-pages" third-party libraries (charts / rich-text editors) into separate chunks instead of bloating the main bundle.

request

Framework $request global configuration.

request: {
  timeout: 20_000,           // default 20000ms (20s). Normal request timeout
  uploadTimeout: 600_000,    // default 600000ms (10min). Upload timeout for SwUploadImage / SwUploadVideo etc.
  headers: {
    'X-Tenant-Id': 'foo',    // global headers, injected into $request and nitroApiFetch calls
  },
}

Per-request overrides (request(url, { timeout: 5000 })) take precedence over global config.

request.mock — dev-time request mock (framework#100 / #188)

Intercepts mocks at the request layer (the createApiFetch plaintext layer), dev-only (both SSR and CSR, framework#208), stripped from production builds via DCE. Build the UI / interactions first while the backend API isn't ready, then just delete the mock to wire up the real API.

  • enabled?: boolean — master switch. Defaults to import.meta.env.DEV (on in dev / off in prod). Set false to temporarily disable all registerApiMock interception.
  • builtins?: boolean — built-in presets: framework ships ready-made fake data for /login/* + /system/info. Only active when enabled: true is set explicitly; defaults to true (on whenever enabled). Set false to use only the mechanism without the built-in fake data.
  • systemInfo?: object — overrides fields of the built-in /system/info skeleton (shallow merge + one level of deep merge on header); effective only when builtins are active.

Business-endpoint mocks go through registerApiMock in a single dev-only file (e.g. app/plugins/dev-mock.ts); delete that file at integration time and component code stays untouched.

// Enable dev mock: built-in login / system-info presets come along too
request: {
  mock: { enabled: true },
}

// Use only the registerApiMock mechanism, without built-in login / system-info fakes
request: {
  mock: { enabled: true, builtins: false },
}

Full usage / matcher / built-in preset details: Dev request mock.

request.transport — encoding of the backend's encrypted payload (fw#382)

The outermost encoding of the backend's encrypted payload. Send and receive share it, so it must match the backend's convention. Defaults to 'base64', which suits the vast majority of backends; only a few H5 backends using a raw-binary protocol (e.g. the yc203 / yc202 line) need 'binary'.

  • 'base64' (default): IV‖ciphertext is Base64-encoded to text and sent as text/plain.
  • 'binary': IV‖ciphertext is a raw binary byte stream with no Base64 (the request body sends raw bytes, the response is read as arrayBuffer, and decryption skips Base64.parse).

The core crypto — AES-CBC / PKCS7 / gzip / HMAC-derived key — is identical in both modes; only this outermost encoding differs.

// Backend using a raw-binary encrypted protocol
request: {
  transport: 'binary',
}

Symptom of a mismatch: if the backend returns base64 but 'binary' is configured (or vice versa) the payload won't decrypt, and the console throws 响应报文长度异常 (N bytes) … 多为 request.transport 与后端约定不符 or Invalid typed array length. The framework does not auto-detect this (every site hard-codes Content-Type: application/json, so it can't serve as a signal), so it must be set explicitly.

Server-side nitroApiFetch shares one source of truth with request(): nitroApiFetch, used in Nitro contexts such as sitemap / tasks, reads swiftWebFramework.request.transport / timeout / headers through Nitro's useRuntimeConfig() (which works without an event) — the very same value the client-side request() uses. Configure swiftConfig.request.transport in one place and you are done; no bridge plugin or extra environment variable is needed.

request.headers applies to both request() (browser and SSR) and nitroApiFetch() (Nitro server routes / tasks), but not upload. The framework overrides the protocol headers Content-Type, deviceType, requestId, version, time, and language case-insensitively; global headers cannot replace them.

To override temporarily on one machine without touching config, use Nitro's nested env convention: NUXT_PUBLIC_SWIFT_WEB_FRAMEWORK_REQUEST_TRANSPORT=binary.

seo

The SEO submodule is permanently enabled (sitemap / schema-org / robots / OG meta — all on). Two fields are exposed here:

  • aiBotPolicy?: 'allow' | 'disallow' — controls whether AI training crawlers (GPTBot / ClaudeBot / CCBot / PerplexityBot) are allowed. 'allow' (default) allows them; 'disallow' explicitly disallows in robots.txt + meta
  • sitemap?: { exclude?: string[], mandatorySources?: string[] } — private-path exclusion for sitemap.xml, see below

seo.sitemap

The sitemap default exclude already includes common private paths (framework#85 GAP3):

/login, /register, /forgot,
/mine/**, /profile/**, /account/**,
/admin/**, /dashboard/**,
/search, /oauth/**

Append business-specific private paths via seo.sitemap.exclude (merged with framework defaults, not replacing) — framework's default private-path list cannot be removed, you can only add to it:

// swift.config.json
{
  "framework": {
    "seo": {
      "sitemap": {
        "exclude": ["/link", "/promo-draft", "/transit/**"]
      }
    }
  }
}

Field:

  • exclude?: string[] — Append paths (micromatch glob syntax). Common paths like /login, /mine/** don't need re-declaring — framework already includes them.
  • mandatorySources?: string[] — Disabled by default; exact same-origin mandatory JSON sources fail XML generation with a safe 503. See the Sitemap guide.

sitemap siteUrl (NUXT_PUBLIC_SITE_URL)

sitemap.xml's siteUrl is locked to the NUXT_PUBLIC_SITE_URL environment variable (not exposed under swiftConfig). framework runs a host-format check at module setup:

InputResult
undefined / ''❌ not configured
example.com (missing protocol)❌ not a valid URL
<your-domain> (placeholder)❌ not a valid URL
ftp://example.com❌ protocol must be http/https
https://example.com/api (with path)❌ must not include path
https://example.com?lang=zh❌ must not include query/hash
https://example.com✅
https://example.com/ (trailing slash)✅
http://localhost:3000 (dev)✅

On failure: console.warn in dev / console.error in production build — build is not blocked (CI pipelines may inject the value post-build).

This value typically comes from ops / DevOps (not developers):

  • Local dev: .env set NUXT_PUBLIC_SITE_URL=http://localhost:3000 or a staging URL
  • Production: ops / CI inject the primary domain (e.g. https://www.example.com)

For detailed diagnostics + nginx forwarding setup see nginx origin header forwarding.

Different semantics from useSeo's origin resolution: sitemap.xml always uses NUXT_PUBLIC_SITE_URL (a stable primary domain — search engine sitemaps must output a single stable URL set); useSeo's canonical/og:url pins to it when set, and only falls back to useRequestURL().origin (following the user's visited domain) when it isn't — since framework#278 this variable is L2 of the origin priority chain, ahead of the request headers (sites with ISR or prerendered pages must set it, otherwise cached pages never see Host). See framework#87 / #85 / #278.

SwAd* ad-family-level config. Its only field for now is showLabel — the site-wide default of the "Ad" compliance badge (SwAdLabel):

  • true (default): every SwAd* component renders the badge when showAdLabel is not set. The default errs on the compliance-safe side — forgetting to turn it off just looks a bit ugly; forgetting to turn it on means unlabeled ads, which is a compliance risk.
  • false: no badge by default site-wide — for sites whose ad creatives already carry a baked-in "Ad" label.
  • An explicit component-level show-ad-label prop always overrides this default (e.g. re-enable a single slot after turning it off globally).
// nuxt.config.ts — turn off globally for sites whose creatives carry a baked-in "Ad" label
swiftConfig: {
  ad: { showLabel: false },
}

Upgrade note: sites whose creatives already carry the ad label and don't want the component badge must now opt out explicitly (global ad.showLabel: false, or per-component :show-ad-label="false").

tracker

Group-wide operational analytics (WebSDK) foundation. When enabled, the framework lazy-loads the WebSDK on the client and takes over tracking — driving impression / click reporting for SwAd* ad components, plus business-side custom reporting via useTracker() / useAdTrack().

  • boolean — true (default) enables the foundation; false disables it entirely
  • Object { enabled?, autoPageView?, heartbeatInterval? }:
    • enabled?: boolean — master switch, default true
    • autoPageView?: boolean — auto-report appPageView on route change, default true
    • heartbeatInterval?: number — video playback heartbeat interval (milliseconds): while playing, a videoEvent (video_behavior_key: 'video_heartbeat', payload carries accumulated watched seconds watch_time) fires every N milliseconds, powering "average watch time / valid play" metrics. Default 30000 (30 seconds); 0 disables the heartbeat (watch_time still ships with the other playback events)

The autoPageClick option was removed with WebSDK v1.1.6 — the SDK auto-collects page_click (richer fields, always on); see Tracking Foundation · SDK Auto-Collected Events.

// Enabled by default, no explicit config needed; to turn off auto pageView:
tracker: { autoPageView: false }

// Disable the tracking foundation entirely
tracker: false

Dual gate (silent no-op if either is missing): reporting only takes effect when both tracker.enabled is true AND system/info.tracker returns appId / encryptedConfig. When config is missing, the framework auto-degrades silently (component tracking still written, nothing sent at runtime) — no need to turn it off manually.

For the full event list and usage, see Tracking Foundation.