ISV and Managed Packages

Skuid is an excellent choice for developing Salesforce apps as managed packages. But because Skuid pages are stored as data, and not as metadata, you’ll need some way to distribute the pages you’ve created in your managed package development environment along with the rest of your metadata components.

In this tutorial, we outline a three-step approach that enables you to easily distribute your pages along with your managed package and update your pages with every update to your managed package:

  1. Group your Pages into a “Module”
  2. Package the latest version of Pages in your Module into a StaticResource for distribution in your app
  3. Have your app leverage an Apex Post-Install Script to extract the latest versions of your Pages each time a new version of your app is installed


When using Skuid to create managed packages, do not use in-line resources within the package’s Skuid pages. Instead, store any and all custom JavaScript in **static resources.


If you are looking to learn how to create and distribute your managed package, read the Salesforce documentation on the subject:

Step 1: Grab the latest version of Skuid

Before using this tutorial, it is essential to have the latest Skuid version installed.

You can install the latest Skuid version from the Skuid releases page.

Step 2: Create and package pages in a module

For more information about how to do this, see create a module .

Step 3: Refresh your packaged Skuid Pages on install

The Skuid Pages which you have put into your “<Module>Pages” StaticResource can be automatically inserted/updated each time your customer installs your app, so that your customers will always have installed the latest version of your pages.

This is best done with an Apex Post-Install Script.

We’ll provide you with a sample Install Script class, as well as a Test Class that will give you 100% coverage.

(a) Create a Post-Install Script Apex Class

Create a new Apex Class called “InstallScript_<MyModule>”, with the following as its Body. The only part of this you will need to change is the NAMESPACE_PREFIX variable — replace “MusicLibrary” with your Module name.

public without sharing class InstallScript_MusicLibrary extends skuid.InstallScript {
 public static final String MODULE_NAME = 'MusicLibrary';
 public override void setModule(){
     this.moduleName = MODULE_NAME;
 public override void onInstallLogic(InstallContext ctx) {}

(b) Create a Unit Test class

Create a separate Apex Class called “UnitTests_SkuidModule”, and paste in the following code, after replacing “InstallScript_MusicLibrary” with the name of your Post Install Script Apex Class:

private class UnitTests_SkuidModule {
   private static String getModuleName() {
       return InstallScript_MusicLibrary.MODULE_NAME;
   private static InstallHandler getInstallScript() {
       return new InstallScript_MusicLibrary();

   private static testMethod void InstallScript_TestInstallProcess() {


     // Load up our controller
     InstallHandler ctl = getInstallScript();
     // Test our install with a null version
     Test.testInstall(ctl, null);


     List<skuid__Page__c> pages = [
       select id, name
       from skuid__Page__c
       where skuid__Module__c = :getModuleName()



   private static testMethod void PageTrigger_PreventProtectedPageModifications() {
     skuid__Page__c test2 = new skuid__Page__c(
     Name = 'UnitTest234',
             skuid__Module__c = getModuleName(),
     skuid__Layout__c = '<skuidpage/>'
     Exception exCaught;
     try {
     insert test2;
     } catch (Exception ex) {
     exCaught = ex;


(c) Associate your Post-Install Script to your Managed Package


Step 6: Prevent your customers from modifying your default pages


In order to prevent your customers from messing with your principal / default pages and royally, irreparably messing up your app, you should include an Apex Trigger on the Skuid Page object which “Protects” your packaged Skuid Pages from being edited.

This is very easy to do using the skuid.utils.RegisterProtectedModule Apex API method. Just add a before insert/update/delete trigger like this on the Skuid Page object.


If you’d like to make edits to Skuid Pages in this org, you will need to deactivate this trigger while making changes, then reactivate it when uploading a new version of your package.

trigger Page on skuid__Page__c (before insert, before update, before delete) {

  // Register our module as one whose pages

  // no one should be able to insert/update/delete but us

  if (Trigger.isBefore) {






Alternatively, builders can unpackage pages manually in the Pages Tab.


Choose the pack(s) you want to unpack.