Build
Build Portal Widget — example output
Service Portal widget architecture
$ nowaikit run build-portal
███╗ ██╗ ██████╗ ██╗ ██╗ █████╗ ██╗ ██╗ ██╗██╗████████╗
████╗ ██║██╔═══██╗██║ ██║ ██╔══██╗██║ ██║ ██╔╝██║╚══██╔══╝
██╔██╗██║██║ ██║██║ █╗ ██║ ███████║██║ █████╔╝ ██║ ██║
██║╚████║██║ ██║██║███╗██║ ██╔══██║██║ ██╔═██╗ ██║ ██║
██║ ╚███║╚██████╔╝╚███╔███╔╝ ██║ ██║██║ ██║ ██╗██║ ██║
╚═╝ ╚══╝ ╚═════╝ ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ✦
NowAIKit — The #1 AI App for ServiceNow
- Running build-portal in direct mode (ollama)...
# Service Portal Widget Build Report
## Analysis Summary
Based on the existing `report-an-incident` widget data in the demo2 instance, I'll create an improved, properly architected incident reporting widget following Service Portal best practices.
---
## Step 1 — Requirement Analysis
| Aspect | Details |
|--------|---------|
| Data Needs | Incident type (Question, Request, Something is broken, Performance Issue), description, priority, urgency |
| User Interaction | Select incident type, enter description, submit ticket |
| Target Users | All instance users |
| Table | `incident` (primary), may need `task` for workflow |
| Widget Context | Main content area, form-based |
---
## Step 2 — Existing Widgets Assessment
The existing widget shows:
- Basic radio button layout
- Limited data binding patterns
- No proper server script or data broker integration
- Missing loading states and error handling
- Not using SCSS properly
Recommendation: Build a new improved version with proper architecture instead of cloning.
---
## Step 3 — Widget Architecture Design
```
WIDGET: incident-report-form
SERVER SCRIPT:
- data.formValues = {} (type, description, priority)
- data.loading = false
- data.error = null
- input handling: {action: "submit", type, description}
CLIENT CONTROLLER:
- c.submitForm() — submits incident creation
- c.onTypeChange() — updates related fields
- $scope.$on('incident-submit-result', handler)
HTML TEMPLATE:
- Header with widget title
- Radio group for incident type
- Textarea for description
- Priority dropdown
- Submit button
- Loading spinner
- Error message display
CSS:
- Responsive grid layout
- Bootstrap 3 classes
- BEM naming convention
OPTIONS:
- incident_type_label — text for type field
- require_description — boolean for mandatory description
- custom_priority_options — array of priority labels
```
---
## Step 4 — Server Script
```javascript
// Incident Report Form Widget
(function() {
function server() {
var data = {},
input = arguments[0]; // {action, ...}
// Default options from widget config
var options = options; // already set by portal engine
// Validate and process input
if (input && input.action === "submit") {
// Validate required fields
if (!input.type || !input.description) {
data.error = "Please complete all required fields";
data.loading = false;
return data;
}
// Validate input values
input.type = gs.getValue("incident", "type", input.type); // normalize
input.description = gs.trim(input.description);
input.description = input.description.substring(0, 65000); // max length
// Create incident
var incident = new GlideRecord('incident');
if (incident.add()) {
incident.type = input.type;
incident.short_description = input.description;
incident.insert();
if (incident.canRead()) {
... (562 more lines — full output truncated for screenshot)



