Download
Join the TestFlight beta
Install the current HTML to App beta from Apple's TestFlight invite and try the macOS builder before the public App Store listing goes live.
HTML to App packages a self-contained HTML file or folder into a standalone macOS app through one guided desktop workflow. It is built for offline tools, viewers, internal utilities, and other local-first projects that should live on disk instead of behind a hosted URL, while still exposing Mac behaviors like Finder opens, notifications, Dock badges, and menu bar apps to JavaScript.
The public Mac App Store listing is not live yet. Join TestFlight for the current beta, or send rollout questions to support@htmltoapp.app.
Actual exported app
Concrete example: local image viewer
index.html, bundled assets, and no server-side dependency. .app bundle that opens selected files in JavaScript through the built-in bridge. The public App Store page is not live yet, but you can download the current beta through TestFlight and review the planned launch path before release.
Download
Install the current HTML to App beta from Apple's TestFlight invite and try the macOS builder before the public App Store listing goes live.
Pricing
Trust
HTML to App is from the same independent developer behind Parall and DockLock Pro. Generated bundles fit into a normal macOS release flow, and rollout questions go through direct email support.
HTML to App is deliberately narrow software. It works best when the project is local-first, Mac-specific, and meant to behave like a real desktop utility.
.app bundle that you can sign or notarize in your own release pipeline.The workflow is short on purpose: choose the local source, set the Mac-specific behavior, then export the final bundle.
Choose a single HTML file or a folder with an index entry point. The best fit is self-contained HTML, CSS, JavaScript, images, and media linked by relative paths.
Name the app, choose the icon, decide whether content is embedded or read from the original folder, and opt into Finder handlers, permissions, notifications, or Dock status only when needed.
Save a standalone macOS app, then move it into your own signing, notarization, testing, or release flow.
This is one of the most concrete technical advantages: launch items show up in your page without you writing a custom native bridge first.
Read startup items from window.HTMLtoApp.launchItems and listen for later opens
with htmltoapp-open. Editor-role builds also expose
window.HTMLtoApp.fs for scoped write-back inside the opened item.
const launchItems = (window.HTMLtoApp && window.HTMLtoApp.launchItems) || [];
window.addEventListener("htmltoapp-open", (event) => {
const detail = event.detail || {};
handleLaunchItems(detail.items || [], !!detail.replaceExisting);
}); Generated apps can surface timely status through the same JavaScript you already use for the page, so counters, reminders, and long-running local tasks can feel at home on macOS.
Use the standard browser-style Notification API from local HTML. HTML to App
forwards supported notification requests into native macOS notifications in the exported app.
Notification.requestPermission().new Notification(title, options).
Update the Dock tile badge, create a menu bar icon, regenerate menus on popup, and keep a
generated utility running after its main window closes. Remove the menu bar item with
menuBar.hideIcon() when users need to start over.
const appBridge = window.HTMLtoApp;
async function notify(title, body) {
if (!("Notification" in window)) return;
const permission = await Notification.requestPermission();
if (permission === "granted") new Notification(title, { body });
return permission;
}
async function requestBadgePermission() {
if (!("Notification" in window)) return "denied";
return await Notification.requestPermission();
}
async function setDockBadge(value) {
const permission = await requestBadgePermission();
if (permission !== "granted") return;
appBridge?.setBadge?.(value);
}
setDockBadge("3"); const appBridge = window.HTMLtoApp;
let paused = false;
appBridge?.menuBar?.setIcon({
title: "TA",
tooltip: "Task Agent",
imagePosition: "left",
closeToMenuBarOnWindowClose: true
});
appBridge?.menuBar?.setMenu(() => [
{ id: "open", title: "Open Window" },
{ id: "paused", title: "Paused", checked: paused, toggle: true },
{ title: "More", submenu: [{ id: "quit", title: "Quit" }] }
]);
appBridge?.menuBar?.onItemClick((event) => {
if (event.id === "open") appBridge.showWindow();
if (event.id === "paused") paused = event.checked;
if (event.id === "quit") appBridge.quit();
});
// Remove the menu bar item when the user wants to start over.
// appBridge?.menuBar?.hideIcon?.(); Here is what is already confirmed about compatibility and what should still be validated before a production rollout.
.app bundle that fits into your own signing and notarization flow.HTML to App is not trying to replace every desktop-app approach. It is for the narrower case of packaging a local HTML project into a focused Mac utility.
Best when: Use those when you need a broader cross-platform desktop stack or deeper runtime customization.
Why HTML to App: Use HTML to App when the job is specifically packaging a self-contained local HTML project as a focused Mac app with less setup.
Best when: Build the native shell yourself when you want full control over the AppKit or WebKit layer and are prepared to maintain it.
Why HTML to App: Use HTML to App when you want packaging, Finder registration, launch-item bridging, and permission scoping in one guided builder.
Best when: Those are strong when the goal is workflow automation instead of shipping a desktop app bundle.
Why HTML to App: Use HTML to App when the end result should behave like a branded app in Finder, the Dock, and Launch Services.
These are the current production screens, organized around the decision each step helps you make.
Step 1
Start with a clear requirements screen so you know whether the project is self-contained enough for a clean local export before you configure anything else.