Skip to content

Draft blog post for Node.js WinRT projections#598

Draft
lei9444 wants to merge 10 commits into
mainfrom
leilzh/blogs
Draft

Draft blog post for Node.js WinRT projections#598
lei9444 wants to merge 10 commits into
mainfrom
leilzh/blogs

Conversation

@lei9444

@lei9444 lei9444 commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Description

Usage Example

Related Issue

Type of Change

  • 🐛 Bug fix
  • ✨ New feature
  • 💥 Breaking change
  • 📝 Documentation
  • 🔧 Config/build
  • ♻️ Refactoring
  • 🧪 Test update

Checklist

  • New tests added for new functionality (if applicable)
  • Tested locally on Windows
  • Main README.md updated (if applicable)
  • docs/usage.md updated (if CLI commands changed)
  • Language-specific guides updated (if applicable)
  • Sample projects updated to reflect changes (if applicable)
  • Agent skill templates updated in docs/fragments/skills/ (if CLI commands/workflows changed)

Screenshots / Demo

Additional Notes

AI Description

This PR introduces a draft blog post for Node.js WinRT projections, alongside several newly added assets such as images and demos. It aims to provide insights on calling Windows APIs directly from Electron and Node.js without the need for native addons. New content includes visual elements like a blog banner, demonstration gifs, and a detailed draft on JavaScript projections.

@github-actions github-actions Bot added the documentation Improvements or additions to documentation label Jul 1, 2026
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Build Metrics Report

Binary Sizes

Artifact Baseline Current Delta
CLI (ARM64) 31.71 MB 31.71 MB ✅ 0.0 KB (0.00%)
CLI (x64) 32.04 MB 32.04 MB ✅ 0.0 KB (0.00%)
MSIX (ARM64) 13.30 MB N/A N/A
MSIX (x64) 14.15 MB N/A N/A
NPM Package 27.77 MB N/A N/A
NuGet Package 27.79 MB N/A N/A
VS Code Extension 20.60 MB N/A N/A

Test Results

0 passed out of 0 tests in 0.0s (-1546 tests, -486.3s vs. baseline)

Test Coverage

0% line coverage, 0% branch coverage · ⚠️ -18.1% vs. baseline

CLI Startup Time

39ms median (x64, winapp --version) · ✅ no change vs. baseline


Updated 2026-07-10 10:01:01 UTC · commit 6a7222d · workflow run

@yeelam-gordon yeelam-gordon left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Draft review pass — 5 inline suggestions:

  1. Surface the Electron on Windows Gallery earlier, as the "menu" of scenarios (2 shown inline, many more copy-paste-able).
  2. Make the default notification example do something Electron's built-in new Notification() can't — that's the "wow."
  3. systemAIModels: no single command today, and I'd keep it opt-in rather than default-in-init (with reasoning inline).
  4. Swap the StorageFile example for the native Share sheet (DataTransferManager) + a screenshot — much stronger hook.
  5. Trim the Plain Node.js section to one hero path; move the other variations to a dedicated guide.

Nice writeup overall — these are about sharpening the hook for Electron devs.

Comment thread ifdef-blog-js-projections-draft.md Outdated
Comment thread ifdef-blog-js-projections-draft.md
Comment thread ifdef-blog-js-projections-draft.md Outdated
Comment on lines +96 to +102
Phi Silica needs a Copilot+ PC. Before running, add the `systemAIModels` restricted capability to `Package.appxmanifest`:

```xml
<Capabilities>
<rescap:Capability Name="systemAIModels" />
</Capabilities>
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On adding systemAIModels — two parts:

1. Can winapp add it with a single command? Not today. winapp manifest only exposes generate / update-assets / add-alias, so systemAIModels currently has to be hand-edited into the manifest (as shown). A winapp manifest add-capability systemAIModels (or a winapp init --ai opt-in) would collapse this to one step and make the guide cleaner — worth filing as a follow-up.

2. Should init add it by default? I'd lean no. systemAIModels is a restricted capability; declaring it on every init (including the majority of apps that never touch on-device AI) over-declares privilege and adds Store-certification justification for apps that don't need it. Note the default template already carries the rescap namespace + runFullTrust, so the namespace plumbing is free — but the capability itself should stay opt-in via a single command, not on-by-default. So the honest answer to "no harm to include by default?" is: there is mild harm (least-privilege + Store review), so prefer the one-command opt-in over defaulting it in.

Comment thread ifdef-blog-js-projections-draft.md Outdated
Comment thread ifdef-blog-js-projections-draft.md Outdated
Comment on lines +135 to +137
## Plain Node.js: a dev-mode quick-start

Not on Electron? The same projections work from a plain Node.js process too. For local prototyping — trying a WinRT API on your own box without shipping an MSIX — register a loose-layout package and give it a command-line alias:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section tries to cover several situations at once and runs long (loose-layout register + copy node.exe + execution alias + run --no-launch + unregister). We agreed we can't show them all inline.

Pick the single simplest + most powerful path as the one hero example — I'd keep the execution-alias + winapp run flow — and move the other variations (bare winapp run without an alias, the copy-node-into-project trick, packaging-later notes) into a dedicated guide, e.g. docs/guides/node/dev-mode.md, and link to it from here. Keeps the blog tight and gives the extra detail a proper home.

Comment thread assets/electron-toast-hello-from-electron.png
Comment thread ifdef-blog-js-projections-draft.md
Comment thread ifdef-blog-js-projections-draft.md Outdated
Comment thread ifdef-blog-js-projections-draft.md Outdated

Both are written entirely in JavaScript. The same pattern extends to file pickers, WinML execution-provider discovery, and other WinRT surfaces — full walk-throughs live in the [Electron guides](https://github.com/microsoft/winappCli/tree/main/docs/guides/electron).

For the full menu of what this unlocks, take a look at [**Electron on Windows Gallery**](https://github.com/microsoft/electron-on-windows-gallery) — an open-source sample gallery powered by this same setup, with samples for text generation, summarization, rewriting, OCR, image description, image scaling, and object extraction.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also move this paragraph to later in the document. Keep this section focused on walking through the 2 examples you listed at the top

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved it into a separate paragraph so it’s no longer part of the two examples, but I kept it before the samples because I feel the demos are one of the most engaging parts of the post and can help capture readers’ interest before they dive into the examples.

Comment thread ifdef-blog-js-projections-draft.md Outdated
Comment thread ifdef-blog-js-projections-draft.md Outdated
Comment thread ifdef-blog-js-projections-draft.md Outdated
Comment thread ifdef-blog-js-projections-draft.md Outdated
Comment thread ifdef-blog-js-projections-draft.md Outdated
Comment thread ifdef-blog-js-projections-draft.md Outdated
Comment thread assets/blog-banner.png

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: for the main.js screenshot could you have copilot remove the tilt on the console window so its straight up and down

Comment thread ifdef-blog-js-projections-draft.md Outdated
@@ -0,0 +1,289 @@
# Introducing a dynamic WinRT projection for Node.js

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Main feedback is to make the title understandable by audience that is not in the Microsoft/Windows world. WinRT doesn't mean much to that audience. Lead with the value from their viewpoint. Something like "New way to call native Windows APIs from JavaScript in Node.js- introducing dynamic API projections". Same for the banner image

Comment thread ifdef-blog-js-projections-draft.md Outdated

![Dynamic WinRT projection for Node.js — public preview banner showing the tagline "Call Windows Runtime APIs directly from JavaScript in Electron and Node.js" alongside a code snippet using LanguageModel and TextSummarizer from the generated bindings.](./assets/blog-banner.png)

We've been working on something new for Electron developers on Windows: **a dynamic WinRT projection for Node.js** that lets your Electron app — or any Node.js process — call many non-UI WinRT APIs (APIs described by `.winmd` metadata in the Windows App SDK or Windows SDK) directly from JavaScript or TypeScript. No app-specific native addon, no `node-gyp` build step, no C++ or C# wrapper in your project. 🚀

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
We've been working on something new for Electron developers on Windows: **a dynamic WinRT projection for Node.js** that lets your Electron app or any Node.js process call many non-UI WinRT APIs (APIs described by `.winmd` metadata in the Windows App SDK or Windows SDK) directly from JavaScript or TypeScript. No app-specific native addon, no `node-gyp` build step, no C++ or C# wrapper in your project. 🚀
We've been working on something new for Electron developers on Windows: **a dynamic Windows Runtime API (WinRT) projections for Node.js** that lets your Electron app - or any Node.js process - call non-UI WinRT APIs (APIs described by `.winmd` metadata in the Windows App SDK or Windows SDK) directly from JavaScript or TypeScript. No app-specific native addon, no `node-gyp` build step, no C++ or C# wrapper in your project. 🚀

Comment thread ifdef-blog-js-projections-draft.md Outdated

## How this projection is different

C++/WinRT, C#/WinRT, `windows-rs`, and PyWinRT project the Windows Runtime into their respective languages. This adds JavaScript to that list — targeting the **Node.js runtime** — but takes a different approach:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add links for these for the user


In this post we'll walk through two common Windows API scenarios from JavaScript:

- **Native notifications** with `AppNotificationBuilder` / `AppNotificationManager`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I love these examples, add more so it's not just the obvious ones, many APIs in the sdks

The WinApp CLI sets up the manifest and SDKs, adds `@microsoft/dynwinrt` + `@microsoft/dynwinrt-codegen` to your `package.json`, and writes typed bindings to `.winapp/bindings/`. Then run this once before starting Electron:

```bash
npx winapp node add-electron-debug-identity

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only needed for APIs that need package identity, not all do - would be good to clarify and link to the docs/guides for how this works.

npx winapp init . --use-defaults --add-js-bindings
```

The WinApp CLI sets up the manifest and SDKs, adds `@microsoft/dynwinrt` + `@microsoft/dynwinrt-codegen` to your `package.json`, and writes typed bindings to `.winapp/bindings/`. Then run this once before starting Electron:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's also worth mentioning that the bindings and output can be configured in package.json and that the config object is written on the init command

Comment thread ifdef-blog-js-projections-draft.md Outdated

![Dynamic WinRT projection for Node.js — public preview banner showing the tagline "Call Windows Runtime APIs directly from JavaScript in Electron and Node.js" alongside a code snippet using LanguageModel and TextSummarizer from the generated bindings.](./assets/blog-banner.png)

We've been working on something new for Electron developers on Windows: **a dynamic WinRT projection for Node.js** that lets your Electron app — or any Node.js process — call many non-UI WinRT APIs (APIs described by `.winmd` metadata in the Windows App SDK or Windows SDK) directly from JavaScript or TypeScript. No app-specific native addon, no `node-gyp` build step, no C++ or C# wrapper in your project. 🚀

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be worth adding a sentence or two to introduce the motivation of why developers should care in this intro, what is the pain point we are solving?

@Jaylyn-Barbee Jaylyn-Barbee left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The blog flows nicely, just a few suggestion

Comment thread ifdef-blog-js-projections-draft.md Outdated

![Dynamic WinRT projection for Node.js — public preview banner showing the tagline "Call Windows Runtime APIs directly from JavaScript in Electron and Node.js" alongside a code snippet using LanguageModel and TextSummarizer from the generated bindings.](./assets/blog-banner.png)

We've been working on something new for Electron developers on Windows: **a dynamic WinRT projection for Node.js** that lets your Electron app — or any Node.js process — call many non-UI WinRT APIs (APIs described by `.winmd` metadata in the Windows App SDK or Windows SDK) directly from JavaScript or TypeScript. No app-specific native addon, no `node-gyp` build step, no C++ or C# wrapper in your project. 🚀

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am viewing the first couple of paragraphs of this blog post and my eyes were immediately drawn to a few sets of em dashes (—) which we know to be a common AI artifact. I would hate for our readers to discount this content because of this. Is it possible to rewrite these parts to have a more human voice?

Comment thread ifdef-blog-js-projections-draft.md Outdated

## How this projection is different

C++/WinRT, C#/WinRT, `windows-rs`, and PyWinRT project the Windows Runtime into their respective languages. This adds JavaScript to that list — targeting the **Node.js runtime** — but takes a different approach:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
C++/WinRT, C#/WinRT, `windows-rs`, and PyWinRT project the Windows Runtime into their respective languages. This adds JavaScript to that list — targeting the **Node.js runtime** — but takes a different approach:
C++/WinRT, C#/WinRT, `windows-rs`, and PyWinRT project the Windows Runtime into their respective languages. This projection adds JavaScript to that list — targeting the **Node.js runtime** — but takes a different approach:

We've been working on something new for Electron developers on Windows: **a dynamic WinRT projection for Node.js** that lets your Electron app — or any Node.js process — call many non-UI WinRT APIs (APIs described by `.winmd` metadata in the Windows App SDK or Windows SDK) directly from JavaScript or TypeScript. No app-specific native addon, no `node-gyp` build step, no C++ or C# wrapper in your project. 🚀

## How this projection is different

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's mentioned in the subheader and in the sentence before the list that this projection takes a different approach, and I am wondering why it is taking a different approach?

<img src="./assets/electron-gallery-samples.gif" width="720" alt="Electron on Windows Gallery running several on-device AI samples end-to-end: text summarization, OCR, object remover, and image description — each driven by a handful of JavaScript against the generated bindings." />
</p>

## What you can build

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This header makes it sound like you're going to tell me the full capabilities of this new projection but it's actually just setting up the two demo's that are going to be shared in this post.

Suggested change
## What you can build
## Examples of what you can build

Also, maybe this header should be after "What's in the box" so it flows better into the demo walkthroughs.

npx winapp init . --use-defaults --add-js-bindings
```

The WinApp CLI sets up the manifest and SDKs, adds `@microsoft/dynwinrt` + `@microsoft/dynwinrt-codegen` to your `package.json`, and writes typed bindings to `.winapp/bindings/`. Then run this once before starting Electron:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The WinApp CLI sets up the manifest and SDKs, adds `@microsoft/dynwinrt` + `@microsoft/dynwinrt-codegen` to your `package.json`, and writes typed bindings to `.winapp/bindings/`. Then run this once before starting Electron:
The WinApp CLI sets up the manifest and SDKs, adds `@microsoft/dynwinrt` + `@microsoft/dynwinrt-codegen` to your `package.json`, and writes typed bindings to `.winapp/bindings/`. Run this once before starting Electron:

Comment thread ifdef-blog-js-projections-draft.md Outdated
.buildNotification()
);
```
Run it, and Windows fires the same native toast you'd get from a C#/C++ app — including the progress bar:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Run it, and Windows fires the same native toast you'd get from a C#/C++ app — including the progress bar:
Run the app, and Windows fires the same native toast you'd get from a C#/C++ app — including the progress bar:

Comment thread ifdef-blog-js-projections-draft.md Outdated
Comment on lines +137 to +141
Full walk-through in the [Call Phi Silica from JavaScript](https://github.com/microsoft/winappCli/blob/main/docs/guides/electron/js-phi-silica.md) guide.

Running the snippet above in an Electron main process, the summary streams into the DevTools console chunk by chunk, followed by the final `Done:` line:

![Electron DevTools console: the Phi Silica summary streams in one partial chunk at a time via op.progress(), followed by a final "Done:" line with the complete summary.](./assets/phi-silica-console.gif)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved the reference to the guide to the end to 1. make sure people see the working example and 2. make things consistent with the other walkthrough above.

Suggested change
Full walk-through in the [Call Phi Silica from JavaScript](https://github.com/microsoft/winappCli/blob/main/docs/guides/electron/js-phi-silica.md) guide.
Running the snippet above in an Electron main process, the summary streams into the DevTools console chunk by chunk, followed by the final `Done:` line:
![Electron DevTools console: the Phi Silica summary streams in one partial chunk at a time via op.progress(), followed by a final "Done:" line with the complete summary.](./assets/phi-silica-console.gif)
Running the snippet above in an Electron main process, the summary streams into the DevTools console chunk by chunk, followed by the final `Done:` line:
![Electron DevTools console: the Phi Silica summary streams in one partial chunk at a time via op.progress(), followed by a final "Done:" line with the complete summary.](./assets/phi-silica-console.gif)
Full walk-through in the [Call Phi Silica from JavaScript](https://github.com/microsoft/winappCli/blob/main/docs/guides/electron/js-phi-silica.md) guide.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants