In the Subdomain serving mode, Universally serves each language on its own subdomain, such as fr.example.com, by fetching the page from your main domain and translating it. Your Astro app renders only the source language. The integration runs in proxy mode, where it adds the hreflang links and the language switcher to your pages and nothing else.
Before you start
- The project is in the Subdomain serving mode. Pick Subdomain under How should translated pages be served? when you create it. A JavaScript mode project can move here with Move to language subdomains on its Setup page. Moving a Subdomain project back to the SDK is not available yet.
- Access to your domain's DNS.
- The Owner or Admin role to create the project, and Owner, Admin, or Editor to add hostnames and click Re-check now.
Install in proxy mode
- Install the package and add
UNIVERSALLY_API_KEYto.env, as in Install the Astro integration. - Register the integration with
mode: 'proxy':
import universally from '@universally-sdk/astro';
import { defineConfig } from 'astro/config';
export default defineConfig({
site: 'https://example.com',
integrations: [universally({ mode: 'proxy' })]
});
- Add the head tag once in your layout, inside
<head>:
---
import { UniversallyHead } from '@universally-sdk/astro/components';
---
<head>
<UniversallyHead />
</head>
Setting UNIVERSALLY_MODE=proxy in the environment does the same as the mode option.
Add a language subdomain
The dashboard side is the same for every project type and is covered in full in Language subdomains.
- Open All Languages. In the Languages card, click Add subdomain for language.
- In Add Target Language, pick Language and Region, then choose the Subdomain format: Region Code, Language Code, or Custom. The segment becomes the subdomain, so French with Language Code on
example.combecomesfr.example.com. A leadingwwwis dropped from your domain. The hostname is created for you. - Add the three DNS records shown with their Name and Value, in any order:
| Type | Name | Value | Purpose |
|---|---|---|---|
| CNAME | fr.example.com |
proxy.universally.app |
Routing |
| TXT | shown once Cloudflare issues it | shown once Cloudflare issues it | Ownership |
| CNAME | _acme-challenge.fr.example.com |
fr.example.com.afc20bbc0f5b23e9.dcv.cloudflare.com |
Certificate |
Records must not be proxied. On Cloudflare, set Proxy status to DNS only: a proxied record resolves as an A record, which cannot be validated.
- Wait for the checks. They run every 5 minutes, and verification and the certificate take a few minutes. Click Re-check now to check straight away.
- Restart or rebuild your Astro site once the subdomain shows Live. Hostnames are read when your config runs.
The status pill reads Add DNS records, Verifying, Live, DNS moved, or Failed. The timeline steps through DNS added, Domain verified, SSL issued, and Live. A hostname is active once Cloudflare reports both the hostname and its certificate as active. For language settings in general, see Add languages.
What proxy mode renders
On https://example.com/about, <UniversallyHead /> renders the source and x-default links on your site, and each target at its hostname with the same path:
<link rel="alternate" hreflang="en-us" href="https://example.com/about" />
<link rel="alternate" hreflang="fr" href="https://fr.example.com/about" />
<link rel="alternate" hreflang="x-default" href="https://example.com/about" />
These links have to be in your source HTML, because the proxy never serves your main domain. See hreflang tags. The switcher script follows unless switcher: false is set.
Proxy mode skips everything else:
- No
/fr/routes. A language path on your own server stays a 404, which is correct. - No catalog, reports, or polling. Your server talks to Universally once, when the config runs.
/_universally/revalidateanswers 404.t()andhref()return their argument, so a layout written for SDK mode keeps working.
Verify it worked
https://fr.example.com/aboutloads your page in French.- The source of
https://example.com/abouthas a link tohttps://fr.example.com/about.
If it does not work
- A language is missing from the links: it has no active hostname yet. The log says "…has no active hostname in Universally, so it was left out of the hreflang links." Finish its DNS records, wait for Live, then rebuild.
- The records cannot be validated: a record is proxied. On Cloudflare, switch it to DNS only.
- The links do not change after a subdomain goes live: hostnames are read when the config runs. Restart or rebuild.
More cases are in Astro integration troubleshooting.