Portlets, too, can be made highly customizable with a great architecture.
Back in March, we introduced a new development design pattern that offers a great deal of customization and maintainability. This approach extended NetSuite's Suitelets to the full range of a developer's ability by intelligently structuring HTML, CSS, and JavaScript for the Suitelet. The method also enforces good programming habits by isolating each component of the MVC architecture to its respective domain: logic is handled by the Suitelet, structure is handled by HTML, and all references to backend libraries are handled through asynchronous requests. This solution, with all of its benefits, is not limited to Suitelets. Because of the broad similarities shared with Suitelets, Portlets may also employ this same design pattern. Today, we will walk through a real-world example of a Portlet that uses this pattern and all considerations that come with Portlet development.
The concept for this Portlet originated in response to a need from a client's Merchandising Department. They had just received a great new solution for a Procure-to-Pay process which streamlined purchasing and improved productivity by up to 75%. Although the tool was great, there was a small problem: the users found it cumbersome to navigate the traditional NetSuite list view to access the Suitelet. They required a much faster approach which also provided specific data which catered to their needs. In particular, the portlet improved the following aspects compared to the traditional list view:
- Speed: Loading, reading, analyzing, navigating, and filtering this list is much faster because there is less data traveling to and from the server, as well as much of the processing happening right in the browser.
- Design: As much as we love NetSuite, the design language could be greatly improved for legibility and the interface could be more inviting. We redesigned the interface a bit to be more friendly.
- Accessibility: The fact that this is a Portlet – and available on the dashboard – means that from the moment the Merchandising Users log in, they are able to start a new PO or return to an incomplete one. Across hundreds of POs, this saves hours of inactivity per week!
Due to reasons involving intellectual property, this is a pared down version of the end product. However, the core details remain unchanged: this example provides the process of laying out the portlet, the files required, and any external libraries which are called. This utility consists of five major parts:
- The Backend Portlet – Queries data and generates everything you see on screen
- HTML – Structures the layout
- CSS – Styles the structure
- Third-Party Libraries – In this case, jQuery and DataTables.js for presentation and rapid filtering
- Client-side Portlet JavaScript – Initializes DataTables libraries
Portlet Script Configuration
This Portlet begins with the Backend Portlet Script. This is the only script file that must be configured as a NetSuite Script Record.
The script performs four important operations:
- The script queries the required information for display

- The script then formats the information for consumption for the DataTables library

- We store the data in an object that is accessible to the HTML page (line 4 in the following image)
- Display the Portlet

Step 3 may be substituted by performing an asynchronous server call upon initialization of the HTML file. We opted to initialize the data at Portlet initialization since this is happening on the server-side anyway and removes a step in the retrieval process.
The sequence in which the elements are created is important. We must treat this the same as any other HTML document, so we load HTML, JS Data Objects, and CSS as early as possible. We save initialization toward the end of the document so the initializer doesn’t get confused about missing DOM elements.
HTML Configuration
The HTML file is strikingly bare – as it should be in a DataTables example. The heavy lifting is done during client-side initialization and the file mostly contains references to static content (jQuery, BootStrap, DataTables CDNs).
The HTML document contains only static components. All dynamic components are written as new HTML during the Portlet initialization process.
Client Script Configuration
The next stage of this design is client-side initialization. Client-side initialization handles two main components:
The most important facet of the Client Script is that we ensure that the DataTables library accesses and displays the data. Using our approach (step 3 of the Portlet Script Configuration), we call on the object datatable_data and set that as our DataTables data.
Considerations
As with any great solution, this one is not without its drawbacks:
- Developer-Centric: Any changes to the table format or data requires developer intervention because nearly everything is handled through code. This makes it a lengthier process for the end-user to get what he wants in the look and feel.
- Initialization: This particular example loads all of the record data by querying the server and loading the results into a large JSON object on this page. A sizeable data set can result in a timeout or memory overflow issue. The developer must be cognizant of these potential issues when developing a client-side solution.
An alternative solution to this drawback is to load data through a backend Suitelet and call that data via an AJAX call. This method requires a bit more planning, but is still considerably more effective than the list view available. - References to Static Content: This issue is prevalent in any lengthy process; the developer must make the decision to use CDNs or store files in the NetSuite directory.
- NetSuite is Always Evolving: NetSuite warns developers to be aware of future releases when modifying any UI due to possible namespace collisions or DOM restructuring. Make sure to keep an eye on your solutions especially when dealing with HTML.
Note: Portlets are effectively iFrames and in an effort to dynamically fill available space, NetSuite offers the nlapiResizePortlet API. Though it only scales Portlets to larger dimensions, it does help to fill the gap for dynamic resizing.
Conclusion
In our real-world implementation, this utility was well-received as a powerful starting point of a complex procurement process. Users are able to quickly sort through information, filter by relevant departments and vendors, and continue from an incomplete procurement cycle.
Portlets are often overlooked in favor of native functionality or standalone Suitelet pages, but we hope that this technique encourages more developers to create interesting and powerful dashboard applications!
The script files for this demo are available to download. Please have a look and use the same pattern to design your own complex Portlet Apps and let us know what you’ve created!
Frequently Asked Questions About NetSuite Portlet Development
-
What is a NetSuite Portlet and how does it differ from a Suitelet?
-
A NetSuite Portlet is a dashboard widget that displays customized data and actions directly on the NetSuite home page, giving users instant access from the moment they log in. Unlike a Suitelet — which requires navigating to a specific URL — a Portlet lives on the dashboard and can be built using the same MVC design pattern, combining a backend Portlet Script, HTML, CSS, and client-side JavaScript.
-
How does MVC architecture improve NetSuite Portlet development?
-
MVC separates concerns across three layers: the backend Portlet Script handles logic and data queries, the HTML file manages structure, and CSS controls styling. This separation makes the solution easier to maintain, reduces the risk of namespace collisions with NetSuite's native UI, and allows each layer to be updated independently without breaking the others.
-
What are the five core components of a Portlet built with the MVC pattern?
-
A Portlet following the MVC architecture consists of: (1) the Backend Portlet Script — the only file configured as a NetSuite Script Record; (2) the HTML file for structure; (3) CSS for styling; (4) third-party libraries such as jQuery and DataTables.js; and (5) the Client-Side Portlet JavaScript, which initializes libraries and renders dynamic content in the browser.
-
What are the main performance advantages of a custom Portlet over the native NetSuite list view?
-
A custom Portlet built with DataTables reduces server round-trips by loading only the required fields, handles filtering and sorting in the browser, and presents a focused UI tailored to the user's workflow. In practice, placing the tool directly on the dashboard eliminates navigation overhead — saving hours of inactivity per week across high-volume processes like purchase order management.
-
What are the key limitations and risks of the MVC Portlet approach in NetSuite?
-
The three main drawbacks are: (1) developer dependency — any change to data structure or layout requires code intervention; (2) data volume risk — loading large JSON datasets at initialization can cause timeouts or memory overflows, mitigated by using an AJAX call to a backend Suitelet instead; and (3) NetSuite version risk — since the solution touches the UI layer, future releases may introduce namespace collisions or DOM changes that break the Portlet.
-
How does the DataTables library integrate with a NetSuite Portlet script?
-
The backend Portlet Script queries and formats the required data into a JSON object (datatable_data), which is made accessible to the HTML page at initialization. The client-side script then consumes this object as the DataTables data source, enabling fast in-browser sorting, filtering, and pagination. Because Portlets are effectively iFrames, all CDN references — including jQuery, Bootstrap, and DataTables — must be explicitly loaded within the Portlet's HTML file.
Talk to a NetSuite Expert
Tell us what you're working on, and we'll help you figure out the next step.



