---
title: Configure Shell modules
slug: cms-12/docs/configuring-shell-modules
docTags: 
createdAt: 2026-08-10T15:56:02.000Z
---

There are two different kinds of shell modules: protected and public. Protected ones are secured by default, while public ones are accessible to all users. The different types of modules are configured through `PublicModuleOptions` and `ProtectedModuleOptions` in the [CmsUI section](docId:0GoHvX6z1ZvAMPqHS0iK-).

You can add modules to Optimizely Content Management System (CMS) by configuring the options for automatic discovery or by explicitly adding them by configuring the corresponding option through code or `appSettings.json` file.

Example of configuration from `appSettings.json`:

```json
"EPiServer": {
  "CmsUI": {
    "ProtectedModule": {
      "Items": [{
        "Name": "MySecureModule"
      }]
    }
  }
}
```

Example of configuration from code:

```csharp
services.Configure<ProtectedModuleOptions>(o => o.Items.Add(new ModuleDetails { Name = "MySecureApp" }));
```

Install public modules in the `modules` folder; install protected modules in the `modules\_protected` folder. Treat the web application as a "default" shell module but with path `.\` (the application root). To add settings for the "default" shell module, add a [module.config](https://world.optimizely.com/documentation/developer-guides/CMS/configuration/Configuring-moduleconfig/)  to the root of the application.

## Options configuration

You can configure a module through options like resource paths and assemblies. However, you should have a corresponding [module.config](docId\:RZVSXXKVRj26ep5OsAUB-) for a shell module.

### Module manifest

Each module can have a manifest file (`module.config`) in the module's root directory, where you can specify further module-specific settings.

### Security

A shell module can specify which security policy you should apply to requests for the module by assigning attribute `authorizationPolicy` in `module.config` with the name of the policy to apply. If the module does not explicitly specify a policy, is by default no policy applied to public modules, while a policy named `episerver:defaultshellmodule` (requires the user to be in any of the roles defined in `CmsPolicyOptions.DefaultShellModuleRoles` which by default is `WebEditors`, `WebAdmins`, `CmsAdmins` and `Administrators`) is applied to protected modules.

Example of assigned policy `episerver:cmsedit` for the module through `module.config`:

```xml
<?xml version="1.0" encoding="utf-8" ?>
<module authorizationPolicy="episerver:cmsedit">
  <assemblies>
    <add assembly="MyModuleAssembly" />
  </assemblies>
</module>
```

### Discovery

`ProtectedModuleOptions` and `PublicModuleOptions` have a property `AutoDiscovery` that can be configured to specify how you should perform module discovery. By default, it is `PublicModuleOptions.AutoDiscovery` set to `AutoDiscovery.Modules` meaning it scans the `modules` folder for modules, which will then be automatically registered. The default for `ProtecedModuleOptions.AutoDiscovery` is set to `AutoDsicovery.Minimal` meaning all protected modules need to be explicitly registered. The CMS built-in modules like edit and admin mode are registered when `AddCms` is called.

## Version client resources

You can specify the relative path to client resources in the module folder using the optional `clientResourceRelativePath` attribute of the module node in the module manifest file, [module.config](docId\:RZVSXXKVRj26ep5OsAUB-). The module client resource path is equal to the resource base path when `clientResourceRelativePath` attribute is not defined, or the value is an empty string. Otherwise, the system combines the module resource base path and the relative path specified in `clientResourceRelativePath` attribute. The resulting value is used as the module client resource path if it is a valid absolute path.

You can implement versioning to avoid client-side caching issues without individually changing all resource file references.

**Example module directory structure**

![Example module directory structure](https://api.archbee.com/api/optimize/BrbvVORKJ5iIeSMZye5kI/lP57UUVPrSGREyU9mPp0d-20260722-184801.png "clientresourcerelativepath.png")

**Example module.config**

```xml
<?xml version="1.0" encoding="utf-8"?>
<module clientResourceRelativePath="1.5.0" >
  <!-- ... -->
  <clientResources>
    <add location="myScript" path="ClientResources/script.js" resourceType="Script" />
    <add location="myStyles" path="ClientResources/styles.css" resourceType="Style" />
  </clientResources>
  <!-- ... -->
</module>
```

- Resource base path – `~/modules/SampleModule/`
- Client resource path – `~/modules/SampleModule/1.5.0/`
