Concrete CMS CDN integration in 2026

Introduction

A Concrete CMS CDN integration can deliver theme stylesheets, JavaScript, images, and other public static files from edge servers closer to site visitors. Editable pages and dynamic application requests remain on the Concrete origin while the CDN handles repeat asset requests.

This guide uses Concrete's native AssetList to register CDN-hosted theme assets and an environment variable to keep the CDN Service Domain outside the theme code. The procedure was tested with Concrete CMS 9.5.2.

Before you start

  • This tutorial shows how to integrate a CDN service into a website. In this particular demo example we will use:
    • barsoom-cdn.cdnsun.org as the CDN Service Domain, and
    • https://barsoom.cdnsun.org as the website URL (i.e. barsoom.cdnsun.org is the Origin Domain).
  • Please visit the Services/How-To section to obtain your CDN Service Domain.
  • Before you take any steps please back up your files and database.
  • To integrate a CDN service on https:// website the CDN service must have SSL enabled.
  • If your website embeds custom fonts then please first enable CORS for them.
  • Before you take any steps please make sure that your CDN Service Domain is ready-to-use here.

Create CDN Static service

Please refer to Creating a CDN Static service for more details.

How to enable CDN in Concrete CMS

  1. Add the complete HTTPS URL of the CDN Service Domain to the environment used by the Concrete application:
    CDN_BASE_URL=https://barsoom-cdn.cdnsun.org

    Keeping the value outside the application code lets development, staging, and production use different CDN Service Domains without changing theme files.

  2. Open application/bootstrap/app.php. Import Concrete's asset classes, normalize the environment value, and define the public path of the active theme:
    use Concrete\Core\Asset\Asset;
    use Concrete\Core\Asset\AssetList;
    
    $cdnBaseUrl = rtrim((string) getenv('CDN_BASE_URL'), '/');
    $themePath = '/application/themes/my_theme';
    $assetList = AssetList::getInstance();

    Replace my_theme with the handle of the active theme. Keep its CSS, JavaScript, and images inside the theme directory under Concrete's public document root.

  3. In the same bootstrap file, register the theme stylesheet and JavaScript file with unique AssetList handles:
    $assetList->register(
        'css',
        'my-theme-cdn',
        $cdnBaseUrl !== ''
            ? $cdnBaseUrl . $themePath . '/css/app.css'
            : 'themes/my_theme/css/app.css',
        [
            'local' => $cdnBaseUrl === '',
            'version' => '1.0.0',
        ]
    );
    
    $assetList->register(
        'javascript',
        'my-theme-cdn',
        $cdnBaseUrl !== ''
            ? $cdnBaseUrl . $themePath . '/js/app.js'
            : 'themes/my_theme/js/app.js',
        [
            'local' => $cdnBaseUrl === '',
            'version' => '1.0.0',
            'position' => Asset::ASSET_POSITION_FOOTER,
        ]
    );

    When CDN_BASE_URL is present, AssetList treats each absolute URL as a remote asset. When it is empty, the local theme paths remain available as a fallback. Change the version value when deploying a new asset revision.

  4. Open application/themes/my_theme/page_theme.php. Require both registered assets from the theme's registerAssets() method:
    public function registerAssets(): void
    {
        $this->requireAsset('css', 'my-theme-cdn');
        $this->requireAsset('javascript', 'my-theme-cdn');
    }

    Concrete now places the stylesheet and script tags in the normal header and footer output while using their URLs under the CDN Service Domain.

  5. Generate URLs for theme images and other assets that are not managed by AssetList from the same environment value. For example, add this near the top of a theme element:
    $cdnBaseUrl = rtrim((string) getenv('CDN_BASE_URL'), '/');
    $themeBaseUrl = $cdnBaseUrl !== ''
        ? $cdnBaseUrl . '/application/themes/my_theme'
        : $view->getThemePath();

    Then use the generated base URL in the markup:

    <img
        src="<?php echo h($themeBaseUrl . '/images/logo.svg'); ?>"
        alt="Company logo"
    >

    Apply this pattern only to public static files. Keep page URLs, forms, login routes, dashboard requests, and other dynamic application URLs on the origin.

  6. File Manager media: files managed through Concrete's File Manager use File Storage Locations rather than the theme AssetList. Configure a separate storage location with a public URL under the CDN Service Domain when those media files should also use the CDN.

  7. Open the public site and confirm that the frontend remains styled normally and static assets load from the CDN Service Domain.
    Styled Concrete CMS site loading CSS, JavaScript, and an image through the CDN Service Domain

Verify & Troubleshoot

  • View HTML source code of your web pages to verify that you are using CDN, you should see source attribute of your images, CSS, JavaScript, etc. beginning with your CDN Service Domain.
    Frontend HTML proof that static assets are loaded from the CDN Service Domain
  • Don't see your CDN Service Domain in the source code of your web pages? If your website is using any cache plug-in/mechanism then you might want to clear/flush its cache.
  • Having trouble with custom fonts? Please refer to Using custom fonts with CDN - setting CORS for more details.
  • Still having trouble? Check your CDN URLs using our content check tool or please refer to Debugging a CDN service for more hints.

Contact Us

            _____     _  _   
  ____     |  ___||  | \| || 
 |    \\   | ||__    |  ' || 
 | [] ||   | ||__    | .  || 
 |  __//   |_____||  |_|\_|| 
 |_|`-`    `-----`   `-` -`  
 `-`