Skip to main content

Docusaurus Single-Locale Pages Deployment

Single-locale deployment is used to avoid ESA Pages static file count limits. The idea is to keep one Git repository, but create two ESA Pages projects. Each project builds only one locale.

Deployment Shape

Recommended structure:

Chinese Pages project -> https://nevergpdzy.com
English Pages project -> https://en.nevergpdzy.com

Both sites are deployed at the domain root. The English site does not use the /en prefix.

The route layout is:

https://nevergpdzy.com/docs/intro -> Chinese docs
https://nevergpdzy.com/blog -> Chinese blog
https://en.nevergpdzy.com/docs/intro -> English docs
https://en.nevergpdzy.com/blog -> English blog

Build Commands

Chinese project:

npm run build:zh

English project:

npm run build:en

Both commands generate site stats first, then build only one locale:

docusaurus build --locale zh-Hans
docusaurus build --locale en

In local verification, each single-locale output contains about 814 files, 413 directories, and 1227 total items, which stays below the common ESA Pages 2000 static file limit.

Environment Variables

Independent-domain single-locale mode requires both variables:

SITE_URL
SINGLE_LOCALE_DEPLOY

Chinese Pages project:

SITE_URL=https://nevergpdzy.com
SINGLE_LOCALE_DEPLOY=true

English Pages project:

SITE_URL=https://en.nevergpdzy.com
SINGLE_LOCALE_DEPLOY=true

If either variable is missing, the configuration falls back to the single-site bilingual behavior. In that fallback mode, hand-written links in the English locale continue to use /en/docs/intro and /en/blog.

When independent-domain single-locale mode is enabled:

  • Docusaurus url uses SITE_URL.
  • baseUrl stays /.
  • Hand-written footer links no longer add /en for the English locale.
  • Navbar uses the custom custom-locale-switch instead of the default localeDropdown.

The custom language switch only changes navigation behavior and does not introduce new visual styling. Desktop uses Docusaurus' default navbar__link style, and the mobile sidebar uses the default menu__link menu style, so the same language switch is visible on mobile.

Switching rules:

https://nevergpdzy.com/docs/intro
-> https://en.nevergpdzy.com/docs/intro

https://en.nevergpdzy.com/docs/intro
-> https://nevergpdzy.com/docs/intro

Query strings and hashes are preserved:

https://nevergpdzy.com/docs/intro?x=1#title
-> https://en.nevergpdzy.com/docs/intro?x=1#title

The component derives the counterpart domain from the current SITE_URL:

  • If the current hostname does not start with en., the target hostname is prefixed with en..
  • If the current hostname starts with en., the target hostname removes en..

ESA Pages Project Settings

Chinese project:

Repository: current repository
Build command: npm run build:zh
Output directory: build
SITE_URL: https://nevergpdzy.com
SINGLE_LOCALE_DEPLOY: true

English project:

Repository: current repository
Build command: npm run build:en
Output directory: build
SITE_URL: https://en.nevergpdzy.com
SINGLE_LOCALE_DEPLOY: true

Do not build the full bilingual site in either single-locale ESA Pages project, or the deployment can hit the same file count problem again.

Verification Checklist

After a local or ESA build, check:

  1. The Chinese project has no build/en directory.
  2. The English project has no build/en directory.
  3. The Chinese project serves /docs/intro.
  4. The English project serves English content at /docs/intro.
  5. The English project's footer does not contain /en/docs/intro or /en/blog.
  6. The Chinese site switches to https://en.nevergpdzy.com.
  7. The English site switches back to https://nevergpdzy.com.
  8. sitemap.xml uses the current project's SITE_URL.
  9. The output stays under the ESA Pages file limit:
Get-ChildItem build -Recurse -File | Measure-Object
Get-ChildItem build -Recurse -Directory | Measure-Object

Old /en Paths

After split deployment succeeds, old /en/... URLs do not automatically become English independent-domain URLs. If old links must be preserved, add redirects in ESA later:

https://nevergpdzy.com/en/docs/intro
-> https://en.nevergpdzy.com/docs/intro

This redirect is not required for the first rollout. Add it after the main split deployment is working.