Craft CMS Multi-Site Setup

Our company is engaged in the development, support and maintenance of sites of any complexity. From simple one-page sites to large-scale cluster systems built on micro services. Experience of developers is confirmed by certificates from vendors.
Development and maintenance of all types of websites:
Informational websites or web applications
Business card websites, landing pages, corporate websites, online catalogs, quizzes, promo websites, blogs, news resources, informational portals, forums, aggregators
E-commerce websites or web applications
Online stores, B2B portals, marketplaces, online exchanges, cashback websites, exchanges, dropshipping platforms, product parsers
Business process management web applications
CRM systems, ERP systems, corporate portals, production management systems, information parsers
Electronic service websites or web applications
Classified ads platforms, online schools, online cinemas, website builders, portals for electronic services, video hosting platforms, thematic portals

These are just some of the technical types of websites we work with, and each of them can have its own specific features and functionality, as well as be customized to meet the specific needs and goals of the client.

Our competencies:
Development stages
Latest works
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    822
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    847
  • image_website-sbh_0.png
    Website development for SBH Partners
    999
  • image_website-_0.png
    Website development for Red Pear
    451

Configuration of Multi-Site Support in Craft CMS

Craft CMS supports multiple sites from one installation: different domains, languages, regions. Content can be unique to each site or synchronized between them.

Multi-Site Architecture

Craft Installation
├── Site Group: Main
│   ├── Site: mysite.ru (ru-RU) — primary
│   ├── Site: mysite.com (en-US)
│   └── Site: mysite.de (de-DE)
└── Site Group: Microsite
    └── Site: promo.mysite.ru (ru-RU)

Configuration via CP or Project Config

# config/project/sites/mysite-ru.yaml
name: 'My Site RU'
handle: mySiteRu
language: ru-RU
primary: true
enabled: true
hasUrls: true
baseUrl: 'https://mysite.ru/'

Nginx configuration for multiple domains on one installation:

# Both domains point to one document root
server {
  server_name mysite.ru mysite.com mysite.de;
  root /var/www/mysite/web;
  # ...standard Craft Nginx config...
}

Content Distribution Management via Sites

propagationMethod in Section defines how content is distributed:

  • all — entry is created for all sites automatically
  • none — only for site where it's created
  • siteGroup — for sites in the same group
  • language — for sites with same language
# config/project/sections/blog.yaml
propagationMethod: all
siteSettings:
  mySiteRu:
    hasUrls: true
    uriFormat: 'blog/{slug}'
    template: blog/_entry
  mySiteEn:
    hasUrls: true
    uriFormat: 'en/blog/{slug}'
    template: blog/_entry
  mySiteDe:
    hasUrls: true
    uriFormat: 'de/blog/{slug}'
    template: blog/_entry

Fields with Different Localization

Field "title": translationMethod = site (own title for each site)
Field "publishDate": translationMethod = none (one date)
Field "heroImage": translationMethod = none (shared image)
Field "body": translationMethod = site (unique text)
Field "slug": translationMethod = site (slug in site language)

Language Switcher in Template

{# List of all versions of current page #}
<nav class="language-switcher">
  {% for site in craft.app.sites.getAllSites() %}
    {% set localeEntry = entry.getLocalized().site(site).one() %}
    {% if localeEntry %}
      <a href="{{ localeEntry.url }}"
         lang="{{ site.language | slice(0, 2) }}"
         {% if site.id == currentSite.id %}aria-current="page"{% endif %}>
        {{ site.language | upper | slice(0, 2) }}
      </a>
    {% endif %}
  {% endfor %}
</nav>

Site-Aware Queries

{# Current site content (automatic) #}
{% set posts = craft.entries().section('blog').all() %}

{# Explicit site specification #}
{% set enPosts = craft.entries().section('blog').site('mySiteEn').all() %}

{# Via PHP in module #}
$entries = Entry::find()
  ->section('blog')
  ->site(\Craft::$app->sites->getSiteByHandle('mySiteRu'))
  ->all();

Interface Translations

// translations/ru/site.php
return [
  'Read more' => 'Читать далее',
  'Published on {date}' => 'Опубликовано {date}',
];

In Twig:

{{ "Read more" | t('site') }}
{{ "Published on {date}" | t('site', { date: entry.postDate | date('d.m.Y') }) }}

Configuration of multi-site with 2–3 languages for existing project takes 2–4 days.