diff --git a/frontend/nuxt.config.ts b/frontend/nuxt.config.ts index 628f17fd6..72653e37c 100644 --- a/frontend/nuxt.config.ts +++ b/frontend/nuxt.config.ts @@ -234,151 +234,7 @@ export default defineNuxtConfig({ periodicSyncForUpdates: 120, }, includeAssets: ["favicon.ico", "apple-touch-icon.png", "safari-pinned-tab.svg"], - manifest: { - name: "Mealie", - short_name: "Mealie", - id: "/", - start_url: "/", - scope: "/", - display: "standalone", - background_color: "#FFFFFF", - theme_color: process.env.THEME_LIGHT_PRIMARY || "#E58325", - description: "Mealie is a recipe management and meal planning app", - lang: "en", - display_override: [ - "standalone", - "minimal-ui", - "browser", - "window-controls-overlay", - ], - categories: ["food", "lifestyle"], - prefer_related_applications: false, - handle_links: "preferred", - launch_handler: { - client_mode: ["focus-existing", "auto"], - }, - edge_side_panel: { - preferred_width: 400, - }, - share_target: { - action: "/r/create/url", - method: "GET", - enctype: "application/x-www-form-urlencoded", - params: { - text: "recipe_import_url", - }, - }, - icons: [ - { - src: "/icons/android-chrome-192x192.png", - sizes: "192x192", - type: "image/png", - purpose: "any", - }, - { - src: "/icons/android-chrome-512x512.png", - sizes: "512x512", - type: "image/png", - purpose: "any", - }, - { - src: "/icons/android-chrome-maskable-192x192.png", - sizes: "192x192", - type: "image/png", - purpose: "maskable", - }, - { - src: "/icons/android-chrome-maskable-512x512.png", - sizes: "512x512", - type: "image/png", - purpose: "maskable", - }, - ], - screenshots: [ - { - src: "/screenshots/home-narrow.png", - sizes: "1600x2420", - form_factor: "narrow", - label: "Home Page", - }, - { - src: "/screenshots/recipe-narrow.png", - sizes: "1600x2420", - form_factor: "narrow", - label: "Recipe Page", - }, - { - src: "/screenshots/editor-narrow.png", - sizes: "1600x2420", - form_factor: "narrow", - label: "Editor Page", - }, - { - src: "/screenshots/parser-narrow.png", - sizes: "1600x2420", - form_factor: "narrow", - label: "Parser Page", - }, - { - src: "/screenshots/home-wide.png", - sizes: "2560x1460", - form_factor: "wide", - label: "Home Page", - }, - { - src: "/screenshots/recipe-wide.png", - sizes: "2560x1460", - form_factor: "wide", - label: "Recipe Page", - }, - { - src: "/screenshots/editor-wide.png", - sizes: "2560x1460", - form_factor: "wide", - label: "Editor Page", - }, - { - src: "/screenshots/parser-wide.png", - sizes: "2560x1460", - form_factor: "wide", - label: "Parser Page", - }, - ], - shortcuts: [ - { - name: "Shopping Lists", - short_name: "Shopping Lists", - description: "Open the shopping lists", - url: "/shopping-lists", - icons: [ - { - src: "/icons/mdiFormatListChecks-192x192.png", - sizes: "192x192", - }, - { - src: "/icons/mdiFormatListChecks-96x96.png", - sizes: "96x96", - }, - ], - }, - { - name: "Meal Planner", - short_name: "Meal Planner", - description: "Open the meal planner", - url: "/household/mealplan/planner/view", - icons: [ - { - src: "/icons/mdiCalendarMultiselect-192x192.png", - sizes: "192x192", - }, - { - src: "/icons/mdiCalendarMultiselect-96x96.png", - sizes: "96x96", - }, - ], - }, - ], - }, + manifest: false, // This is served via the backend, see mealie/routes/spa/manifest.py }, // Vuetify module configuration: https://go.nuxtjs.dev/config-vuetify diff --git a/mealie/routes/spa/__init__.py b/mealie/routes/spa/__init__.py index 16ff82993..a17022204 100644 --- a/mealie/routes/spa/__init__.py +++ b/mealie/routes/spa/__init__.py @@ -16,6 +16,7 @@ from mealie.core.config import get_app_settings from mealie.core.dependencies.dependencies import try_get_current_user from mealie.db.db_setup import generate_session from mealie.repos.repository_factory import AllRepositories +from mealie.routes.spa.manifest import serve_manifest from mealie.schema.recipe.recipe import Recipe from mealie.schema.user.user import PrivateUser @@ -251,4 +252,5 @@ def mount_spa(app: FastAPI): app.get("/g/{group_slug}/r/{recipe_slug}", include_in_schema=False)(serve_recipe_with_meta) app.get("/g/{group_slug}/shared/r/{token_id}", include_in_schema=False)(serve_shared_recipe_with_meta) + app.get("/manifest.webmanifest", include_in_schema=False)(serve_manifest) app.mount("/", SPAStaticFiles(directory=__app_settings.STATIC_FILES, html=True), name="spa") diff --git a/mealie/routes/spa/manifest.py b/mealie/routes/spa/manifest.py new file mode 100644 index 000000000..2c328bd7f --- /dev/null +++ b/mealie/routes/spa/manifest.py @@ -0,0 +1,125 @@ +import json +from urllib.parse import urlparse + +from fastapi import Response + +from mealie.core.config import get_app_settings + + +def serve_manifest(): + settings = get_app_settings() + sub_path = urlparse(settings.BASE_URL).path or "/" + + manifest = { + "name": "Mealie", + "short_name": "Mealie", + "id": "/", + "start_url": sub_path, + "scope": sub_path, + "display": "standalone", + "background_color": "#1E1E1E", + "theme_color": settings.theme.light_primary, + "description": "Mealie is a recipe management and meal planning app", + "lang": "en", + "display_override": ["standalone", "minimal-ui", "browser", "window-controls-overlay"], + "categories": ["food", "lifestyle"], + "prefer_related_applications": False, + "handle_links": "preferred", + "launch_handler": {"client_mode": ["focus-existing", "auto"]}, + "edge_side_panel": {"preferred_width": 400}, + "share_target": { + "action": "/r/create/url", + "method": "GET", + "enctype": "application/x-www-form-urlencoded", + "params": {"text": "recipe_import_url"}, + }, + "icons": [ + {"src": "/icons/android-chrome-192x192.png", "sizes": "192x192", "type": "image/png", "purpose": "any"}, + {"src": "/icons/android-chrome-512x512.png", "sizes": "512x512", "type": "image/png", "purpose": "any"}, + { + "src": "/icons/android-chrome-maskable-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable", + }, + { + "src": "/icons/android-chrome-maskable-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable", + }, + ], + "screenshots": [ + { + "src": "/screenshots/home-narrow.png", + "sizes": "1600x2420", + "form_factor": "narrow", + "label": "Home Page", + }, + { + "src": "/screenshots/recipe-narrow.png", + "sizes": "1600x2420", + "form_factor": "narrow", + "label": "Recipe Page", + }, + { + "src": "/screenshots/editor-narrow.png", + "sizes": "1600x2420", + "form_factor": "narrow", + "label": "Editor Page", + }, + { + "src": "/screenshots/parser-narrow.png", + "sizes": "1600x2420", + "form_factor": "narrow", + "label": "Parser Page", + }, + {"src": "/screenshots/home-wide.png", "sizes": "2560x1460", "form_factor": "wide", "label": "Home Page"}, + { + "src": "/screenshots/recipe-wide.png", + "sizes": "2560x1460", + "form_factor": "wide", + "label": "Recipe Page", + }, + { + "src": "/screenshots/editor-wide.png", + "sizes": "2560x1460", + "form_factor": "wide", + "label": "Editor Page", + }, + { + "src": "/screenshots/parser-wide.png", + "sizes": "2560x1460", + "form_factor": "wide", + "label": "Parser Page", + }, + ], + "shortcuts": [ + { + "name": "Shopping Lists", + "short_name": "Shopping Lists", + "description": "Open the shopping lists", + "url": "/shopping-lists", + "icons": [ + {"src": "/icons/mdiFormatListChecks-192x192.png", "sizes": "192x192"}, + {"src": "/icons/mdiFormatListChecks-96x96.png", "sizes": "96x96"}, + ], + }, + { + "name": "Meal Planner", + "short_name": "Meal Planner", + "description": "Open the meal planner", + "url": "/household/mealplan/planner/view", + "icons": [ + {"src": "/icons/mdiCalendarMultiselect-192x192.png", "sizes": "192x192"}, + {"src": "/icons/mdiCalendarMultiselect-96x96.png", "sizes": "96x96"}, + ], + }, + ], + } + + return Response( + content=json.dumps(manifest), + media_type="application/manifest+json", + headers={"Cache-Control": "no-cache"}, + )