An application (app, sometimes called an _add-on_) extends the functionality of the Episerver website with initializable modules, gadgets, visitor group criteria, virtual path providers, page and search providers, and so on. This topic provides guidelines and recommendations for developing and packaging custom apps.
## Develop an app
Episerver and third-parties can develop app modules. An app is packaged as a NuGet package and follows a set of guidelines. The module system (or Shell modules) defines the folder structure and configuration system that an app uses, and is a built-in module system to extend the user interface. You can use it to build any module.
Episerver loads and processes app assemblies during site start-up, so an app can contain components like InitializableModule and plug-ins that require assembly scanning. Use the following guidelines to develop an app.
Place the app in a **Shell module directory**. For example, a Google Maps dynamic content app could reside in _~/modules/EPiServer.Samples.AddOns.GoogleMaps/_.

Reference assembly names in Web Forms pages, controls, and strongly typed MVC views of your apps.
**User control example**
**Strongly typed MVC view example**
Make paths to included resources relative to the app directory in the modules directory. The EPiServer.Shell.Paths class provides new methods to resolve URLs to resources located in the directory of the corresponding Shell module directory. A specified assembly (or any type from the app assemblies) identifies the app module.
**Resolving a path to an app resource by type**
**Resolving a path to a client resource**
Use relative paths to resources in app GUI plug-ins. **Plug-in attributes** provides new properties for that.
`
GuiPlugInAttribute.UrlFromModuleFolder
` – Define the URL to a control relative to the app module directory (found in the `EPiServer.PlugIn
` namespace).`
GuiPlugInAttribute.Url
` – Returns a resolved URL to an app control (found in the `EPiServer.PlugIn
` namespace).`
DynamicContentPlugInAttribute.ViewUrlFromModuleFolder
` – Define the URL to view a control for this dynamic content, relative to the app module directory (found in the `EPiServer.DynamicContent
` namespace).`
DynamicContentPlugInAttribute.ViewUrl
` – Returns a resolved URL to a view control (found in the `EPiServer.DynamicContent
` namespace).
You should define paths to **plug-in resources** as follows:
The path to the template file relative to the module folder should be in the `
Path
` property of the `RenderDescriptorAttribute
` on a page or a block template. The path should not be application-relative and not an absolute virtual path. The system resolves the virtual path to the content template file in the app directory. **Example**The resolved virtual path to the block template in a public app is _~/modules/<package ID>/Blocks/SampleBlockControl.ascx_.
The directory structure where template files reside, must follow the namespace convention if the `
Path
` property of `RenderDescriptorAttribute
` of a page or a block template is not set.See [Content model and views](🔗) .
Use the Episerver platform `
LocalizationService
` model with embedded language files for apps and assemblies that belong to Shell modules are automatically scanned for XML localization data. You also can use standard resource files.You can add required client resources on the page without modifying the templates, to inject styles, scripts or HTML on the pages.Â
You should version [client resources](🔗) to avoid caching problems when upgrading to a new version. .
Keep configuration changes to a minimum.
Configuration file and source code transformation are not supported.
PowerShell scripts and other tools are not supported.
Third-party apps cannot use an `
EPiServer
` namespace.
## Create an app package
Create a package from an assembly, a project or a convention-based working directory. See the [tools and documentation available from Nuget](🔗) to create a NuGet package.
Create the NuGet (nuspec) manifest by running the following command: **nuget spec**
Edit the _nuspec_ file and specify the information for your app package. If you are going to create your package from a project, use replacement tokens for the app package ID, version, author, and description. The following nuspec file example is for the Google Maps app:
### Public and protected apps
Public and protected apps differ in user access rights required to access the app files and routes.
**Protected** – Accessed only by the authorized users within **WebEditors** or **WebAdmins** roles. Consider making your app protected because it is a more secure approach.
**Public** – Accessed by any site user including anonymous users. Make your app public only if it provides content such as page templates, dynamic content rendering controls, public MVC views or client resources for the site visitor. If the size of the public content is relatively small, consider including it as an embedded resource in one of the apps binaries and make the app protected instead.
Public and protected apps have the following file locations and virtual paths:
Public app files, reside in the _modules_ folder by default located under the site root (the same path where all the public shell modules are located).
Public apps have a default virtual path starting from _~/modules/<package ID>/_.
Protected app files are located by default in _~/modules/\_protected/<package ID>/_.
Protected apps have a default virtual path starting from _~/<EPiServerProtectedPath>/modules/<package ID>/_ (for example _/EPiServer/Modules/<package ID>)_.
Note
Mark protected apps with the `
EPiServerModulePackage
` tag. Mark public apps with the `EPiServerPublicModulePackage
` tag.
### Dependencies and versioning
If your app requires you to install other apps on the site, add these to the list of dependencies in the _nuspec_ file to ensure that the other apps get installed when a user chooses to install your app. If the other apps cannot install to the environment, the installation aborts.
App packages must follow the [Semantic Versioning (SemVer)](🔗) scheme for versioning for the package itself to have a common understanding of which versions are compatible and which versions introduce breaking changes.
**SemVer** means having version numbers in the format _Major.Minor.Patch_, where the different segments correspond to:
**Major** – Breaking changes.
**Minor** – New features, but backwards compatible.
**Patch** – Backwards-compatible bug fixes only.
For example, if you require the feature set from version 1.3 of a dependency, set _\[1.3,2)_ as the version range, which accepts versions that are known to be compatible. When version 2.0 is released, it may or may not turn out to be compatible. If it is compatible, the version range can be changed to _\[1.3,3)_ in the next update. Otherwise the version range, after your code base is changed to run with version 2.0 of this dependency, is changed to something like _\[2.0,3)_. See [NuGet Docs](🔗) for version ranges in NuGet.
### Prerequisite dependency on an installed product
A prerequisite is a dependency that your app has to a product that is not yet installed, but must be installed for the app package to function. Assemblies installed in the application and system packages (for example, _EPiServer.CMS.Core_ and _EPiServer.CMS.UI_) are represented in the NuGet environment as virtual packages to which you can add dependencies. The names and version numbers of these packages are based on the assembly names and assembly versions. Dependencies must be actual NuGet packages for Visual Studio-enabled apps.Â
### Package directory structure
The package directory structure should follow the conventions in NuGet Docs. If you are going to create the package from a Visual Studio project, run the following command:
Alternatively, if you have prepared a NuGet manifest (_nuspec_) file and a convention-based directory structure for the actual package content, you can create the package with the following command:
### Use NuGet Package Explorer
Use the **NuGet Package Explorer GUI** tool to view metadata and create new packages. The following example shows the Google Maps app package opened in NuGet Package Explorer.

## Develop Visual Studio-enabled apps
You should attach dependencies to ordinary NuGet packages rather than as references to assemblies. In most scenarios, the primary assembly of the NuGet package matches the ID of the package.
Content files must have a path in the _nuspec_ as they appear on site, which implies that paths for content files should include _\\modules\\<packageid>_ for public apps. For example:
...and _modules\\\_protected\\<packageid>_ for protected apps. For example:
The NuGet package should contain a _module.config_ file in the package root (for example, `<file src="module.config" target="Content\\modules\\<packageId>\\module.config" />
`). The _module.config_ must contain a **tags** attribute that contains either `EPiServerModulePackage
` or `EPiServerPublicModulePackage
`, which is is required for the Episerver app user interface to distinguish the app from other shell modules. The _module.config_ also can contain a description attribute that describes the module in the app UI. It also should list assemblies the package contains. The following code sample shows a minimal _module.config_.
The `EPiServer.Packaging.Converter
`Â converts old apps to a format that lets the app be installed from Visual Studio. A readme file describes how to use the converter.
### ZIP compressed content
Deliver content in your app as a compressed zip archive by compressing the whole content structure below the package folder to a zip file. Give it the same name as the package and place within the package directory, for example:
Optimizely scans module directories during startup and adds a virtual path provider for any archive that is found as long as it follows this convention.
Using this feature is NOT recommended if your module contains large files because the content is kept in a memory cache. However, it is useful if you are developing a Visual Studio app that contains many small files because it prevents the module from adding the files to the Visual Studio project of the developers installing your app. If you want to debug files in an app that uses this functionality, extract the archive into its current directory and delete or rename the archive.
## Execute custom code for apps
Execute custom code at the following extension points, when certain actions are performed:
After the app installation
After an app update
Before an app uninstallation (does not trigger when uninstalling an app using Visual Studio)
If your app requires executing custom code only on web application start-up and does not need to be notified about installations, updates or deletions, consider using `IInitializableModule
`.
### Base class for your custom code
To execute custom code when the status of the app package changes, the custom code should include a class inherited from the abstract class `EPiServer.Packaging.PackageInitializer
` in the _EPiServer.Packaging_ assembly:
The `PackageInitializerclass
` combines the `IInitializableModule
` and `IPackageNotification
` interfaces. Inheritors of this class are instantiated and executed by the Optimizely Framework initialization system in the same manner as for the regular `IInitializableModule
`.
The `Initializemethod
` in `PackageInitializer
` checks if the app (package ID) containing the assembly with the inheriting class is newly installed, and calls the `AfterInstall
` Â method if necessary, or if the app is newly updated calls `AfterUpdate
` Â if necessary.
When overriding the Initialize method, you should call the base implementation before proceeding with the initialization to ensure that the `AfterInstall
` and `AfterUpdate
` methods are executed before the initialization.
The `BeforeUninstallmethod
` is called before the package contents are removed, when the user clicks the **Uninstall** button in the app system.
### AfterInstall method
The `AfterInstall
` method is called after the app installation is complete and only the first time the application starts, (as opposed to the `Initialize
` method which is called each time the application starts).
Do the following to get custom code executed after an app installation:
Create a class that inherits from `
EPiServer.Packaging.PackageInitializer
`.Decorate the class with a \`\[ModuleDependency(typeof(EPiServer.Packaging.PackagingInitialization))\]\` attribute.
Override the `
AfterInstall
` method and put you custom code inside this method.If the app requires custom initialization:
Override the `
Initialize
` method.Call `
base.Initialize
` in the overridden method body.Place your custom initialization code after the `
base.Initialize
` method call.
The app installation and the point where the `AfterInstall
` method is called:
The user clicks **Install** in the app management user interface.
The app is deployed to the site.
Site restart occurs automatically, or the user clicks **Restart** in the app management user interface.
On system startup, the app assemblies load into the AppDomain.
The `
Initialize
` method is called for the initializable modules.The `
AfterInstall
` method is called from base.Initialize.
### AfterUpdate method
The `AfterUpdate
` method executes after the app update is complete and is called only the first time the application starts after updating an app.
Do the following to execute custom code after an app update:
Create a class that inherits from `
EPiServer.Packaging.PackageInitializer
`.Decorate the class with \`\[ModuleDependency(typeof(EPiServer.Packaging.PackagingInitialization))\]\` attribute.
Override the `
AfterUpdate
` method and put you custom code inside this method.If the app requires custom initialization:
Override the `
Initialize
` method.Call `
base.Initialize
` in the overridden method body.Place your custom initialization code after the `
base.Initialize
` method call.
The app installation and the point where the `AfterUpdate
` method is called:
The user clicks **Update** in the app management user interface. The updated app is deployed to the site.
Site restart occurs automatically or the user clicks **Restart** in the app management user interface.
On system startup the app assemblies are loaded into the AppDomain.
The Initialize method is called for the initializable modules.
AfterUpdate is called from `
base.Initialize
`.
### BeforeUninstall method
The `BeforeUninstall
` method executes immediately after the user clicks **Uninstall** in the app management user interface, but before the actual uninstallation takes place. If an exception occurs in the `BeforeUninstall
` method, the uninstallation is aborted. It does not trigger when uninstalling an app using Visual Studio.
Do the following to execute custom code before app unistallation:
Create a class that inherits from `
EPiServer.Packaging.PackageInitializer
`.Override the `
BeforeUninstall
` method and put you custom code inside this method.
The process of app uninstallation:
The user clicks **Uninstall** in the app management user interface.
`
BeforeUninstall
` is called.Actual removal of the app is performed (but apps assemblies are still loaded in the AppDomain).
Restart occurs automatically, or the user clicks **Restart** in the app management user interface.
Assemblies from the deleted app are no longer loaded into the AppDomain.
### Manage dependencies
If an app is dependent on other systems or apps, you need to indicate these dependencies in the `ModuleDependencies
` element so that initialization methods are called after those of the listed dependencies. To load the app automatically when a dependency is loaded, set the type attribute to `RunAfter
`. This is needed for CMS UI apps, otherwise they are not loaded.