This page lists every option you can pass to universally({...}) in astro.config.mjs, the environment variable that sets each one, and the format of the push endpoint.
Options
| Option | Environment variable | Default | Notes |
|---|---|---|---|
mode |
UNIVERSALLY_MODE |
'sdk' |
'sdk' or 'proxy', case insensitive. Any other value throws when the config runs. See Astro with language subdomains. |
apiKey |
UNIVERSALLY_API_KEY |
none, required | The 64 character key from the project's Setup page. An sk_ key also authenticates. A pk_ key fails the languages call and the build. |
apiUrl |
UNIVERSALLY_API_URL |
https://api.universally.com |
Where languages and catalogs are read from. |
translatorUrl |
UNIVERSALLY_TRANSLATOR_URL |
https://translator.universally.com |
Where new strings are reported. |
revalidateSeconds |
UNIVERSALLY_REVALIDATE_SECONDS |
60 |
Smallest gap between two checks for dashboard edits, per language. 0 or a negative number turns polling off. A non numeric environment value is ignored and the default applies. |
hreflang.format |
none | 'variant' |
'variant', 'lang', or a function. Any other string behaves as 'variant'. |
hreflang.xDefault |
none | true |
Adds an x-default link to the source page. Only false disables it. |
switcher |
none | true |
Renders the language switcher script in <UniversallyHead />. Only false disables it. |
scriptsUrl |
UNIVERSALLY_SCRIPTS_URL |
https://scripts.universally.com |
Origin the switcher script loads from. |
A missing key throws: "set UNIVERSALLY_API_KEY in .env or pass apiKey in the integration options. The key is the 64 character site key from your project Setup page."
Where values come from
Each value is resolved in this order, first match wins:
- The option in
universally({...}) - The process environment
.env.localin the Astro project root, next toastro.config.mjs.envin the same folder
An empty value counts as missing. .env.production and other mode files are not read. Reading the files needs Node 20.12 or newer; on older Node they are skipped without an error. The key is resolved at build time and compiled into the server bundle, never the client bundle, so it has to be present where the build runs. See Deploy an Astro site with Universally.
hreflang.format
For a source of English (US) with French (France) under /fr/ and Spanish (Mexico) under /es/, the page /fr/about renders:
<!-- format: 'variant', the default -->
<link rel="alternate" hreflang="en-us" href="https://example.com/about" />
<link rel="alternate" hreflang="fr" href="https://example.com/fr/about" />
<link rel="alternate" hreflang="es-419" href="https://example.com/es/about" />
<link rel="alternate" hreflang="x-default" href="https://example.com/about" />
<!-- format: 'lang' -->
<link rel="alternate" hreflang="en" href="https://example.com/about" />
<link rel="alternate" hreflang="fr" href="https://example.com/fr/about" />
<link rel="alternate" hreflang="es" href="https://example.com/es/about" />
<link rel="alternate" hreflang="x-default" href="https://example.com/about" />
The source comes first, then targets in the order Universally returns them, then x-default. Query strings and hashes are dropped from the URLs. See hreflang tags.
A function receives one language row, with fields such as lang, variant, region, and url, and returns the value. It runs only when the config runs:
universally({
hreflang: {
format: (language) => language.variant.toUpperCase()
}
})
Examples
// Check for dashboard edits every five minutes
universally({ revalidateSeconds: 300 })
// Place the switcher script yourself
universally({ switcher: false })
// Serve through language subdomains
universally({ mode: 'proxy' })
Types and exports
import universally, {
REVALIDATE_PATH, // '/_universally/revalidate'
DEFAULT_REVALIDATE_SECONDS, // 60
DEFAULT_SCRIPTS_URL // 'https://scripts.universally.com'
} from '@universally-sdk/astro';
import type {
HreflangOptions,
ResolvedHreflang,
UniversallyMode,
UniversallyOptions,
ResolvedUniversallyOptions
} from '@universally-sdk/astro';
import { UniversallyHead } from '@universally-sdk/astro/components';
Astro.locals is typed by /// <reference types="@universally-sdk/astro/env" /> in src/env.d.ts:
declare namespace App {
interface Locals {
lang?: string;
t: (source: string) => string;
href: (path: string) => string;
}
}
Push endpoint
POST /_universally/revalidate
X-Universally-Signature: v1=<hex>
Content-Type: application/json
{ "siteId": "site_123", "cacheEpoch": 12, "langs": ["fr"], "ts": 1750000000 }
| Field | Meaning |
|---|---|
X-Universally-Signature |
HMAC-SHA256 of the raw body, keyed with the private half of the site key (its last 32 hex characters), as lowercase hex |
langs |
Variant codes or URL prefixes. null or [] means every language. |
ts |
Unix seconds, within 5 minutes of the receiver's clock |
A trailing slash on the path is accepted.
| Status | When |
|---|---|
200 |
{ "ok": true, "reloaded": [...] }, listing only languages whose cache epoch changed |
401 |
{ "ok": false }: malformed body, missing or wrong signature, expired ts, or a key with no private half |
404 |
Proxy mode, where the endpoint does not exist |
405 |
Any method other than POST |
413 |
Body over 16 KiB, checked before the signature |