IPackage IPackage.Build(IFluentBuilder fluentBuilder)
        {
            // All CMS manager assets will be contained in a single module

            var module = fluentBuilder.BuildUpModule()
                         .Name("cms_manager")
                         .AssetDeployment(AssetDeployment.PerModule)
                         .Build();

            // Build the API services

            fluentBuilder.BuildUpService(null, typeof(LiveUpdateService))
            .Name("liveUpdate")
            .Route(_configuration.ServiceBasePath + "live-update/", new [] { Method.Get, Method.Post, Method.Delete }, 0)
            .RequiredPermission(Permissions.View, false)
            .CreateComponent("liveUpdateClient")
            .DeployIn(module)
            .Build();

            fluentBuilder.BuildUpService(null, typeof(CrudService))
            .Name("crud")
            .Route(_configuration.ServiceBasePath + "crud/", new [] { Method.Get, Method.Post, Method.Put, Method.Delete }, 0)
            .CreateComponent("crudClient")
            .DeployIn(module)
            .Build();

            fluentBuilder.BuildUpService(null, typeof(ListService))
            .Name("list")
            .Route(_configuration.ServiceBasePath + "list/", new [] { Method.Get, Method.Post }, 0)
            .CreateComponent("listClient")
            .DeployIn(module)
            .Build();

            fluentBuilder.BuildUpService(null, typeof(VersionsService))
            .Name("versions")
            .Route(_configuration.ServiceBasePath + "versions/", new [] { Method.Get, Method.Post, Method.Put, Method.Delete }, 0)
            .CreateComponent("versionsClient")
            .DeployIn(module)
            .Build();

            fluentBuilder.BuildUpService(null, typeof(HistoryService))
            .Name("history")
            .Route(_configuration.ServiceBasePath + "history/", new [] { Method.Get }, 0)
            .CreateComponent("historyClient")
            .DeployIn(module)
            .Build();

            fluentBuilder.BuildUpService(null, typeof(SegmentTestingService))
            .Name("segmentTesting")
            .Route(_configuration.ServiceBasePath + "segment-testing/", new [] { Method.Get, Method.Post, Method.Put, Method.Delete }, 0)
            .CreateComponent("segmentTestingClient")
            .DeployIn(module)
            .Build();

            // Load templates and accumulate all of the CSS and JS assets

            var scriptModules = new List <string>();

            LoadScriptModule("updateNotifierModule", scriptModules);
            LoadScriptModule("dataModule", scriptModules);
            LoadScriptModule("validationModule", scriptModules);
            LoadScriptModule("viewsModule", scriptModules);
            LoadScriptModule("filtersModule", scriptModules);
            LoadScriptModule("genericComponentsModule", scriptModules);
            LoadScriptModule("displayOnlyComponentsModule", scriptModules);
            LoadScriptModule("fieldEditorComponentsModule", scriptModules);
            LoadScriptModule("elementEditorComponentsModule", scriptModules);

            // Load templates that are directly loaded into regions

            var less = new StringBuilder();

            var cmsManagerTemplatePath = AddTemplate("CmsManager", less, scriptModules);
            var debugToolsTemplatePath = AddTemplate("DebugTools", less, scriptModules);

            // Load Vue temlates that are dynamically constructed in JavaScript

            AddTemplate("EnvironmentSelector", less, scriptModules);
            AddTemplate("WebsiteVersionSelector", less, scriptModules);
            AddTemplate("UserSegmentSelector", less, scriptModules);
            AddTemplate("SegmentationScenarioSelector", less, scriptModules);
            AddTemplate("SegmentationTestSelector", less, scriptModules);
            AddTemplate("PageSelector", less, scriptModules);
            AddTemplate("LayoutSelector", less, scriptModules);
            AddTemplate("RegionSelector", less, scriptModules);
            AddTemplate("ComponentSelector", less, scriptModules);

            AddTemplate("UserSegmentDisplay", less, scriptModules);
            AddTemplate("ContextDisplay", less, scriptModules);

            AddTemplate("EnvironmentEditor", less, scriptModules);
            AddTemplate("WebsiteVersionEditor", less, scriptModules);
            AddTemplate("SegmentationScenarioEditor", less, scriptModules);
            AddTemplate("PageEditor", less, scriptModules);
            AddTemplate("LayoutEditor", less, scriptModules);
            AddTemplate("RegionEditor", less, scriptModules);
            AddTemplate("ComponentEditor", less, scriptModules);

            AddTemplate("UpdateNotifierLog", less, scriptModules);

            // Output JavaScript and CSS assets in a module

            var assetsComponentBuilder = fluentBuilder.BuildUpComponent(null)
                                         .Name("assets")
                                         .DeployIn(module)
                                         .RenderInitialization("cms-manager-init", "<script>ns." + NamespaceName + ".init();</script>")
                                         .DeployLess(less.ToString());

            foreach (var scriptModule in scriptModules)
            {
                assetsComponentBuilder.DeployScript(scriptModule);
            }

            var assetsComponent = assetsComponentBuilder.Build();

            // This region of the CMS manager is for editing pages of the website
            var editorRegion = Build(module, assetsComponent, fluentBuilder.BuildUpRegion()
                                     .Name("editor")
                                     .NeedsComponent("crudClient")
                                     .NeedsComponent("listClient")
                                     .NeedsComponent("versionsClient")
                                     .NeedsComponent("historyClient")
                                     .NeedsComponent("segmentTestingClient")
                                     .AddTemplate(cmsManagerTemplatePath));

            // This region of the CMS manager is for debug tools
            var toolsRegion = Build(module, assetsComponent, fluentBuilder.BuildUpRegion()
                                    .Name("tools")
                                    .AddTemplate(debugToolsTemplatePath));

            // To have the CMS manager fill the whole page make this the page layout
            var managerLayout = fluentBuilder.BuildUpLayout()
                                .Name("manager")
                                .ZoneNesting("editor,tools")
                                .Region("editor", editorRegion)
                                .Region("tools", toolsRegion)
                                .Build();

            // To have the CMS manager occupy a region of the page put this region
            // into a zone of the page layout
            var managerRegion = fluentBuilder.BuildUpRegion()
                                .Name("manager")
                                .Layout(managerLayout)
                                .Build();

            // If the ManagerPath is configured then add a page to the website that
            // contains the CMS manager
            if (!string.IsNullOrEmpty(_configuration.ManagerPath))
            {
                fluentBuilder.BuildUpPage()
                .Name("cmsManager")
                .Route(_configuration.ManagerPath, 0, Method.Get)
                .Layout(managerLayout)
                .Build();
            }

            return(this);
        }