User GuideTenant Pages
Tenant Pages
Create custom portal pages for your customers and vendors
Tenant Pages
Tenant Pages allow you to create custom data views that appear in customer and vendor portals. Each page displays synced data in a configurable table format.
What is a Tenant Page?
A tenant page is a custom page that:
- Displays data from a specific dataset (synced from NetSuite)
- Appears in the customer/vendor portal sidebar
- Has configurable columns, filters, and sorting
- Respects row-level security (customers see only their data)
Page Properties
| Property | Type | Description |
|---|---|---|
id | string | Unique page identifier |
organization_id | string | Owner organization |
title | string | Display name in sidebar |
slug | string | URL path segment |
description | string | Optional page description |
icon | string | Sidebar icon identifier |
dataset_id | string | Source dataset/collection |
record_type | string | NetSuite record type |
tenant_id | string | Parent tenant identifier |
table_config | object | Table display configuration |
status | number | 1=Draft, 2=Active, 3=Inactive |
sort_order | number | Position in sidebar |
Page Status
| Value | Status | Description |
|---|---|---|
| 1 | Draft | Page is not visible |
| 2 | Active | Page is visible and accessible |
| 3 | Inactive | Page is hidden but preserved |
Creating a Tenant Page
Via Dashboard
- Navigate to Portal → Pages
- Click Create Page
- Configure page settings:
- Title and slug
- Dataset/record type
- Table columns
- Filters
- Set status to Active
- Click Save
Page Input
| Field | Required | Description |
|---|---|---|
title | Yes | Page display name |
slug | Yes | URL path (e.g., my-orders) |
dataset_id | Yes | Target dataset |
record_type | Yes | NetSuite record type |
tenant_id | Yes | Parent tenant ID |
table_config | Yes | Column and filter config |
description | No | Page description |
icon | No | Sidebar icon |
status | No | Default: 2 (Active) |
sort_order | No | Sidebar position |
Table Configuration
The table_config object defines how data is displayed:
interface TableConfig {
columns: TableColumn[];
filters?: TableFilter[];
pagination?: {
page_size: number;
};
sorting?: {
column: string;
direction: 'asc' | 'desc';
};
}Column Configuration
| Property | Type | Description |
|---|---|---|
key | string | Data field key |
label | string | Column header text |
type | enum | Data type for formatting |
sortable | boolean | Enable column sorting |
searchable | boolean | Include in search |
width | string | Column width (CSS) |
Column Types
| Type | Description | Example Display |
|---|---|---|
text | Plain text | "ABC Company" |
number | Numeric value | "1,234" |
date | Date formatting | "Jan 15, 2024" |
email | Email link | "user@example.com" |
phone | Phone formatting | "(555) 123-4567" |
boolean | Yes/No display | "Yes" / "No" |
currency | Money formatting | "$1,234.56" |
Filter Configuration
| Property | Type | Description |
|---|---|---|
key | string | Field to filter |
label | string | Filter label |
type | enum | Filter input type |
options | array | Options for select type |
Filter Types
| Type | Description |
|---|---|
text | Free text input |
select | Dropdown selection |
date | Date picker |
number | Numeric input |
Example Configuration
"My Orders" Page
{
"title": "My Orders",
"slug": "my-orders",
"dataset_id": "sale",
"record_type": "salesorder",
"table_config": {
"columns": [
{
"key": "tranid",
"label": "Order #",
"type": "text",
"sortable": true,
"searchable": true
},
{
"key": "trandate",
"label": "Date",
"type": "date",
"sortable": true
},
{
"key": "total",
"label": "Amount",
"type": "currency",
"sortable": true
},
{
"key": "status",
"label": "Status",
"type": "text",
"sortable": true
}
],
"filters": [
{
"key": "status",
"label": "Status",
"type": "select",
"options": [
{ "value": "pending", "label": "Pending" },
{ "value": "approved", "label": "Approved" },
{ "value": "shipped", "label": "Shipped" }
]
}
],
"pagination": {
"page_size": 25
},
"sorting": {
"column": "trandate",
"direction": "desc"
}
},
"status": 2,
"sort_order": 1
}Row-Level Security
Tenant pages automatically filter data based on the logged-in user's context:
| Portal Type | Filter Applied |
|---|---|
| Tenant | All records for the tenant |
| Customer | Records where entity = customer ID |
| Vendor | Records where entity = vendor ID |
Users only see data they are authorized to access.
Page Data
Each page has associated TenantPageData records:
| Property | Type | Description |
|---|---|---|
id | string | Unique record identifier |
tenant_page_id | string | Parent page |
ns_id | string | NetSuite internal ID |
customer_ns_id | string | Customer NetSuite ID (for filtering) |
data | object | Synced record data |
synced_at | string | Last sync timestamp |
Editing Pages
- Navigate to Portal → Pages
- Click on a page
- Modify settings
- Click Save
Editable Properties
| Property | Editable |
|---|---|
title | Yes |
slug | Yes |
description | Yes |
icon | Yes |
table_config | Yes |
status | Yes |
sort_order | Yes |
dataset_id | No |
record_type | No |
Deleting Pages
- Navigate to Portal → Pages
- Click Delete on the page
- Confirm deletion
Warning: Deleting a page also removes associated page data.
Page URLs
Pages are accessible at:
/portal/pages/{tenant_id}/{slug}Example:
/portal/pages/ACCT_123456/my-ordersSidebar Display
Active pages appear in the portal sidebar in sort_order sequence. Only pages with status = 2 (Active) are displayed.