In many Visual Builder Studio projects, custom AppUIs are developed to extend Oracle Fusion Cloud applications. Each custom AppUI typically lives in its own Git repository within the Visual Builder workspace. While Oracle provides a rich set of built-in actions and components, developers frequently need custom JavaScript logic — and the same helper functions often get duplicated across multiple AppUIs.
One of the powerful (and underutilized) features of Visual Builder is the ability to create shared JavaScript functions at the resource level and expose them for reuse across different AppUIs via dependencies. This eliminates code duplication, improves maintainability, reduces bugs from inconsistent implementations, and makes future updates much easier.
A very common example is the need to export data to CSV from various screens. Especially when using the Redwood Collection component, which includes a built-in export button — developers must provide custom code to generate and trigger the file download. Without a shared approach, the same download logic (handling headers, data formatting, Blob creation, etc.) gets copied into every AppUI that needs it.
Other typical candidates for sharing include:
The recommended pattern is to create a dedicated “Shared” AppUI that contains only JavaScript functions (no pages/UI), deploy it as an extension, and then add it as a dependency in any consuming AppUI.

export.js
define([
'ojs/ojlogger',
], (
Logger
) => {
'use strict';
function exportToCsv (params) {
try {
const {
headerLabels,
rows,
fileNamePrefix,
} = params;
const reportRows = [
headerLabels,
...rows,
];
const csvContent = "data:text/csv;charset=utf-8,\uFEFF" + reportRows.map(e => e.join(",")).join("\n");
const encodedUri = encodeURI(csvContent);
const link = document.createElement("a");
link.setAttribute("href", encodedUri);
link.setAttribute("download", `${fileNamePrefix} - ${getDateTimeString()}.csv`);
document.body.appendChild(link);
link.click();
} catch (e) {
Logger.error(e);
throw new Error("Failed to export to csv.", {
cause: e,
});
}
}
return {
exportToCsv
};
// Helpers --------------------------------------------------------------------------------------
function validateRequiredFields({ headerLabels, rows, fileNamePrefix }) {
const errors = [];
// Validate headerLabels
if (!Array.isArray(headerLabels)) {
errors.push('headerLabels must be a array');
} else if (headerLabels.length) {
errors.push('headerLabels cannot be empty');
}
// Validate rows
if (!Array.isArray(rows)) {
errors.push('rows must be a array');
} else if (rows.length) {
errors.push('rows cannot be empty');
}
// Validate fileNamePrefix
if (typeof fileNamePrefix !== 'string') {
errors.push('fileNamePrefix must be a string');
} else if (!fileNamePrefix.trim()) {
errors.push('fileNamePrefix cannot be empty');
}
if (errors.length > 0) {
throw new Error(`Validation failed: ${errors.join('; ')}.`);
}
}
function getDateTimeString() {
const date = new Date();
const year = date.getFullYear();
const month = `${date.getMonth() + 1}`.padStart(2, '0');
const seconds = date.getSeconds();
const minutes = date.getMinutes();
const hour = date.getHours();
const day =`${date.getDate()}`.padStart(2, '0');
return `${month}.${day}.${year}-${hour}:${minutes}:${seconds}`;
}
});
functions.json file (it appears after creating functions).
functions.json (or via UI if available in your VB version), ensure the desired functions are listed under modules and marked as accessible.
format.js, validate.js).
exportCSV function, passing headers and data from variables.
This pattern scales very well for medium/large Oracle Fusion extension projects with multiple AppUIs. Start small with 2-3 common utilities and expand the Shared module over time.
Have you already implemented shared JavaScript in Visual Builder? What kind of helpers do you find most useful to share?