Multilingual Astro: Two Domains, Two Languages, One Build
In short
Astro can put languages on their own domains, but only with server output – fully static websites have no built-in way to do it. We solve this with a single build that our open-source integration then splits into one domain per language; for codeaeffchen.de that is more than 400 pages on two domains. The real work is not the pages themselves but everything around them: canonicals, hreflang, sitemaps, robots.txt, error pages and redirects all have to be right per domain.
Our website exists in two languages – not under /en/, but on two domains: German on codeaeffchen.de, English on codeaeffchen.com. Both come from a single Astro project and a single build. That sounds like a detail, but it is one of the places where Astro stops for static websites – and where a lot can go wrong without anyone noticing right away.
This article shows when two domains make sense, what Astro brings for it, where it stops and how we close the gap. We have published the solution as an open-source integration.
Own Domain or Subdirectory?
Before the technology, the actual decision. In its guide to multilingual and multi-regional sites (Google Search Central), Google describes three viable options: subdirectories such as example.com/en/, subdomains such as en.example.com, and separate domains such as example.de and example.com. None of them is wrong per se.
The differences lie elsewhere:
- Subdirectory: simple, one domain, all signals pooled. For an international audience, though, a
.deaddress with/en/does not feel like a provider that is at home there. - Own domain per language or market: a country domain is a strong signal for the target market and feels familiar to visitors. The price: each domain builds its authority separately, and analytics, Search Console and redirects all exist twice.
We chose two domains because the English site should stand on its own – with its own address, its own English URLs (/services/ instead of /leistungen/) and its own analytics. For many corporate websites, a subdirectory is the simpler and entirely sufficient choice.
What Astro Brings – and Where It Stops
Astro has built-in internationalisation: languages, the default language and path prefixes can be configured, and helper functions generate the matching URLs. For subdirectories, that is all you need.
For separate domains, there is the i18n.domains option. It comes with a condition stated explicitly in the Astro documentation: it requires server output, with no prerendered pages. A fully static website – exactly what makes Astro so strong for marketing sites, corporate presences and blogs – cannot use this option.
Which leaves the question: how do the pages of a static website get onto two domains?
One Build, Two Domains
Our approach: Astro builds the website as usual – German at the root, English under /en/. An additional step then splits the output into one folder per domain. What has to happen is more than copying files:
- Shared files such as stylesheets, scripts, images and fonts end up in both folders, so each domain is self-contained.
- Links lose the
/en/prefix on the English domain:/en/contact/becomes/contact/. - Absolute addresses – canonical, hreflang, Open Graph, structured data – point to the right domain.
- Sitemaps list only each domain’s own pages, under its own address.
- robots.txt points to the right sitemap.
- The error page sits where the web server expects it.
- Redirects in the
.htaccessapply only to the domain they belong to.
For us, this step runs on every deploy and splits more than 400 pages. We check it against a simple standard: from a fresh build it must produce exactly the same files as before – file by file.
What We Learned Along the Way
Most mistakes with two domains are silent: the site looks right, only search engines get contradictory signals. We found some of them ourselves only late.
Canonicals of redirect pages. For moved URLs, Astro generates small redirect pages. Their canonical was built from the default domain plus /en/ – an address that no longer exists after the split. We only noticed while comparing every file before and after switching to the integration; it rewrites both spellings.
Page pairs with different addresses. Our glossary has the same 69 terms in both languages, but under different addresses: /glossar/dsgvo/ in German, /glossary/gdpr/ in English. An automatic path translation does not find such pairs. The result: for a month the pages were not linked via hreflang, and the language switcher only led to the overview. The fix is a real mapping of the pairs – backed by a test that fails as soon as the lists drift apart.
Files each language has on its own. Some files sit at the root but belong to one language – in our case the llms.txt for AI systems. If the split step copied them blindly, the English domain would get the German version.
Everything around it exists twice. Two domains mean two Search Console properties, two sites in web analytics and redirects in two forms. Planning for that from the start saves you puzzling later over why one language is missing from the reports.
Using the Integration
We have published the split step as an Astro integration: @codeaeffchen/astro-split-domains, with source code and documentation on GitHub, MIT-licensed. It goes into the Astro config – after the sitemap, so its output is split as well:
import sitemap from '@astrojs/sitemap';
import splitDomains from '@codeaeffchen/astro-split-domains';
export default defineConfig({
site: 'https://example.de',
integrations: [
sitemap(),
splitDomains({
enabled: process.env.SPLIT_DOMAINS === '1',
defaultLocale: { code: 'de', site: 'https://example.de' },
locales: [{ code: 'en', site: 'https://example.com' }],
}),
],
});
A build with SPLIT_DOMAINS=1 produces dist/de/ and dist/en/, each uploaded to its domain. Without the variable, the output stays flat – handy for local preview and for checks that should see the whole project.
The integration does not guess: if a language folder is missing or the .htaccess is only half-marked, the build fails instead of shipping a broken domain. It deliberately does not generate hreflang annotations itself – they belong in the pages, because only there is it known which page has which counterpart.
How our own website is built beyond that and what is checked before every change is covered in the codeaeffchen.de case study.
Planning a multilingual Astro website – or moving an existing multilingual site to Astro? We’ll tell you whether separate domains pay off for your case or whether a subdirectory is enough. Drop us a line.
Frequently Asked Questions
Can Astro serve a multilingual website on several domains?
Only to a limited extent out of the box: the i18n.domains option puts languages on their own domains, but according to the Astro documentation it requires server output with no prerendered pages. Fully static websites need an extra step after the build that splits the output onto the domains – which is exactly what our integration @codeaeffchen/astro-split-domains does.
Own domain or subdirectory – which is better for SEO?
Both work. In its guide to multilingual and multi-regional sites, Google describes subdirectories, subdomains and country-specific domains as viable options. A country domain is a strong signal for the target market, but each domain builds its authority separately. A subdirectory pools the signals on one domain but feels less local abroad.
What do I need to watch with hreflang across two domains?
hreflang annotations must use absolute URLs, be set reciprocally on both sides and point to the counterpart that actually exists. If addresses differ per language – such as /glossar/dsgvo/ and /glossary/gdpr/ – an automatic path translation is not enough; you need a real mapping of page pairs.
Where can I get the integration?
As the npm package @codeaeffchen/astro-split-domains, with the source code on GitHub at codeaeffchen-gmbh/astro-split-domains. It is MIT-licensed and runs in production for codeaeffchen.de and codeaeffchen.com.
Related Services
Related Projects
Founder & Full-Stack Developer
20+ years of web development experience. Specialised in Laravel, WordPress and custom software for mid-sized businesses.