Adding Superpowers to your Blazor WebAssembly App with Project Fugu APIs

Blazor WebAssembly is a powerful framework for building web applications that run on the client-side. With Project Fugu APIs, you can extend the capabilities of these apps to access new device features and provide an enhanced user experience. In this article, learn about the benefits of using Project Fugu APIs, the wrapper packages that are available for Blazor WebAssembly, and how to use them in your application.

Whether you're a seasoned Blazor developer or just getting started, this article will help you add superpowers to your Blazor WebAssembly app.

In diesem Artikel:

Adding Superpowers to your Blazor WebAssembly App with Project Fugu APIs
Christian Liebel ist Consultant bei Thinktecture. Sein Fokus liegt auf Webstandards und Progressive Web Apps. Er vertritt Thinktecture beim W3C.

Blazor WebAssembly is Microsoft’s framework for building single-page apps (SPAs) with C# and Razor. You can use Blazor to build more or less the same experiences as with other SPA frameworks such as React or Angular. This includes Progressive Web Apps (PWA)—web-based applications that work offline and can be installed on the user’s system.

Project Fugu, a joint venture between Microsoft, Google, Intel, and others, wants to bring more capabilities to the web to make PWAs and other web-based applications even more powerful. This includes accessing the file system, displaying app badges, or registering a web app as a handler for specific file extensions. As web platform APIs are for everyone, they can also be used within Blazor WebAssembly applications.

A diagram showing four Fugu APIs, with hte
The Fugu is the mascot of the Project Fugu initiative.

However, those APIs are typically JavaScript-based. To access them within Blazor WebAssembly apps, they must be wrapped for .NET. Some ready-to-use open-source NuGet packages exist, but my Thinktecture colleague Patrick Jahr and I missed some APIs. So, over the last couple of weeks, we implemented several missing Fugu wrappers for Blazor WebAssembly. You can find the source code and all samples on GitHub:

This blog post will introduce some of the new web platform APIs, including their browser and platform support, and explains how to use the Blazor WebAssembly wrapper packages provided by the community and us. Please note that our packages are technical showcases and not official Thinktecture products.

Stay backwards compatible with Progressive Enhancement

Before using any of the following APIs, you should always check if it is available on the target system, as the platform support varies. Calling a non-existing API will lead to an error during runtime, and the application may crash. To avoid this, all wrapper packages discussed in this blog post offer a method called IsSupportedAsync() returning a boolean value whether the API is available:

					var isSupported = await badgingService.IsSupportedAsync();
if (isSupported)
    // enable badging feature
    // use fallback mechanism or hide/disable feature

In case the API is not available on the user’s system, you should hide or disable the feature. In some cases, alternative implementations are available to achieve similar behavior.

Share content to other apps with the Web Share API

The Web Share API allows you to share a title, URL, text, or files with another application installed on the user’s system via the share functionality provided by the operating system.

The image shows the platform-specific share dialog on top of a Blazor WebAssembly application.
Thanks to the Web Share API, Blazor WebAssembly apps can share data using the platform-specific share sheet

To use this API from your Blazor WebAssembly application, install the wrapper NuGet package for the Web Share API by using the following command:

					dotnet add package Thinktecture.Blazor.WebShare

Before using the API, you have to add the WebShareService to the IServiceCollection in Program.cs as follows:


Now, you can inject the WebShareService into your Blazor component. By calling its ShareAsync() method and passing a WebShareDataModel object to it, the device’s share sheet will open. The user can select an already installed application to share the content with or send it to another device via nearby sharing or AirDrop.

    var data = new WebShareDataModel
        Title = "Test 1",
        Text = "Lorem ipsum dolor...",
        Url = ""
    await webShareService.ShareAsync(data);
catch (Exception ex)
    // data not shareable or user denied sharing

Please note that the API is only exposed on secure contexts (sites transferred via HTTPS and localhost) and can only be invoked due to user interaction (i.e., a keypress or click). This also applies to most other APIs in this article. If the data cannot be shared or the user has dismissed the share sheet, an exception will be thrown.

Details about sharing files can be found in the readme file of the Web Share API wrapper package.

The Web Share API is supported by Chrome 89, Edge 81, and Safari 12.1. Mozilla Firefox also supports the API, but only on Android. For more details, see the browser support table for the Web Share API on

Access the clipboard via the Async Clipboard API

The Async Clipboard API allows you to read and write text, images, and other data from or to the system’s clipboard. The supported data formats depend on the target platform. For instance, WebKit currently only supports plain text, HTML, URI lists, and PNG images.

You can install this wrapper package by using the following command:

					dotnet add package Thinktecture.Blazor.AsyncClipboard

Before using the API, you have to add the service to your service collection:


Afterward, you can inject the service into your Blazor component. It offers two shorthand methods for writing and reading plain text to or from the clipboard:

					// Write plain text to the clipboard
await asyncClipboardService.WriteTextAsync("Hello world");

// Read plain text from the clipboard
var text = await asyncClipboardService.ReadTextAsync();

The service also offers WriteAsync() and ReadAsync() methods for dealing with arbitrary data, if supported by the target platform. The readme file of the Async Clipboard API wrapper package explains those two methods in more detail.

Depending on the platform and action, permission or confirm prompts may open.

The browser shows a permission prompt after the application has attempted to access the clipboard
Due to security and privacy considerations, Chrome shows a permission prompt before giving the web application read access to the Clipboard.

The Async Clipboard API is supported since Microsoft Edge 79, Google Chrome 62, and Apple Safari 13.1. Mozilla Firefox only supports writing plain text, since version 63. For more details, see the browser support table for the Async Clipboard API on

Opening and saving files with the File System Access API

The File System Access API allows your app to open, modify, and save local files and directories. It is based on the more general File System API and specifically deals with the local file system. This allows developers to finally bring traditional productivity apps to the web, such as image editors, word processors, or IDEs. For instance, the web-based version of Visual Studio Code uses this API to access local code workspaces.

Kristoffer Strube maintains wrappers for both the File System API and the File System Access API. His implementations inspired all our wrappers, and some rely on his packages. We want to take this opportunity to thank Kristoffer for the great collaboration so far.

To install this wrapper, run the following command:

					dotnet add package KristofferStrube.Blazor.FileSystemAccess

Next, the File System Access API service needs to be added to your service collection:


Now you can inject the IFileSystemAccessService into your Blazor component or service. To get a file handle, call the ShowOpenFilePickerAsync() method. If the user selects a file via the file picker, it will then be passed to the application, where you can access its contents:

    var fileHandles = await _fas.ShowOpenFilePickerAsync();
    var fileHandle = fileHandles.Single();
    var file = await fileHandle.GetFileAsync();
    var text = await file.TextAsync();
catch (Exception ex)
    // API not available, user denied request or file could not be opened/read

With the help of the file handle, you can also modify its contents. Additional usages of this API and package are shown in the readme file of the File System Access API wrapper package.

A screenshot showing a file open dialog box on top of a Blazor WebAssembly application.

The File System Access API is supported by Chromium-based browsers only: Microsoft Edge and Google Chrome since version 86. Browser vendors can decide to disable the API, though. For example, Brave chose not to support the API, although this browser is also Chromium-based. Apple Safari only supports the File System API with the Origin Private File System (OPFS), an isolated file system that isn’t mapped to the local one. Mozilla Firefox supports neither of them. For more details, see the browser support table for the File System Access API on If you need to support all browsers, refer to fallback approaches.

Registering your app as a file editor via File Handling

The File Handling API is built on top of the File System API. It allows your PWA to register as a file handler for specific file types. This requires your app to be installed on the user’s system, as the app has to register its name and icon with the operating system. On desktop systems, installation is currently only supported by Chromium-based browsers.

To use the File Handling API in your Blazor WebAssembly app, install the following NuGet package:

					dotnet add package Thinktecture.Blazor.FileHandling

Next, you need to add the file handling service to the service collection:


In contrast to all other APIs, the File Handling API has an imperative and a declarative part. To be registered as a file handler on installation, you must declare the file_handlers property in your application’s Web Application Manifest:

  "file_handlers": [{
    "action": "./",
    "accept": {
      "text/plain": [".txt"]

This property takes an array of file handlers which must include an action (the URL that should be called if the application is invoked as a file handler) and an accept object. This object maps the list of file extensions to a media type. A handler can deal with more than one media type and file extension. Optionally, you can also specify an icon for this file type.

A screenshot showing a Windows Explorer window with a context menu for a text file. A Blazor WebAssembly app appears as a compatible program.
The Blazor WebAssembly app appears in the list of compatible editing programs.

The second part involves adding code to your application: This code is executed when your application is launched as a file handler. Therefore, we are exposing the method SetConsumerAsync() on the FileHandlingService. This method takes a callback with launch parameters. The callback is invoked if the application was launched as a file handler. It will then expose the file handles on the Files property. The type is fully compatible with the File System Access API types.

					await _fileHandlingService.SetConsumerAsync(async (launchParams) =>
    foreach (var fileSystemHandle in launchParams.Files)
        if (fileSystemHandle is FileSystemFileHandle fileSystemFileHandle)
            var file = await fileSystemFileHandle.GetFileAsync();
            var text = await file.TextAsync();

Using the file handles, the application can access the files’ contents and display them during runtime.

A screenshot of a Blazor WebAssembly application displaying text from a local file.
The Blazor WebAssembly app has gained access to the content of a file it was opened with.

The File Handling API is only supported by Chromium-based browsers since version 102 (see Chrome 102 release notes).

Communicate unfinished tasks via the Badging API

The Badging API allows you to display a badge on the installed application’s icon as a less obtrusive alternative to notification banners. The badges are well known from applications like email clients, instant messengers, or to-do apps. This also requires your application to be installed so it has an icon in the taskbar or dock.

To use this API, install the following wrapper package:

					dotnet add package Thinktecture.Blazor.Badging

As always, the services needs to be added to the service collection:

To set a badge on the application’s icon, call the SetAppBadgeAsync() method. This method takes a number that will be shown on the badge. You can also set it to null. In this case, a generic badge will be shown (without a number).
					await badgingService.SetAppBadgeAsync(3);
A screenshot showing a Blazor WebAssembly application and the Windows task bar. The application's icon has a little badge with the number 3 on it.
Thanks to the Badging API, Blazor WebAssembly applications can display badges on their app icons.

To remove the badge again, for example, when all email messages are read, all instant messages are answered, or all todo items are done, simply call the ClearAppBadgeAsync() method:

					await badgingService.ClearAppBadgeAsync();

The Badging API is currently only supported by Chromium-based browsers since version 81 on macOS and Windows, and by Apple Safari on iOS and iPadOS starting from version 16.4 Beta 1 (as long as the application has been added to the home screen and has permission for receiving push notifications). For more details, see the browser support table for the setAppBadge() method on

Powerful APIs for a more capable web

The new web platform APIs introduced by Project Fugu make web applications significantly more powerful, including your Blazor WebAssembly apps. Using the wrapper packages provided by the community and us, you can genuinely add superpowers to your Blazor-based web apps. We look forward to your feedback and are eager to see where our packages will be used. Keep an eye on our blog for more wrapper packages and updates on Progressive Web Apps. So let’s go and make the web a more powerful place!


Aktuelle Artikel, Screencasts, Webinare und Interviews unserer Experten für Sie

Verpassen Sie keine Inhalte zu Angular, .NET Core, Blazor, Azure und Kubernetes und melden Sie sich zu unserem kostenlosen monatlichen Dev-Newsletter an.

Diese Artikel könnten Sie interessieren
Incremental Roslyn Source Generators: Using Additional Files – Part 7

Incremental Roslyn Source Generators: Using Additional Files – Part 7

In the previous article the Source Generator itself needed a 3rd-party library Newtonsoft.Json in order to generate new source code. The JSON-strings were hard-coded inside the Source Generator for simplicity reasons. In this article we will see how to process not just .NET code, but also other files, like JSON or XML.
Understanding and Controlling the Blazor WebAssembly Startup Process

Understanding and Controlling the Blazor WebAssembly Startup Process

There are a lot of things going on in the background, when a Blazor WebAssembly application is being started. In some cases you might want to take a bit more control over that process. One example might be the wish to display a loading screen for applications that take some time for initial preparation, or when users are on a slow internet connection. However, in order to control something, we need to understand what is happening first. This article takes you down the rabbit hole of how a Blazor WASM application starts up.
Incremental Roslyn Source Generators: Using 3rd-Party Libraries – Part 6

Incremental Roslyn Source Generators: Using 3rd-Party Libraries – Part 6

We previously talked about how to change the source code generation based on current project dependencies. In this article, the Source Generator itself needs a 3rd-party library, in our case Newtonsoft.Json. This library is a development dependency and will not be rolled out to production.
Blazor WebAssembly in Practice: Maturity, Success Factors, Showstoppers

Blazor WebAssembly in Practice: Maturity, Success Factors, Showstoppers

ASP.NET Core Blazor is Microsoft's framework for implementing web-based applications, aimed at developers with knowledge of .NET and C#. It exists alongside other frameworks such as ASP.NET Core MVC. About two and a half years after the release of Blazor WebAssembly and based on our experiences from many customer projects at Thinktecture, we want to have a close look at the following questions: What is the current state of the framework? How can you successfully use Blazor? And where does it have limitations?
Blazor WebAssembly: Debugging gRPC-Web with Custom Chrome Developer Tools

Blazor WebAssembly: Debugging gRPC-Web with Custom Chrome Developer Tools

If you are working with Blazor, gRPC is a big issue for transferring data from APIs to clients. One issue of developing with gRPC-Web is debugging the transmitted data because the data is in an efficient binary message format. In this article, I will show you how to solve this problem with the help of my NuGet.
Entity Framework Core: User-defined Fields and Tables

Entity Framework Core: User-defined Fields and Tables

The requirement to store additional fields, unknown at development time, in a relational database is not new. Nonetheless, none of the projects I know of are willing to change the database structure at runtime. What if there is a project which needs dynamically created fields and doesn't want or cannot use entity–attribute–value model or switch to No-SQL databases?