---
title: Configure Shell modules
slug: cms-13/docs/configure-shell-modules
docTags: 
createdAt: 2026-07-30T20:22:07.530Z
---

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

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

Example configuration from `appSettings.json`:

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

Example 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](docId\:dI64jrVOXLd4rWo8gsedO) to the root of the application.

## Options configuration

Configure a module through options like resource paths and assemblies. A corresponding [module.config](docId\:dI64jrVOXLd4rWo8gsedO) file is recommended for each shell module.

### Module manifest

Each module has a manifest file (`module.config`) in the module root directory, where further module-specific settings are specified.

### Security

A shell module specifies which security policy to apply to requests by assigning the `authorizationPolicy` attribute in `module.config` with the name of the policy. If the module does not explicitly specify a policy, by default no policy is 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 `CmsEditors` and `CmsAdmins`) 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 specifies how module discovery is performed. By default, `PublicModuleOptions.AutoDiscovery` is set to `AutoDiscovery.Modules`, meaning it scans the `modules` folder for modules, which are then automatically registered. The default for `ProtectedModuleOptions.AutoDiscovery` is `AutoDiscovery.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

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\:dI64jrVOXLd4rWo8gsedO). The module client resource path equals the resource base path when the `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 the `clientResourceRelativePath` attribute. The resulting value is used as the module client resource path if it is a valid absolute path.

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

**Example module directory structure**

```text
Modules/
└── SampleModule/
    ├── {version}/
    │   ├── ClientResources/
    │   │   ├── Scripts/
    │   │   │   └── script.js
    │   │   ├── Styles/
    │   │   │   └── styles.css
    │   │   └── Images/
    │   │
    │   ├── bin/
    │   │   └── SampleModule.dll
    │   │
    │   ├── Views/
    │   │   ├── Shared/
    │   │   └── Components/
    │   │
    │   ├── Controllers/
    │   │
    │   ├── App_Data/
    │   │
    │   └── module.config
```

**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/`
