Back to list
groeimetai

widget-coherence

by groeimetai

🤖 AI-powered ServiceNow development with 400+ MCP tools. Works with Claude, GPT, Gemini, Ollama & 75+ providers. Deploy widgets, manage incidents, automate workflows - all through natural language. Open-source Build Agent alternative.

42🍴 9📅 Jan 23, 2026

SKILL.md


name: widget-coherence description: This skill should be used when the user asks to "create a widget", "build a widget", "service portal widget", "sp_widget", "fix widget", "widget not working", "ng-click not working", or any Service Portal widget development. version: 1.0.0 tools:

  • snow_deploy
  • snow_update
  • snow_preview_widget
  • snow_widget_test
  • snow_find_artifact
  • snow_edit_artifact

Widget Coherence for ServiceNow Service Portal

Service Portal widgets MUST have perfect communication between Server Script, Client Controller, and HTML Template. This is not optional - widgets fail when these components don't talk to each other correctly.

The Three-Way Contract

Every widget requires synchronized communication:

1. Server Script Must:

  • Initialize ALL data.* properties that HTML will reference
  • Handle EVERY input.action that client sends via c.server.get()
  • Return data in the format the client expects

2. Client Controller Must:

  • Implement EVERY method called by ng-click in HTML
  • Use c.server.get({action: 'name'}) for server communication
  • Update c.data when server responds

3. HTML Template Must:

  • Only reference data.* properties that server provides
  • Only call methods defined in client controller
  • Use correct Angular directives and bindings

Data Flow Patterns

Server → Client → HTML

// SERVER SCRIPT
(function() {
  data.incidents = [];
  data.loading = true;

  var gr = new GlideRecord('incident');
  gr.addQuery('active', true);
  gr.setLimit(10);
  gr.query();

  while (gr.next()) {
    data.incidents.push({
      sys_id: gr.getUniqueValue(),
      number: gr.getValue('number'),
      short_description: gr.getValue('short_description')
    });
  }
  data.loading = false;
})();
// CLIENT CONTROLLER
api.controller = function($scope) {
  var c = this;

  c.selectIncident = function(incident) {
    c.selectedIncident = incident;
  };
};
<!-- HTML TEMPLATE -->
<div ng-if="data.loading">Loading...</div>
<div ng-if="!data.loading">
  <div ng-repeat="incident in data.incidents"
       ng-click="c.selectIncident(incident)">
    {{incident.number}}: {{incident.short_description}}
  </div>
</div>

Client → Server (Actions)

// CLIENT CONTROLLER
c.saveIncident = function() {
  c.server.get({
    action: 'save_incident',
    incident_data: c.formData
  }).then(function(response) {
    if (response.data.success) {
      c.data.message = 'Saved successfully';
    }
  });
};
// SERVER SCRIPT
if (input && input.action === 'save_incident') {
  var gr = new GlideRecord('incident');
  gr.initialize();
  gr.setValue('short_description', input.incident_data.short_description);
  data.new_sys_id = gr.insert();
  data.success = !!data.new_sys_id;
}

Validation Checklist

Before deploying a widget, verify:

  • Every data.property in server is used in HTML or client
  • Every ng-click="c.method()" has matching c.method in client
  • Every c.server.get({action: 'x'}) has matching if(input.action === 'x') in server
  • No orphaned methods or unused data properties
  • All data.* properties are initialized in server (even if empty)

Common Failures

Action Name Mismatch

// CLIENT - sends 'saveIncident'
c.server.get({action: 'saveIncident'});

// SERVER - expects 'save_incident' (MISMATCH!)
if (input.action === 'save_incident') { }

Method Name Mismatch

<!-- HTML - calls saveData() -->
<button ng-click="c.saveData()">Save</button>
// CLIENT - defines save() (MISMATCH!)
c.save = function() { };

Undefined Data Properties

<!-- HTML - references user.email -->
<span>{{data.user.email}}</span>
// SERVER - only sets user.name (user.email is undefined!)
data.user = { name: userName };

Angular Directives Reference

DirectivePurpose
ng-ifConditionally render element
ng-show/ng-hideToggle visibility (element stays in DOM)
ng-repeatIterate over array
ng-clickHandle click events
ng-modelTwo-way data binding
ng-classDynamic CSS classes
ng-disabledDisable form elements

Score

Total Score

75/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

+10
人気

GitHub Stars 100以上

0/15
最近の活動

1ヶ月以内に更新

+10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

+5

Reviews

💬

Reviews coming soon