Манифест — это JSON-файл, в котором написано всё, что нужно операционной системе, чтобы показать ваш сайт как приложение: имя на иконке, цвет шапки, набор иконок под разные размеры, режим запуска (с адресной строкой или без). Файл маленький, обычно укладывается в 30–50 строк. Но именно он отвечает за то, появится ли в Chrome кнопка «Установить приложение» и как сайт будет выглядеть после установки.
Имя файла и MIME-тип
Манифест может называться по-разному. Спецификация рекомендует имя с расширением .webmanifest и MIME-тип application/manifest+json:
app.webmanifest
Альтернативный вариант — manifest.json с MIME-типом application/json или text/json. Браузеры понимают и тот, и другой вариант. На практике .webmanifest чуть лучше, потому что валидатор сразу видит, что это именно манифест приложения, а не произвольный JSON.
Размещают файл обычно в корне сайта, чтобы scope был самый широкий (про scope — ниже).
Подключение в HTML
На каждой HTML-странице, которая входит в состав PWA, в <head> должна быть ссылка на манифест:
<link rel="manifest" href="/app.webmanifest">
Если страница без этой ссылки попадёт в кэш и пользователь её откроет напрямую, браузер не поймёт, что это часть PWA, и предложение установки не покажет. На больших сайтах ссылку обычно вставляют в общий шаблон лэйаута, чтобы не дублировать вручную.
Минимальный пример
Самый компактный валидный манифест, при котором Chrome покажет кнопку «Установить»:
{
"name": "Кофейная карта",
"short_name": "Кофе",
"start_url": "/",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#5e3719",
"icons": [
{
"src": "/icons/coffee-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "/icons/coffee-512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}
Ключевые поля
Разберём поля, которые встречаются почти в любом манифесте.
name и short_name
name — полное имя приложения. Показывается на сплэш-экране при запуске и в системных диалогах. short_name — короткое имя для подписи под иконкой на главном экране, где места мало (примерно 12 символов).
"name": "Прогноз погоды для путешественников",
"short_name": "Погода"
start_url
URL, который открывается по тапу на иконку. Если приложение должно стартовать с главной — пишут "/". Если есть отдельный экран запуска (например, /dashboard) — указывают его.
Полезный приём — добавить в start_url UTM-метку, чтобы в аналитике отделять открытия из установленного PWA от обычных визитов:
"start_url": "/?source=pwa"
display
Определяет режим запуска. Допустимы четыре значения, от самого «нативного» к самому «браузерному»:
- fullscreen — на весь экран, без статус-бара. Подходит для игр и плееров.
- standalone — собственное окно без адресной строки и вкладок. Самый частый выбор для PWA. Выглядит как нативное приложение.
- minimal-ui — окно с минимальным UI браузера: только кнопки «назад» и «обновить».
- browser — обычная вкладка браузера. Установка фактически ничего не меняет визуально.
icons
Массив иконок под разные размеры экранов и плотности пикселей. Минимум — две: 192×192 и 512×512 пикселей (требование Chrome для установки). Реально нужно больше, чтобы хорошо смотрелось на разной плотности:
"icons": [
{ "src": "/icons/icon-72.png", "sizes": "72x72", "type": "image/png" },
{ "src": "/icons/icon-96.png", "sizes": "96x96", "type": "image/png" },
{ "src": "/icons/icon-128.png", "sizes": "128x128", "type": "image/png" },
{ "src": "/icons/icon-144.png", "sizes": "144x144", "type": "image/png" },
{ "src": "/icons/icon-192.png", "sizes": "192x192", "type": "image/png" },
{ "src": "/icons/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any maskable" }
]
Свойство purpose: "maskable" на одной из иконок — чтобы Android мог обрезать её в любую форму (круг, скруглённый квадрат) под текущую тему ОС. Без этой иконки система может вписать вашу картинку в белый кружок, и получится некрасиво.
theme_color и background_color
theme_color — цвет рамки приложения. На Android окрашивает строку состояния. background_color — цвет сплэш-экрана, который показывается, пока загружается основной интерфейс.
Оба значения дублируйте в HTML мета-тегом — на случай, если браузер ещё не прочёл манифест, а страница уже рисуется:
<meta name="theme-color" content="#5e3719">
scope
Определяет, в каких URL приложение работает в собственном окне. По умолчанию равен директории, где лежит манифест. Если хочется, чтобы приложение покрывало весь сайт, — ставят "/". Если уйти за пределы scope (нажать на ссылку, которая туда не входит), браузер откроет её в обычной вкладке.
"scope": "/"
orientation
Принудительная ориентация при запуске: portrait, landscape или any (на усмотрение системы). Обычно ставят any, чтобы пользователь сам решал.
Как проверить, что манифест подхватился
В Chrome DevTools открыть вкладку Application → Manifest. Браузер покажет распарсенный манифест, иконки в виде превью, цвета. Внизу — список ошибок и предупреждений: каких полей не хватает для установки, какая иконка не найдена, какой цвет невалидный. Это самый быстрый способ дебага.
Картина по поддержке менее радужная, чем у service worker, и стоит знать нюансы:
- Firefox на десктопе манифест не поддерживает совсем — есть экспериментальная реализация за флагом browser.ssb.enabled, но это лабораторная функция, не для обычных пользователей. На Firefox Android манифест поддерживается, и сайт можно установить на главный экран.
- Opera на десктопе манифест тоже игнорирует, несмотря на Chromium-основу. На Opera Mobile работает.
- Safari на macOS добавил частичную поддержку только с версии 17: основные поля (name, short_name, иконки) применяются, многое игнорируется. На iOS Safari частичная поддержка есть с 11.3 — именно она нужна для функции «Добавить на экран «Домой»».
- Samsung Internet и Chrome Android поддерживают полностью.
Глобально: около 77% пользователей видят полную поддержку, ещё ~16% — частичную. Главный практический вывод: PWA-установка на десктопе работает у пользователей Chrome и Edge; на Firefox/Opera десктопе пользователи увидят обычный сайт без кнопки установки. На мобильных платформах ситуация значительно лучше — и Android, и iOS позволяют «Добавить на главный экран», пусть и с разным уровнем интеграции с ОС.