Yext makes it easy to power multiple distinct websites based on the same underlying code repository. This is useful for creating many templated websites, each with their own unique requirements, while still being able to share code and structure across each website from a single repository.
This can be achieved by using scopes — values you use to specify which code in your repository should be used for which site.
Note: This reference article assumes you are using Pages 1.0.0 or higher.
Repository Structure
You can create scopes by configuring the following sections of your repository:
config.yaml
Each of your website scopes will require its own configuration file. Create a sub-folder per scope at the root of your project, each with their own config.yaml file:
. ├── [CONFIGURATION_SCOPE_1] // e.g. locations.brand1.com │ └── config.yaml ├── [CONFIGURATION_SCOPE_2] // e.g. locations.brand2.com │ └── config.yaml ├── src │ ├── assets │ ├── components │ ├── styles │ └── templates │ ├── [CONFIGURATION_SCOPE_1] │ │ ├── index.tsx │ │ └── 404.tsx │ └── [CONFIGURATION_SCOPE_2] │ ├── index.tsx │ └── 404.tsx ├── package.json ├── package-lock.json ├── tsconfig.json ├── tailwind.config.js └── vite.config.js
Your config.yaml file should include the --scope flag and point to your specific scope configuration:
# example config.yaml
buildConfiguration:
buildCommand: npm run build -- --scope REPLACE_WITH_SCOPE_CONFIGURATION
installDependenciesStep:
command: npm ci
requiredFiles:
- package.json
- package-lock.json
- .npmrc
Templates (src/templates)
Define a sub-folder per scope to specify templates generated on a per-scope basis.
In the example below, deploying a site using CONFIGURATION_SCOPE_1 generates brand1.tsx; using CONFIGURATION_SCOPE_2 generates brand2.tsx.
. ├── [CONFIGURATION_SCOPE_1] │ └── config.yaml ├── [CONFIGURATION_SCOPE_2] │ └── config.yaml ├── src │ └── templates │ ├── [CONFIGURATION_SCOPE_1] // e.g. locations.brand1.com │ │ ├── brand1.tsx │ │ └── 404.tsx │ └── [CONFIGURATION_SCOPE_2] // e.g. locations.brand2.com │ ├── brand2.tsx │ └── 404.tsx
Global templates: Place a template at the root of your templates folder to use it across all scopes. In the example below, robots.ts is generated for both scopes:
. ├── src │ └── templates │ ├── robots.ts // generated for all scopes │ ├── [CONFIGURATION_SCOPE_1] │ │ ├── brand1.tsx │ │ └── 404.tsx │ └── [CONFIGURATION_SCOPE_2] │ ├── brand2.tsx │ └── 404.tsx
Overriding global templates: Override a global template by providing a template with the same name within a scope. In the example below, location.tsx is configured globally but overridden for CONFIGURATION_SCOPE_1:
. ├── src │ └── templates │ ├── location.tsx // generated for all scopes │ ├── robots.ts │ ├── [CONFIGURATION_SCOPE_1] │ │ ├── brand1.tsx │ │ └── location.tsx // overrides the root-level location.tsx │ └── [CONFIGURATION_SCOPE_2] │ └── brand2.tsx
Local Development
To use and test this feature during local development, specify a scope when running your dev command:
npx pages dev --scope REPLACE_WITH_SCOPE_CONFIGURATION
To test your production build:
npx pages prod --scope REPLACE_WITH_SCOPE_CONFIGURATION
Deploying to Production
To deploy a website based on a scope, define an environment variable called CONFIGURATION_SCOPE. The value you provide tells the Pages system which section of your repository to use for that deployment.

When that website deploys, each locations.brand1.com scope within the repository structure will be used.
Reverse Proxy
If you have multiple websites that require a reverse proxy setup and the subdirectory differs between scopes, you will need to configure a unique vite.config.js per scope.
For example, if you are powering:
www.brand1.com/locationswww.brand2.com/restaurants
Use the following structure with a scope-level vite.config.js in each root-level scope folder:
. ├── [CONFIGURATION_SCOPE_1] │ ├── vite.config.js // scope-level vite.config.js │ └── config.yaml ├── [CONFIGURATION_SCOPE_2] │ ├── vite.config.js // scope-level vite.config.js │ └── config.yaml ├── src │ └── templates │ ├── location.tsx │ ├── robots.ts │ ├── [CONFIGURATION_SCOPE_1] │ │ ├── brand1.tsx │ │ └── location.tsx │ └── [CONFIGURATION_SCOPE_2] │ └── brand2.tsx
Configure the assetsDir property to match your reverseProxyPrefix for each scope:
// [CONFIGURATION_SCOPE_1]/vite.config.js — for www.brand1.com/locations
export default defineConfig({
plugins: [react(), yextSSG()],
build: {
assetsDir: "locations/assets"
}
});
// [CONFIGURATION_SCOPE_2]/vite.config.js — for www.brand2.com/restaurants
export default defineConfig({
plugins: [react(), yextSSG()],
build: {
assetsDir: "restaurants/assets"
}
});
Refer to the Reverse Proxy reference article to ensure the rest of your project is set up correctly.