Nucleus .Net Core CMS

Extension Packaging

A Nucleus extension is installed by installing a package using the Extensions page.

An extension package is a zip file which contains all of the files needed for your extension, along with a Extension Packaging manifest package.xml file with instructions for Nucleus on how to install your components. If you use one of the Nucleus Visual Studio project templates, your project file will contain MSBuild commands which will automatically create a package (zip) file when you build your project using Release configuration.

Your extension is installed into the Extensions folder, in a sub-directory specified by the folderName attribute of your <component> element. A package often contains only one component, but can contain multiple components if needed.

Sample package.xml

Replace {generate-guid} with a guid that you have generated yourself. There are many web sites including https://www.guidgen.com/ which can generate Guids for you, as well as Visual Studio extensions, and the uuidgen command line tool available from the developer command prompt in Visual Studio.

The Visual Studio templates in the Nucleus Developer Tools automatically create a manifest (package.xml). The Nucleus Developer Tools also provide tools to manage file references in your package.xml file, so you can easily add files to your package.xml without having to edit the file manually.

<?xml version="1.0" encoding="utf-8" ?>
<package id="{generate-guid}" xmlns="urn:nucleus/schemas/package/1.0">
  <name>My Sample Extension</name>
  <version>1.0.0</version>
  <publisher name="your-company" url="http://your-site.com" email="support@your-domain" />
  <description>
    Sample Description.
  </description>
  <compatibility minVersion="3.0.0.0" maxVersion="3.*" />
  
  <components>
    <component folderName="MyExtension" optional="false">
      <file name="myextension.css" />
      
      <folder name="bin">
        <file name="MyExtension.dll" />        
      </folder>
      
      <folder name="Views">
        <file name="Viewer.cshtml" />
        <file name="Settings.cshtml" />
      </folder>      
    </component>
  </components>  
</package>

Manifest (package.xml) Elements

<package>

The root element of a manifest file is the <package> element. It must have a unique id (guid) and must include the xmlns="urn:nucleus/schemas/package/1.0" attribute.

The package element contains:

Name Required? Description
id Yes (attribute) A unique id (guid) to identify your installation package.
name Yes (element) Display name for your extension.
publisher Yes (element) Specifies publisher/support information for your extension. This is displayed to users during the installation process and in the extensions page.
description Yes (element) Description for your package. This is displayed to users during the installation process and in the extensions page.
compatibility No (element) The compatibility element defines which Nucleus versions that the extension is compatible with.
components Yes (element) The components element contains one or more <component> elements which provide installation instructions to Nucleus.

<publisher>

Name Required? Description
name No (attribute) Your company name.
url No (attribute) Your website url, or the Url for product information for your extension.
email No (attribute) A support email address for your extension.

<compatibility>

Name Required? Description
minVersion Yes (attribute) The minimum version of Nucleus supported by your extension in .NET System.Version format.
maxVersion No (attribute) The maximum version of Nucleus supported by your extension in .NET System.Version format.

The maxVersion attribute is not required, but is recommended. You can use '*' in place of any parts of the version.

<components>

The <components> element wraps one or more <component> elements.

<component>

Name Required? Description
folderName Yes (attribute) Specifies the folder within the /extensions folder that your files will be installed to.
optional Yes (attribute) Specifies whether the user can choose whether to install the component. This feature is not yet implemented.

The <component> element can contain any combination of: moduleDefinition, layoutDefinition, containerDefinition, controlPanelExtensionDefinition, file, folder, cleanup.

<moduleDefinition>

Modules must specify additional information for use by Nucleus.

Name Required? Description
id Yes (attribute) A unique id (guid) for your module.
friendlyName Yes (element) The display name for your module. This is displayed in the Nucleus user interface.
extension Yes (element) The extension name for your module. This should match the value of the [Extension] attribute on your controller classes.
viewController Yes (element) The class name for your view controller. If the controller name ends in Controller you can omit the Controller suffix.
settingsController No (element) The class name for your settings controller. If your settings controller class is the same class as your view controller, you can omit this setting.
viewAction Yes (element) The action in your controller class to call to display the end-user user interface.
editAction No (element) The action in your controller class to call to display the administrative/settings user interface.
categories No (element) A comma-separated list of module categories. In the Nucleus add module page, modules are listed beneath each category that they are assigned to.

The classTypeName is the assembly-qualified name for your controller class. You need to include the class name (including namespace) followed by a comma, then the assembly name (without .dll). You do not need to include version, culture or the public key token.

<layoutDefinition>

Layouts must specify additional information for use by Nucleus.

Name Required? Description
id Yes (attribute) A unique id (guid) for your layout.
friendlyName Yes (element) The display name for your layout. This is displayed in the Nucleus user interface.
relativePath Yes (element) The path to the layout view (razor page), relative to the root of your extension.

<containerDefinition>

Containers must specify additional information for use by Nucleus.

Name Required? Description
id Yes (attribute) A unique id (guid) for your container.
friendlyName Yes (element) The display name for your container. This is displayed in the Nucleus user interface.
relativePath Yes (element) The path to the container view (razor page), relative to the root of your extension.

<controlPanelExtensionDefinition>

Control panel extensions must specify additional information for use by Nucleus.

Name Required? Description
id Yes (attribute) Unique id (guid) for your control panel extension.
friendlyName Yes (element) Display name for your control panel extension. This is shown on-screen in the Manage or Settings control panel.
description Yes (element) Description for your control panel extension. This is shown on-screen in the Manage or Settings control panel.
controllerName Yes (element) The type name of your controller class. You can omit the root namespace and Controller suffix. For example, if your class name is MyExtension.MyControlPanelController, you can just specify MyControlPanel.
extensionName Yes (element) The name of the extension that the control panel extension belongs to. This value must match the value of the Extension() attribute in your controller class and is used for MVC routing.
scope Yes (element) Specifies whether the control panel extension is added to the Manage or Settings control panel. The allowed values are Site or Global. If your control panel extension saves settings for the current site, choose Site. If your settings are for the entire Nucleus instance, choose Global.
editAction Yes (element) The name of the Controller Action to run when the user selects the control panel extension. This action should render a View.
icon No (element) Specifies an icon to use in the manage or settings page. The icon value can be a character value, wrapped in a CDATA (example: ) from Material Symbols, an SVG element, or the relative path to an image that you install as part of your package. Whatever way you specify your icon, the rendered size will be rendered as a 44x44 pixels.

<file>

Specifies a file to copy during installation. The file must be present in the package, in a folder location that matches the structure represented by the manifest's file/folder elements. The file is copied to /Extensions/extension-name/folder, where folder is the root when the file element is a child of the <components>, or a sub-folder if the <file> element is a child of a <folder> element.

Name Required? Description
name Yes (attribute) File name.
uncompress No (attribute, boolean). If set to true, and the file is a .zip file, the file will be un-compressed into the target folder.

<folder>

Specifies a folder. <folder> elements can contain <file> elements or nested <folder> elements to represent the target folder structure within the /extensions/[folder-name] folder.

Name Required? Description
name Yes (attribute) Folder name, relative to the component folder name.

<cleanup>

Use the <cleanup> element to remove components during an upgrade when they are no longer needed.

The <cleanup> element can contain any number of moduleDefinition, layoutDefinition, containerDefinition, controlPanelExtensionDefinition, file or folder elements. Items within the <cleanup> element are removed during installation.

Package Signing

Package signing allows developers to digitally sign their extension packages. A valid signature ensures that the package has not been modified and can verify the identity of the developer. Package signing is optional.

Package signing was implemented in Nucleus version 3.1.

Using your own certificate

If you have a code signing certificate, you can use it to sign your extension packages. If you do not have a code signing certificate and you upload your package to the Nucleus Extensions store, the store will automatically sign the package with the Nucleus Extensions Store code signing certificate.

Your code signing certificate must be issued by a trusted Certificate Authority. The signing process involves the following steps:

  1. Obtain a Code Signing Certificate: Purchase a code signing certificate from a trusted Certificate Authority.
  2. Install your Certificate: Install the code signing certificate on your development (or build) machine.
  3. Sign Your Package: Use the code signing certificate to sign your package.

The extension build script module.build.targets is part of Nucleus developer tools. Starting with version 3.1, package signing is automatic. You can identify your code signing certificate in one of two ways:

Option 1: Add a <SigningCertificateIdentity> element to your project (.csproj) file:

Edit your project file and add a SigningCertificateIdentity element. A good place to add the element is within the <PropertyGroup Label="Nucleus"> element that is included in the Nucleus project templates.

<PropertyGroup Label="Nucleus">
  <!-- existing settings -->
  <SigningCertificateIdentity>1234567890abcdef1234567890abcdef12345678</SigningCertificateIdentity>
</PropertyGroup>

Option 2: Use an environment variable:

Set an environment variable named NUCLEUS_SIGNING_CERTIFICATE_IDENTITY to the identity of your code signing certificate. The extension build script automatically signs all of your packages using the code signing certificate that matches the identity you specify in the environment variable if your project file does not contain a <SigningCertificateIdentity> element.

The certificate identity can be your certificate thumbprint, serial number, subject key identifier or subject name. If more than one certificate in your certificate store matches the identity, signing will fail. The certificate thumbprint is the best identity to use as it is unique.

Nucleus Extensions Store Signing

Code signing certificates can be expensive, especially for small developers. To help with this, the Nucleus Extensions store automatically signs uploaded packages with its own code signing certificate before saving them. This ensures that packages uploaded to the store have not been modified, but does not

How it works

When you build your extension, a task in module.build.targets automatically signs the package using the specified code signing certificate by generating an encrypted hash value, using the private key from your certificate and the package contents (the files in your package zip file, including the package.xml (manifest file), but with signature elements of the package.xml file excluded). A signature element is automatically added to the package.xml file inside your package zip file containing the encrypted hash value, the signing date, and the certificate chain. The signature is validated by Nucleus platform when the package is installed or updated. Your original package.xml file is not modified during the signing process.

When your extension is installed by a user, the Nucleus extension manager validates the signature. If the signature is valid, a message is displayed identifying the developer who signed the package. If the signature is invalid, an error message is displayed and the package cannot be installed.

If an extension package is not signed, a warning message is displayed, but the package can still be installed.