logo

NJP

ServiceNow Meets Smart Glasses: Live-Coding a Scripted REST API Proof of Concept

New article articles in ServiceNow Community · Aug 14, 2026 · article

What if a P1 incident showed up in front of your eyes the second it needed your attention, without you touching your phone?

 

That's the idea behind our recent Live Coding w/Earl+Travis episode: get ServiceNow tickets rendering on a pair of smart glasses, live, in about an hour, mistakes included. We hit a CORS wall, a demo-data bug that made incidents look like they were created in the future, and an AI coding agent that quietly added a feature nobody asked for. By the end, a real ticket showed up on a real pair of glasses live!

 

Below is the Scripted REST API script we wrote on stream, along with a look at the glasses-side app that called it. One thing up front: the script is a proof-of-concept stub, not something to point at a production instance.

 

Table of Contents

 

 

The Use Case: Eyes-Free Incident Awareness

 

The scenario we picked was deliberately narrow: you're a help desk agent, an on-call engineer, or an admin watching a queue of inbound tickets, and a P1 comes in. Normally that means catching it in an email, a Teams or Slack alert, or a dashboard you have to remember to check, competing with whatever else is already on your screen.

 

If I were to work on this further, then I would make it so that the glasses stay blank until something needs your attention. Less distracting that way.

 

↑ Return to Table of Contents

 

Architecture at a Glance

 

The whole thing is two small pieces talking to each other:

 

  • A ServiceNow Scripted REST API answers a plain GET request with the most recent incident's short description as plain text.
  • A small web app running on Even Realities G2 smart glasses polls that endpoint and renders the response on the glasses' display.

 

One wrinkle showed up almost immediately: the ServiceNow endpoint answers with a 200 but sends no Access-Control-Allow-Origin header, so a direct cross-origin fetch from the glasses' web app gets silently dropped by CORS. During development, the app works around this by trying the direct URL first, then falling back to a same-origin dev proxy, which sidesteps CORS entirely because same-origin requests never trigger the check. That fallback only exists in the local dev server. A packaged build has no such workaround, which is one of several reasons this stays a prototype (more on that later).

 

Put together, it looks like this:

 

ServiceNow Scripted REST API --GET--> Glasses web app --render--> 576x288 display
  (plain text response) (direct, then proxy fallback)

 

↑ Return to Table of Contents

 

Building the ServiceNow Side: A Scripted REST API

 

We started here first because a Scripted REST API is the fastest way to get something the glasses could call while we figured out everything else. We stood up a new REST API resource in the global scope (partly to dodge cross-scope access issues while testing), used the default GET operation, and wrote the simplest script that would work: grab the most recent incident and return its short description as plain text.

 

Quick disclaimer before the code below: this is a stub. It has no input parameters, no filtering beyond most recent, no structured response format, no versioning, and no rate limiting. The endpoint also has no CORS rule configured, so it only works through a same-origin proxy in local development. Anything exposed beyond a single sideloaded app needs real authentication and authorization, meaningful error responses, a documented and versioned contract, and CORS configured on purpose, not left open by accident.

 

(function process(/*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {

    response.setContentType('text/plain');
    response.setStatus(200);

    let returnString = 'No records found';

    let taskGr = new GlideRecord('incident');
    taskGr.orderByDesc('sys_created_on');
    taskGr.setLimit(1);
    taskGr.query();
    if (taskGr.next()){
        returnString = `New task: ${taskGr.getValue('short_description')}`;
    }

    let writer = response.getStreamWriter();
    writer.writeString(returnString);

})(request, response);

 

If you try this on a Personal Developer Instance, watch out for one thing: our first pass ordered by sys_updated_on instead of sys_created_on, and it came back empty. Some demo data on PDIs has timestamps set in the future, which broke a most-recent query that assumed every timestamp was in the past. If a query like this comes back empty on a PDI, check for future-dated demo records before you assume your logic is wrong.

 

↑ Return to Table of Contents

 

Building the Glasses Side: An Even Realities G2 Hub App

 

The glasses we used are Even Realities G2. No camera, no speaker, just a small heads-up display and a microphone, controlled by swiping and tapping the temple. What made this build possible in an hour is that Even Realities ships an open (if very new) SDK. An app for these glasses is just a web app: HTML, CSS, and JavaScript rendered into a fixed 576×288 pixel canvas, sideloaded over your local network by scanning a QR code from the Even Hub app on your phone.

 

The SDK is new enough that it's still changing fast, so we handed the documentation and a saved build guide to Claude and asked for a minimal app: one static line of text, a second line showing whatever the ServiceNow endpoint returned, then sideloaded with a QR code to scan. Instead of walking through the entire app, here are two pieces of it that anyone building on this SDK should know about.

 

The CORS fallback. The ServiceNow endpoint sends no CORS headers, so the app tries the direct request first (so the display itself will tell us the moment a server-side CORS rule lands) and falls back to a same-origin dev proxy:

 

export const DIRECT_URL = 'https://your-instance.service-now.com/api/<app-id>/smartglasses'
export const PROXY_URL = '/sn/api/<app-id>/smartglasses'

async function get(url: string): Promise<EchoResult> {
  const route = url === DIRECT_URL ? 'direct' : 'proxy'
  const res = await fetch(url, { method: 'GET', cache: 'no-store' })
  const text = (await res.text()).trim()
  if (!res.ok) throw new Error(`HTTP ${res.status} on ${route}`)
  return { text, route, status: res.status }
}

export async function fetchEcho(): Promise<EchoResult> {
  try {
    return await get(DIRECT_URL)
  } catch (directErr) {
    console.warn('[echo] direct failed, falling back to proxy:', directErr)
    return await get(PROXY_URL)
  }
}

 

A tap on the temple doesn't arrive as a textEvent the way you'd expect. It shows up on the general sysEvent object instead, and the single-click event type normalizes to undefined rather than a real value. A handler that only checks for an explicit click event type never fires on a real single tap.

 

function gestureFrom(event: EvenHubEvent): 'click' | 'doubleClick' | null {
  const sys: any = (event as any).sysEvent
  if (sys && !sys.imuData && sys.systemExitReasonCode === undefined) {
    if (sys.eventType === OsEventTypeList.DOUBLE_CLICK_EVENT) return 'doubleClick'
    if (sys.eventType === OsEventTypeList.CLICK_EVENT || sys.eventType === undefined) return 'click'
  }
  // ...secondary text-container event path omitted here for brevity
  return null // scrolls, foreground transitions, IMU data
}

 

Sideloading turned out to be the easy part: run the web app on a local dev server, point the Even Hub app's QR scanner at the URL while your phone and computer share Wi-Fi, and it pushes straight onto the glasses. No app store review, no packaging step, at least not during development.

 

↑ Return to Table of Contents

 

Watching It Work (and Where It Broke)

 

The first real test was almost anticlimactic: scan the QR code, and Hello World shows up floating in the display. We created a test incident in the instance next, and its short description showed up on the second line a moment later. Loop confirmed, end to end.

 

Then it stopped updating, because nothing in the app ever refreshed it; it fetched once on load and that was it. We asked our AI coding assistant to add a refresh button, and it added the button we asked for, plus a five-second polling loop we hadn't asked for. It worked, and honestly it was a reasonable addition. But nobody scoped that in, and it's the kind of change you should catch in review rather than ship blind. If you need an agent to stick to exactly what you asked, say so directly, in the prompt, your project instructions, or a skill file. Letting it improvise is great when you're exploring and risky when you're not paying close attention.

 

From there it was straightforward: submit a new ticket, watch it land on the glasses a few seconds later, no phone or dashboard needed. Goal complete, for a one-hour build.

 

↑ Return to Table of Contents

 

What It Would Take to Ship This

 

This works today only because it's sideloaded onto one pair of glasses, pointed at one developer instance, over one local network. Getting it in front of anyone else means addressing a real list:

 

  • Real authentication and authorization , instead of a stub endpoint left open for demo convenience.
  • A CORS rule scoped to the domains that should call this API , not a dev-only same-origin proxy.
  • No hardcoded assumption about which instance or which glasses are on the other end. Right now there's exactly one of each.
  • A response contract with a schema, versioning, and real error codes. Plain text works for a stub; it falls apart the moment someone else has to integrate against it.
  • A real release process. Sideloading works for one developer, not for distribution.

 

The Scripted REST API script earlier in this post is a proof-of-concept stub, built live in about ten minutes. Use it as a starting point for your own experiments, not as production code.

 

Still, the core result holds: with an open, documented SDK on the wearable side, wiring ServiceNow data into it took about an hour, live, mistakes included.

 

↑ Return to Table of Contents

 

Bonus: Does AI Atrophy Your Coding Skills?

 

A viewer asked a good question: has relying on AI coding assistants made our coding skills worse? Short answer from both of us: writing code from memory has gotten rustier. Reading code, catching a subtle bug, validating what an assistant produced, that skill is sharper than ever. The skill that's grown the most is architecture: understanding how systems fit together well enough to direct an agent, rather than typing every line yourself.

 

Someone in chat put it better than we did: it's the same way a calculator dulled our manual arithmetic without touching our understanding of math.

 

We also talked about why these glasses skip a camera: camera-equipped wearables are starting to run into access restrictions in more places, and a display-only pair that looks like ordinary glasses sidesteps that problem completely. It's the main reason why I am playing around with these glasses specifically.

 

↑ Return to Table of Contents

 

Watch the Full Episode

 

Want to watch it happen live, CORS debugging, future-dated demo data, and surprise polling loop included? The full episode is below.

 

https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FzJeb6RhiMjI%3Ffeature%3Doembed&display_name=YouTube&url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DzJeb6RhiMjI&image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FzJeb6RhiMjI%2Fhqdefault.jpg&type=text%2Fhtml&schema=youtube

 

Thanks to everyone who hung out in the chat and helped debug live, including the sharp-eyed viewer who caught our future-dated demo data before we did. If you build something on top of this idea, we'd love to hear about it in the comments.

 

View original source

https://www.servicenow.com/community/developer-advocate-blog/servicenow-meets-smart-glasses-live-coding-a-scripted-rest-api/ba-p/3587465