CustomModule
NDE Customization package
Install / Use
/learn @ExLibrisGroup/CustomModuleREADME
CustomModule
✨ New Feature (9th November 2025): Support for all customization files in assets folder:
All files that are you are able to customize through the assets folder of your customization package are now supported for preview when using the custom module in proxy mode.
For example to preview your brand logo you can now place your customized logo file in the following path in your local project:
src/assets/images/library-logo.png
To start proxy mode use the command:
npm run start:proxy
Overview
The NDE Customization package offers options to enhance and extend the functionality of Primo’s New Discovery Experience (NDE). You can add and develop your own components, customize theme templates, and tailor the discovery interface to your specific needs.
Note: <mark>This branch includes updates and other improvements that are compatible with the December 2025 release of NDE.</mark>
Note: The NDE Customization package is currently available exclusively to Primo customers who have early access to the New Discovery Experience (NDE). Further availability will be announced in upcoming releases.
Prerequisites
Node.js and npm (Node Package Manager)
-
Verify Node.js and npm Installation:
- Open a terminal.
- Run the following commands to check if Node.js and npm are installed:
node -v npm -v - If installed, you will see version numbers. If not, you will see an error.
-
Install Node.js and npm (if not installed):
- Visit the Node.js download page.
- Download the appropriate version for your operating system (npm is included with Node.js).
- Follow the installation instructions.
Angular CLI
-
Verify Angular CLI Installation:
- Open a terminal.
- Run the following command:
ng version - If Angular CLI is installed, you will see the version and installed Angular packages.
-
Install Angular CLI (if not installed):
- After installing Node.js and npm, install Angular CLI globally by running:
npm install -g @angular/cli
- After installing Node.js and npm, install Angular CLI globally by running:
Development server setup and startup
Step 1: Download the Project
- Navigate to the GitHub repository: https://github.com/ExLibrisGroup/customModule.
- Download the ZIP file of the project.
- Extract the ZIP file to your desired development folder (e.g.,
c:\env\custom-module\).
Step 2: Install Dependencies
- Inside the
customModuledirectory, install the necessary npm packages:npm install
Step 3: Configuring proxy for and starting local development server
There are two options for setting up your local development environment: configuring a proxy or using parameter on your NDE URL.
-
Option 1: Update
proxy.const.mjsConfiguration:- Set the URL of the server you want to test your code with by modifying the proxy.const.mjs file in the ./proxy directory:
// Configuration for the development proxy const environments = { 'example': 'https://myPrimoVE.com', } export const PROXY_TARGET = environments['example']; - Start the development server with the configured proxy by running:
npm run start:proxy - Open your browser on port 4201 to see your changes. e.g: http://localhost:4201/nde/home?vid=EXLDEV1_INST:NDE&lang=en
- Set the URL of the server you want to test your code with by modifying the proxy.const.mjs file in the ./proxy directory:
-
Option 2: Parameter on NDE URL:
- Start your development server by running
npm run start - Add the following query parameter to your NDE URL:
useLocalCustomPackage=trueFor example:https://sqa-na02.alma.exlibrisgroup.com/nde/home?vid=EXLDEV1_INST:NDE&useLocalCustomPackage=true - This setting assumes that your local development environment is running on the default port
4201.
- Start your development server by running
Step 4: Code Scaffolding and Customization
Add Custom Components
-
Create custom components by running:
ng generate component <ComponentName>Example:
ng generate component RecommendationsComponent -
Update
selectorComponentMapincustomComponentMappings.tsto connect the newly created components:export const selectorComponentMap = new Map<string, any>([ ['nde-recommendations-before', RecommendationsComponentBefore], ['nde-recommendations-after', RecommendationsComponentAfter], ['nde-recommendations-top', RecommendationsComponentTop], ['nde-recommendations-bottom', RecommendationsComponentBottom], ['nde-recommendations', RecommendationsComponent], // Add more pairs as needed ]); -
Customize the component’s
.html,.ts, and.scssfiles as needed:src/app/recommendations-component/recommendations-component.component.htmlsrc/app/recommendations-component/recommendations-component.component.tssrc/app/recommendations-component/recommendations-component.component.scss
- All components in the NDE are intended to be customizable. However, if you encounter a component that does not support customization, please open a support case with us. This helps ensure that we can address the issue and potentially add customization support for that component in future updates.
Accessing host component instance
You can get the instance of the component your custom component is hooked to by adding this property to your component class:
@Input() private hostComponent!: any;
Accessing app state
- You can gain access to the app state which is stored on an NGRX store by injecting the Store service to your component:
private store = inject(Store);
- Create selectors. For example:
const selectUserFeature = createFeatureSelector<{isLoggedIn: boolean}>('user');
const selectIsLoggedIn = createSelector(selectUserFeature, state => state.isLoggedIn);
- Apply selector to the store to get state as Signal:
isLoggedIn = this.store.selectSignal(selectIsLoggedIn);
Or as Observable:
isLoggedIn$ = this.store.select(selectIsLoggedIn);
Automatic assets public path (assets/...)
If your custom module/add-on is hosted under a dynamic base URL, plain template URLs like:
<img src="assets/images/logo.png" />
may break, because the browser resolves them relative to the host page.
To fix this, we provide:
src/app/services/assets-public-path.directive.ts
This directive automatically rewrites any src / href that starts with assets/ (or /assets/) to:
__webpack_public_path__ + 'assets/...'
Import the directive in a component (Standalone) Add the directive to the component imports:
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { AssetsPublicPathDirective } from '../services/assets-public-path.directive';
@Component({
selector: 'custom-example',
standalone: true,
templateUrl: './example.component.html',
styleUrls: ['./example.component.scss'],
imports: [CommonModule, AssetsPublicPathDirective],
})
export class ExampleComponent {}
If the component is not standalone (NgModule-based), import and export the directive from a shared module, and include that module where your components are declared.
Use it in HTML After the directive is imported, you can use plain assets/... paths in templates:
<!-- Images -->
<img src="assets/images/logo.png" alt="Logo">
<!-- Icons / SVG -->
<img src="assets/homepage/clock.svg" alt="Clock">
<!-- Links to files -->
<a href="assets/files/help.pdf">Help</a>
Supported attributes/elements (common cases):
img[src]
source[src]
script[src]
link[href]
a[href]
Accessing app router
- You can gain access to the app router service by injecting the SHELL_ROUTER injection token to your component:
import {SHELL_ROUTER} from "../../injection-tokens"; //the import path may vary on your project
private router = inject(SHELL_ROUTER);
- Listening for router navigation events. For example:
this.routerSubscription = this.router.events.subscribe((event) => {
if (event instanceof NavigationEnd) {
console.log('Tracking PageView: ', event.urlAfterRedirects);
}
});
Translating from code tables
You can translate codes in your custom component by using ngx-translate (https://github.com/ngx-translate/core).
- If you are using a stand alone component you will need to add the TranslateModule to your component imports list.
- In your components HTML you can translate a label like so:
<span>This is some translated code: {{'delivery.code.ext_not_restricted' | translate}}</span>
Creating your own color theme
The NDE theming is based on Angular Material. We allow via the view configuration to choose between a number of pre built themes.

If you want to create your own theme instead of using one of our options follow these steps:
- Create a material 3 theme by running:
You will be prompted to answer a number of questions like so:ng generate @angular/material:m3-theme
? What HEX color should be used to generate the M3 theme? It will represent your primary color palette. (ex. #ffffff) #1eba18
? What HEX color should be used represent the secondary color palette? (Leave blank to use generated colors from Material)
? What HEX color should be used represent the tertiary color palette? (Leave blank to use generated colors from Material)
? What HEX color should be used represent the neutral color palette? (Leave blank to use generated colors from Material)
? What is the directory you want to p
Related Skills
node-connect
342.5kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
85.3kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
342.5kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
qqbot-media
342.5kQQBot 富媒体收发能力。使用 <qqmedia> 标签,系统根据文件扩展名自动识别类型(图片/语音/视频/文件)。
