PWA Guide

Web App Manifest

Подробное руководство по всем основным и дополнительным полям manifest-файла: что они делают, когда реально нужны, какие значения поддерживают и как использовать их в реальном проекте.

Поле Что делает Возможные значения / структура Chrome / Chromium Safari
1 name Полное имя приложения. Строка. Активно используется в install UI и списках приложений. Может использоваться для названия web app, добавленного на экран.
2 short_name Короткая версия названия. Строка. Используется там, где не помещается name. Используется как компактная подпись иконки.
3 lang Язык строк manifest. BCP 47 language tag. Спецификация есть, но поле не реализовано. Практической поддержки нет.
4 dir Направление текста. ltr, rtl, auto. Не реализовано. Не реализовано.
5 description Описание приложения. Строка. Может показываться в некоторых install-интерфейсах. Обычно не используется заметным образом.
6 icons Иконки приложения. Массив объектов. Основной способ задать иконки PWA. Нужны дополнительно Apple-иконки через HTML.
7 screenshots Скриншоты для install UI. Массив объектов. Используются в richer install UI. Обычно игнорируются.
8 categories Категории приложения. Массив строк. Могут использоваться экосистемой Chromium и сторами. Практической пользы почти нет.
9 iarc_rating_id Возрастной рейтинг IARC. Строка. Как browser-функция не реализовано. Не используется.
10 start_url Стартовый URL приложения. URL. Ключевое поле для точки входа PWA. Учитывается при запуске web app.
11 scope Границы приложения. Путь / URL-prefix. Влияет на app-like поведение внутри PWA. Работает, но поведение менее прозрачно.
12 scope_extensions Расширение scope на другие origin. Экспериментальный массив объектов. Только экспериментально. Не поддерживается.
13 display Режим отображения приложения. browser, minimal-ui, standalone, fullscreen. Работает и влияет на интерфейс окна. Поддержка неполная и платформенно-зависимая.
14 display_override Расширенный список режимов отображения. Массив строк. Частично в Chromium, в основном на desktop. Не поддерживается.
15 orientation Предпочтительная ориентация экрана. Значения Screen Orientation API. Работает в standalone/fullscreen сценариях. Часто игнорируется, особенно на iOS.
16 theme_color Цвет UI браузера / приложения по умолчанию. Любой валидный CSS-цвет. Используется широко. Ограниченно; часто важнее HTML meta tag.
17 background_color Фон до загрузки стилей. Любой валидный CSS-цвет. Используется для ранней фазы загрузки и splash screen. Часто не даёт ожидаемого эффекта.
18 shortcuts Быстрые действия у иконки приложения. Массив объектов. Работает в Chromium. Не поддерживается.
19 share_target Позволяет делиться данными в PWA. Объект. Работает для установленного PWA. Не поддерживается.
20 file_handlers Ассоциации файлов с PWA. Массив объектов. Экспериментально в Chromium. Не поддерживается.
21 protocol_handlers Обработка протоколов вроде mailto. Массив объектов. Есть поддержка в Chromium. Не поддерживается или практически бесполезно.
22 related_applications Связанные приложения. Массив объектов. Может использоваться как подсказка про native app. Почти не влияет на UX.
23 prefer_related_applications Предпочесть native app вместо PWA. true / false. Может учитываться вместе с related_applications. Практического эффекта почти нет.
24 id Стабильный идентификатор приложения. Строка. Очень рекомендуется указывать явно. Безопасно указывать, даже если эффект ограничен.
25 launch_handler Как открывать PWA при повторном запуске. Объект. Экспериментально в Chromium. Не поддерживается.
26 note_taking Дополнительные подсказки для note-taking apps. Объект. Экспериментально. Не поддерживается.
27 serviceworker Service worker для payment app. Объект. Очень узкоспециализированно. Не поддерживается.
28 share_target / files Приём файлов через share menu. Массив объектов внутри share_target.params.files. Работает при правильной конфигурации. Не поддерживается.
29 protocol_handlers.mailto Частный пример для mailto. Объект внутри protocol_handlers. Работает как часть модели protocol handlers. Не поддерживается.

1. name

Что это: полное официальное имя приложения.

Зачем нужно: именно это имя браузер и операционная система стараются использовать там, где есть достаточно места: в диалоге установки, в списке приложений, иногда на splash screen, в системных списках и переключателях приложений.

Практическое применение: если короткое название у тебя одно, а официальное - длиннее и понятнее, то полное брендированное имя лучше выносить именно сюда.

Значение: строка. Формального лимита по длине нет, но слишком длинное имя будет обрезаться в интерфейсах.

Chrome / Chromium: поле реально используется в install UI, списках приложений и других PWA-сценариях.

Safari: может использовать это название для web app, добавленного на домашний экран, но поведение зависит от платформы Apple и конкретного UI.

Пример:

{
  "name": "ShkurkoDev Web App Manifest Guide"
}

2. short_name

Что это: короткая версия названия приложения.

Зачем нужно: используется там, где полное имя не помещается - например, под иконкой на домашнем экране или в более компактных UI.

Практическое применение: почти всегда стоит задавать вместе с name, особенно если бренд длинный.

Значение: строка. На практике лучше делать короткой, чтобы не было обрезания.

Chrome / Chromium: активно использует, если name слишком длинный.

Safari: может использовать короткое имя как подпись иконки на домашнем экране.

Пример:

{
  "name": "ShkurkoDev Web App Manifest Guide",
  "short_name": "Manifest"
}

3. lang

Что это: язык строк внутри manifest.

Зачем нужно: по задумке это должно сообщать браузеру, на каком языке указаны текстовые значения вроде name и description.

Практическое применение: на сегодняшний день почти нулевое, потому что поле не реализовано.

Возможные значения: теги языка по BCP 47, например ru, en, en-US, pt-BR.

Chrome / Chromium: спецификация это поле описывает, но реальной реализации нет.

Safari: практической поддержки тоже нет.

Пример:

{
  "lang": "ru"
}

4. dir

Что это: направление текста в manifest.

Зачем нужно: предназначено прежде всего для языков с письмом справа налево, например арабского или иврита.

Возможные значения: ltr, rtl, auto.

Практическое применение: почти отсутствует, потому что поле не реализовано в браузерах как рабочая функция manifest.

Chrome / Chromium: не реализовано.

Safari: не реализовано.

Пример:

{
  "dir": "rtl"
}

5. description

Что это: текстовое описание того, что делает приложение.

Зачем нужно: помогает пользователю понять назначение PWA, особенно если браузер показывает richer install UI или app-store-like интерфейс установки.

Практическое применение: полезно прежде всего в Chromium-экосистеме. Для контентных проектов, сервисов, заметок, каталогов, редакторов и внутренних приложений сюда имеет смысл писать короткое понятное описание пользы приложения.

Значение: строка.

Chrome / Chromium: может использоваться в richer install UI.

Safari: обычно почти не использует это поле заметным образом.

Пример:

{
  "description": "Подробное руководство по Web App Manifest с примерами, объяснениями и сравнением поддержки в браузерах."
}

6. icons

Что это: список иконок приложения разных размеров, форматов и назначений.

Зачем нужно: это одно из важнейших полей. По этим данным браузер и система выбирают, какую иконку показать в install UI, на домашнем экране, в списках приложений и иногда при генерации splash screen.

Практическое применение: минимум обычно делают PNG 192×192 и 512×512. Если нужен аккуратный Android-вид, полезно добавить maskable-иконку.

Структура объекта: обычно используются поля src, sizes, type, purpose.

Возможные значения поля purpose: any, maskable, monochrome. Можно комбинировать через пробел, если это поддерживает твой сценарий подготовки иконок.

Chrome / Chromium: это основной источник иконок для PWA.

Safari: одной секции icons часто недостаточно. Для iOS обычно отдельно добавляют <link rel="apple-touch-icon"> в HTML.

Простой пример:

{
  "icons": [
    {
      "src": "/icons/icon-192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "/icons/icon-512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}

Пример с maskable:

{
  "icons": [
    {
      "src": "/icons/icon-192.png",
      "sizes": "192x192",
      "type": "image/png",
      "purpose": "any"
    },
    {
      "src": "/icons/icon-512-maskable.png",
      "sizes": "512x512",
      "type": "image/png",
      "purpose": "maskable"
    }
  ]
}

7. screenshots

Что это: скриншоты интерфейса приложения.

Зачем нужно: не влияют на саму работу PWA, но помогают показать пользователю, как выглядит приложение, если браузер поддерживает расширенный install UI.

Практическое применение: полезно в Chromium, если хочешь, чтобы установка выглядела богаче и понятнее.

Структура: массив объектов. Обычно используются src, sizes, type, form_factor.

Возможные значения form_factor: в примерах обычно встречаются wide и narrow.

Chrome / Chromium: используется в richer install UI.

Safari: как правило, игнорирует это поле.

Базовый пример:

{
  "screenshots": [
    {
      "src": "/screenshots/desktop-home.png",
      "sizes": "1440x900",
      "type": "image/png"
    }
  ]
}

Пример с разными форм-факторами:

{
  "screenshots": [
    {
      "src": "/screenshots/mobile-home.png",
      "sizes": "540x720",
      "type": "image/png",
      "form_factor": "narrow"
    },
    {
      "src": "/screenshots/desktop-dashboard.png",
      "sizes": "1440x900",
      "type": "image/png",
      "form_factor": "wide"
    }
  ]
}

8. categories

Что это: список категорий, к которым относится приложение.

Зачем нужно: помогает описать тип приложения для экосистем, каталогов и app-store-like интерфейсов.

Практическое применение: на поведение PWA как приложения почти не влияет. Это скорее метаданные.

Значение: массив строк, например productivity, business, education.

Chrome / Chromium: может где-то учитываться инфраструктурой вокруг установки и каталогов.

Safari: практической пользы почти нет.

Пример:

{
  "categories": ["education", "productivity", "developer tools"]
}

9. iarc_rating_id

Что это: строковый идентификатор возрастного рейтинга IARC.

Зачем нужно: рассчитано на интеграцию с системами публикации приложений и storefront-сценариями, где учитывается возрастная маркировка.

Практическое применение: для обычного сайта или стандартного PWA почти никогда не нужно.

Значение: строка с кодом IARC.

Chrome / Chromium: как обычная browser-функция manifest не реализовано.

Safari: не используется.

Пример:

{
  "iarc_rating_id": "e7f4a2b1-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}

10. start_url

Что это: URL, который должен открываться при запуске установленного приложения.

Зачем нужно: это точка входа PWA. Именно сюда пользователь попадает после запуска иконки приложения.

Практическое применение: можно открывать главную страницу, dashboard, onboarding или отдельный раздел. Часто добавляют query-параметр, чтобы понимать, что запуск был именно из установленного PWA.

Значение: относительный или абсолютный URL.

Chrome / Chromium: активно используется.

Safari: учитывается при запуске web app, но конкретный UX зависит от Add to Home Screen на платформе Apple.

Простой пример:

{
  "start_url": "/"
}

Пример для отдельного раздела:

{
  "start_url": "/app/"
}

Пример с query-параметром:

{
  "start_url": "/app/?source=pwa"
}

11. scope

Что это: область URL, которую браузер считает частью приложения.

Зачем нужно: определяет границы app-like режима. Страницы внутри scope считаются частью PWA, а при выходе за пределы scope браузер может показать обычный браузерный UI, например адресную строку.

Практическое применение: если приложение живёт в /app/, обычно и scope задают как /app/.

Важно: start_url должен находиться внутри scope.

Chrome / Chromium: влияет на app-like интерфейс и поведение навигации.

Safari: идея та же, но фактическое поведение может быть менее предсказуемым.

Простой пример:

{
  "start_url": "/app/",
  "scope": "/app/"
}

Пример для всего сайта:

{
  "start_url": "/",
  "scope": "/"
}

12. scope_extensions

Что это: экспериментальный механизм для расширения области приложения на другие origin.

Зачем нужно: нужен только в сложных архитектурах, где одно приложение должно восприниматься как единое, хотя часть страниц живёт на другом домене или поддомене.

Практическое применение: очень редкое. Для большинства проектов не нужно.

Chrome / Chromium: только экспериментально.

Safari: не поддерживается.

Пример общего вида:

{
  "scope_extensions": [
    {
      "type": "origin",
      "origin": "https://cdn.example.com"
    }
  ]
}

13. display

Что это: предпочтительный режим отображения приложения после установки.

Зачем нужно: определяет, сколько браузерного интерфейса увидит пользователь.

Возможные значения: browser, minimal-ui, standalone, fullscreen.

Что означают значения:

browser - обычная вкладка браузера; minimal-ui - минимум браузерного UI; standalone - выглядит как отдельное приложение без обычной вкладки; fullscreen - максимальное скрытие UI и контента на весь экран.

Практическое применение: для большинства PWA используется standalone.

Chrome / Chromium: работает как ожидается с fallback-логикой, если нужный режим не поддерживается.

Safari: поддержка неполная и зависит от платформы. Web app на домашнем экране может вести себя не так же, как Chromium PWA.

Примеры:

{
  "display": "standalone"
}
{
  "display": "fullscreen"
}
{
  "display": "browser"
}

14. display_override

Что это: массив режимов отображения с приоритетом.

Зачем нужно: стандартного fallback от display иногда недостаточно, особенно в продвинутых desktop PWA-сценариях Chromium.

Практическое применение: нужно, если хочешь сначала попросить более новый режим, а при отсутствии поддержки откатиться к обычному standalone.

Значение: массив строк.

Chrome / Chromium: поддержка есть частично, в основном в Chromium и особенно на desktop.

Safari: не поддерживается.

Примеры:

{
  "display": "standalone",
  "display_override": ["window-controls-overlay", "standalone"]
}
{
  "display": "browser",
  "display_override": ["tabbed", "standalone", "browser"]
}

15. orientation

Что это: предпочтительная ориентация экрана для приложения.

Зачем нужно: полезно для игр, медиаприложений, киосковых интерфейсов, навигации, терминалов и других сценариев, где UI рассчитан строго под portrait или landscape.

Возможные значения: any, natural, portrait, landscape, portrait-primary, portrait-secondary, landscape-primary, landscape-secondary.

Chrome / Chromium: учитывается прежде всего в standalone/fullscreen режимах.

Safari: особенно на iOS часто игнорирует это поле или применяет не так, как ожидается в Chromium.

Примеры:

{
  "orientation": "portrait"
}
{
  "orientation": "landscape"
}
{
  "orientation": "any"
}

16. theme_color

Что это: цвет пользовательского интерфейса приложения по умолчанию.

Зачем нужно: может применяться к браузерным UI-элементам - например к тулбару, адресной строке, статусной зоне, а также может быть заметен в task switcher и похожих контекстах.

Практическое применение: подбирается под главный брендовый цвет приложения.

Важно: HTML-тег <meta name="theme-color"> может переопределить это значение для конкретной страницы. Также браузер может учитывать цветовые схемы пользователя и CSS-медиаусловия.

Возможные значения: любой валидный CSS-цвет: keyword, hex, rgb(), hsl().

Chrome / Chromium: поле реально используется.

Safari: влияние ограничено; на практике часто важнее HTML meta theme-color.

Примеры:

{
  "theme_color": "#0f172a"
}
{
  "theme_color": "rgb(66 133 244)"
}
{
  "theme_color": "white"
}

Пример совместно с HTML meta:

<meta name="theme-color" content="#111827">

17. background_color

Что это: стартовый цвет фона, который показывается до полной загрузки стилей приложения.

Зачем нужно: помогает избежать резкой белой вспышки при запуске и сделать старт PWA визуально аккуратнее.

Важно: это поле не управляет постоянным фоном интерфейса после загрузки приложения. После загрузки решает уже CSS. Это временный стартовый цвет и источник splash background в некоторых окружениях.

Практическое применение: ставят таким же, как основной фон приложения в CSS.

Возможные значения: любой валидный CSS-цвет.

Chrome / Chromium: используется для initial background и генерации splash screen в некоторых средах.

Safari: часто не даёт такого же заметного эффекта, как в Chromium.

Пример:

{
  "background_color": "#f7f6f2"
}

Пример в связке с CSS:

{
  "background_color": "#f7f6f2"
}
body {
  background-color: #f7f6f2;
}

18. shortcuts

Что это: быстрые действия для установленного приложения.

Зачем нужно: позволяет открыть важные разделы PWA прямо из контекстного меню иконки приложения.

Практическое применение: удобно для “Новая заметка”, “Открыть задачи”, “Избранное”, “Профиль”, “Поиск”.

Структура: массив объектов { name, short_name?, description?, url, icons? }.

Chrome / Chromium: работает у установленного PWA в экосистеме Chromium.

Safari: не поддерживается.

Простой пример:

{
  "shortcuts": [
    {
      "name": "Новая заметка",
      "url": "/notes/new"
    }
  ]
}

Полный пример:

{
  "shortcuts": [
    {
      "name": "Новая заметка",
      "short_name": "Новая",
      "description": "Быстро создать новую заметку",
      "url": "/notes/new",
      "icons": [
        {
          "src": "/icons/new-note.png",
          "sizes": "96x96",
          "type": "image/png"
        }
      ]
    },
    {
      "name": "Избранное",
      "url": "/favorites"
    }
  ]
}

19. share_target

Что это: делает установленное PWA получателем данных из системного меню “Поделиться”.

Зачем нужно: пользователь может отправить в приложение текст, ссылку, заголовок, а иногда и файлы.

Практическое применение: особенно полезно для приложений заметок, закладок, редакторов, менеджеров контента, обмена ссылками и импорта данных.

Структура: объект. Обязательны action и params. Также могут использоваться method и enctype.

Возможные значения method: GET или POST.

Важно: для файлов нужен POST, multipart/form-data и секция params.files.

Chrome / Chromium: работает для установленного PWA.

Safari: не поддерживается.

Простой пример для ссылки и текста:

{
  "share_target": {
    "action": "/share-target/",
    "method": "GET",
    "params": {
      "title": "title",
      "text": "text",
      "url": "url"
    }
  }
}

Пример через POST:

{
  "share_target": {
    "action": "/share-target/",
    "method": "POST",
    "enctype": "application/x-www-form-urlencoded",
    "params": {
      "title": "title",
      "text": "text",
      "url": "url"
    }
  }
}

Пример с файлами:

{
  "share_target": {
    "action": "/share-target/",
    "method": "POST",
    "enctype": "multipart/form-data",
    "params": {
      "title": "title",
      "text": "text",
      "url": "url",
      "files": [
        {
          "name": "images",
          "accept": ["image/png", "image/jpeg"]
        }
      ]
    }
  }
}

20. file_handlers

Что это: список типов файлов, которые установленное PWA может открывать.

Зачем нужно: позволяет связать PWA с файлами на уровне системы, чтобы пользователь открывал их прямо в твоём приложении.

Практическое применение: полезно для редакторов текста, CSV-инструментов, графических редакторов, SVG-просмотрщиков, note apps, IDE-подобных приложений.

Структура: массив объектов { action, accept }, где accept - это словарь, который связывает MIME-типы с расширениями файлов.

Важно: одного manifest недостаточно. После запуска приложение должно уметь реально обработать файлы в JavaScript, например через window.launchQueue.

Chrome / Chromium: экспериментально.

Safari: не поддерживается.

Пример для текстовых файлов:

{
  "file_handlers": [
    {
      "action": "/open-file/",
      "accept": {
        "text/plain": [".txt"]
      }
    }
  ]
}

Пример для нескольких типов:

{
  "file_handlers": [
    {
      "action": "/open-file/",
      "accept": {
        "text/plain": [".txt", ".md"],
        "text/csv": [".csv"],
        "image/svg+xml": [".svg"]
      }
    }
  ]
}

Пример обработки в JavaScript:

if ('launchQueue' in window) {
  launchQueue.setConsumer((launchParams) => {
    for (const fileHandle of launchParams.files) {
      console.log('Получен файл:', fileHandle);
    }
  });
}

21. protocol_handlers

Что это: регистрация PWA как обработчика определённых URL-протоколов.

Зачем нужно: позволяет открывать твоё приложение по ссылкам вроде mailto:, web+music: и другим схемам, если система и браузер это разрешают.

Практическое применение: полезно для почтовых клиентов, музыкальных сервисов, специализированных бизнес-инструментов и кастомных deep link сценариев.

Структура: массив объектов { protocol, url }. Поле url должно быть HTTPS URL внутри scope приложения. Токен %s заменяется входным URL.

Chrome / Chromium: поддержка есть, но это не baseline-функция и зависит от окружения.

Safari: не поддерживается или практической пользы почти нет.

Простой пример для custom protocol:

{
  "protocol_handlers": [
    {
      "protocol": "web+music",
      "url": "/open?uri=%s"
    }
  ]
}

Пример с несколькими обработчиками:

{
  "protocol_handlers": [
    {
      "protocol": "web+jngl",
      "url": "/lookup?type=%s"
    },
    {
      "protocol": "web+jnglstore",
      "url": "/shop?for=%s"
    }
  ]
}

24. id

Что это: уникальный стабильный идентификатор приложения.

Зачем нужно: помогает браузеру понимать, что это именно одно и то же приложение, даже если у тебя со временем меняется start_url.

Практическое применение: это хорошая современная практика. Лучше задавать явно, а не полагаться на start_url как неявный идентификатор.

Значение: строка. Обычно используют путь или URL-подобный идентификатор внутри проекта.

Chrome / Chromium: очень полезно и рекомендуется.

Safari: даже если поддержка ограничена, указывать его безопасно.

Примеры:

{
  "id": "/webappmanifest"
}
{
  "id": "/apps/notes"
}

Пример вместе с start_url:

{
  "id": "/notes",
  "start_url": "/notes/?source=pwa"
}

25. launch_handler

Что это: управление тем, как приложение должно открываться при запуске.

Зачем нужно: особенно полезно на desktop, когда приложение уже открыто и нужно решить, использовать существующее окно или открыть новое.

Практическое применение: нужно для продвинутых desktop PWA-сценариев.

Структура: объект. На текущий момент основное поле - client_mode.

Chrome / Chromium: экспериментально.

Safari: не поддерживается.

Пример:

{
  "launch_handler": {
    "client_mode": "navigate-existing"
  }
}

Другой вариант:

{
  "launch_handler": {
    "client_mode": "auto"
  }
}

26. note_taking

Что это: экспериментальное поле, помечающее приложение как note-taking app.

Зачем нужно: операционная система может использовать это как подсказку, чтобы интегрировать приложение в сценарии “создать заметку”.

Практическое применение: имеет смысл только для приложений заметок.

Структура: объект. Из подтверждённых полей упоминается new_note_url.

Важно: это поле - подсказка. Реализация может проигнорировать его или использовать по-своему.

Chrome / Chromium: экспериментально.

Safari: не поддерживается.

Пример:

{
  "note_taking": {
    "new_note_url": "/notes/new"
  }
}

27. serviceworker

Что это: специальное поле для service worker в web-based payment app.

Зачем нужно: связано с Payment Handler API, а не с обычной офлайн-настройкой PWA.

Практическое применение: для обычных сайтов и PWA практически не нужно.

Структура: объект для платежного сценария.

Chrome / Chromium: только в узкой связке с Payment Handler API.

Safari: не поддерживается.

Пример общего вида:

{
  "serviceworker": {
    "src": "/payment-sw.js",
    "scope": "/",
    "use_cache": false
  }
}

28. share_target / files

Что это: вложенная часть share_target, которая отвечает именно за приём файлов.

Зачем нужно: позволяет получать изображения, документы и другие типы файлов из системного меню “Поделиться”.

Практическое применение: полезно для import flow, заметок, медиаприложений, редакторов и загрузчиков файлов.

Важно: для работы файлов нужно одновременно использовать method: "POST", enctype: "multipart/form-data" и массив files.

Структура файла: каждый объект содержит name и accept.

Chrome / Chromium: работает при корректной конфигурации установленного PWA.

Safari: не поддерживается.

Пример для изображений:

{
  "share_target": {
    "action": "/share-target/",
    "method": "POST",
    "enctype": "multipart/form-data",
    "params": {
      "files": [
        {
          "name": "images",
          "accept": ["image/png", "image/jpeg"]
        }
      ]
    }
  }
}

Пример для нескольких типов файлов:

{
  "share_target": {
    "action": "/import/",
    "method": "POST",
    "enctype": "multipart/form-data",
    "params": {
      "title": "title",
      "files": [
        {
          "name": "documents",
          "accept": [".pdf", "application/pdf", ".txt", "text/plain"]
        },
        {
          "name": "images",
          "accept": ["image/*"]
        }
      ]
    }
  }
}

29. protocol_handlers.mailto

Что это: частный пример использования protocol_handlers для протокола mailto.

Зачем нужно: если у тебя PWA работает как почтовый интерфейс, можно попытаться сделать его обработчиком email-ссылок.

Практическое применение: подходит в основном для почтовых и коммуникационных приложений.

Chrome / Chromium: возможен как часть механизма protocol handlers.

Safari: не поддерживается.

Пример:

{
  "protocol_handlers": [
    {
      "protocol": "mailto",
      "url": "/compose?to=%s"
    }
  ]
}

Пример с несколькими протоколами сразу:

{
  "protocol_handlers": [
    {
      "protocol": "mailto",
      "url": "/compose?to=%s"
    },
    {
      "protocol": "web+message",
      "url": "/messages/new?data=%s"
    }
  ]
}