Changing PWA App Name and Splash Screen

Dan Shockley:
When an app was started from the PWA template, where do you go to change out the “Digital Matters” proposed Add to HomeScreen app name and icon, as well as the splash screen when it launches?


Delfs:
you can set app.env items like that in the App model from the settings vertical tab


Delfs:
sorry that is the logo


Delfs:
the PWA settings are set in an onAppLoad global named action


Delfs:
We also have some updated code that you can add for PWA splash screen image generation. Ping team tomorrow and we can pass it in. It is in a newer version of that tempalte


Dan Shockley:
Thanks! That pointed me in the right direction, and I’ll be interested in that splash screen gen code.


Delfs:
in this screen for this action you can paste the following json in the aight most area for the TWO actions used for PWA

the first is for config, the second one does the business



![image](undefined)

---
![](upload://1om6kBJcNYszxGyrr8qi6ReFUya.png) **Delfs:** 

{
“action”: “function”,
“function”: “// PWA Manifest and related info\nlet manifest = {\n name: "Digital Matter App",\n short_name: "Digital Matter",\n icons: [{\n src: "https://ucarecdn.com/3aa65c6a-9a4a-404c-ae46-3f9cd4efb884/",\n sizes: "196x196",\n type: "image/png",\n purpose: "any"\n }, {\n src: "https://ucarecdn.com/3aa65c6a-9a4a-404c-ae46-3f9cd4efb884/",\n sizes: "196x196",\n type: "image/png",\n purpose: "maskable"\n }],\n start_url: https://${window.location.host},\n display: "standalone",\n background_color: "#ffffff",\n theme_color: "#ffffff",\n pwacompat: {\n // splashSourceUrl:\n // URL for the high-resolution source image used for dynamic splash generation.\n // This should be an image designed for full-screen splash usage—not just a small logo.\n splashSourceUrl: "https://ucarecdn.com/915e884d-c028-4ea4-b343-2a700e4999a9/",\n\n // backgroundColor:\n // The background color to use when generating the splash screen.\n // Defaults to the manifest’s background_color if not explicitly set.\n backgroundColor: "#1E0C3C",\n\n // mode:\n // Determines how the source image is drawn:\n // - "logo": Draw the image at a fixed fraction of the device width (centered), ideal for displaying a splash logo.\n // - "cover": Scale the image so it covers the entire splash area (object-cover behavior).\n mode: "cover",\n\n // logoScale:\n // In "logo" mode, the fraction (0–1) of the device width the logo should occupy.\n // For example, 0.7 means the logo is scaled to 70% of the device width.\n logoScale: 0.7,\n\n // forceBoth:\n // If true, the library will generate splash images for both portrait and landscape orientations.\n forceBoth: true\n }\n};\npwacompat: {\n // splashSourceUrl:\n // URL for the high-resolution source image used for dynamic splash generation.\n // This should be an image designed for full-screen splash usage—not just a small logo.\n splashSourceUrl: "https://ucarecdn.com/915e884d-c028-4ea4-b343-2a700e4999a9/",\n\n // backgroundColor:\n // The background color to use when generating the splash screen.\n // Defaults to the manifest’s background_color if not explicitly set.\n backgroundColor: "#1E0C3C",\n\n // mode:\n // Determines how the source image is drawn:\n // - "logo": Draw the image at a fixed fraction of the device width (centered), ideal for displaying a splash logo.\n // - "cover": Scale the image so it covers the entire splash area (object-cover behavior).\n mode: "cover",\n\n // logoScale:\n // In "logo" mode, the fraction (0–1) of the device width the logo should occupy.\n // For example, 0.7 means the logo is scaled to 70% of the device width.\n logoScale: 0.7,\n\n // forceBoth:\n // If true, the library will generate splash images for both portrait and landscape orientations.\n forceBoth: true\n}\n}\n\nBF.pwaSetManifest(manifest);”
}



---
![](upload://1om6kBJcNYszxGyrr8qi6ReFUya.png) **Delfs:** 
and sencond

{
“action”: “function”,
“function”: “/\n * pwacompat 3.0\n *\n * A library to dynamically generate and inject splash screen images\n * for installed PWAs on iOS (and optionally provide defaults for Android).\n *\n * It merges configuration from your manifest’s "pwacompat" property (if present)\n * with any options you pass to init().\n *\n * Usage example:\n *\n * // In your manifest.json, you could include:\n * // "pwacompat": {\n * // "splashSourceUrl": "https://example.com/full-splash.png",\n * // "backgroundColor": "#1E0C3C",\n * // "mode": "logo", // or "cover"\n * // "logoScale": 0.7,\n * // "forceBoth": true\n * // }\n *\n * // Then in your page (after load), call:\n * pwacompat.init({\n * // Optionally override any settings here:\n * // splashSourceUrl: ‘https://example.com/full-splash.png’\n * });\n *\n * Note: For full installability, include a <link rel="manifest" …> in your document.\n */\n\n(function() {\n ‘use strict’;\n\n /\n * Merges two objects, with properties in overrides taking precedence.\n * @param {Object} defaults\n * @param {Object} overrides\n * @returns {Object}\n */\n function mergeOptions(defaults, overrides) {\n const result = {};\n for (const key in defaults) {\n result[key] = defaults[key];\n }\n for (const key in overrides) {\n result[key] = overrides[key];\n }\n return result;\n }\n\n /\n * Fetches and parses the manifest from <link rel="manifest">.\n * Returns a Promise resolving to the manifest object or null.\n * @returns {Promise<Object|null>}\n */\n function fetchManifest() {\n return new Promise((resolve) => {\n const manifestLink = document.head.querySelector(‘link[rel="manifest"]’);\n if (!manifestLink) {\n resolve(null);\n return;\n }\n const manifestHref = manifestLink.href;\n const xhr = new XMLHttpRequest();\n xhr.open(‘GET’, manifestHref);\n const crossorigin = manifestLink.getAttribute(‘crossorigin’);\n if (crossorigin) {\n xhr.withCredentials = true;\n }\n xhr.onload = function() {\n try {\n const manifest = JSON.parse(xhr.responseText);\n resolve(manifest);\n } catch (e) {\n console.warn(‘pwacompat3: Error parsing manifest JSON’, e);\n resolve(null);\n }\n };\n xhr.onerror = function() {\n console.warn(‘pwacompat3: Failed to load manifest from’, manifestHref);\n resolve(null);\n };\n xhr.send();\n });\n }\n\n /\n * Loads an image from a URL.\n * @param {string} url\n * @returns {Promise}\n */\n function loadImage(url) {\n return new Promise((resolve, reject) => {\n const img = new Image();\n img.crossOrigin = "anonymous";\n img.onload = function() {\n resolve(img);\n };\n img.onerror = function(e) {\n reject(new Error('pwacompat3: Failed to load image: ’ + url));\n };\n img.src = url;\n });\n }\n\n /\n * Generates a splash image as a data URI.\n *\n * @param {HTMLImageElement} image - The source image.\n * @param {string} backgroundColor - Background color.\n * @param {string} mode - "logo" or "cover".\n * @param {number} logoScale - In "logo" mode, fraction of device width for the logo.\n * @param {string} orientation - "portrait" or "landscape".\n * @returns {string} Data URI (PNG).\n */\n function generateSplash(image, backgroundColor, mode, logoScale, orientation) {\n // Determine target dimensions (CSS pixels) based on orientation.\n let targetWidth = window.screen.width;\n let targetHeight = window.screen.height;\n if (orientation === "landscape") {\n [targetWidth, targetHeight] = [targetHeight, targetWidth];\n }\n const dpr = window.devicePixelRatio || 1;\n const canvasWidth = targetWidth * dpr;\n const canvasHeight = targetHeight * dpr;\n\n const canvas = document.createElement(‘canvas’);\n canvas.width = canvasWidth;\n canvas.height = canvasHeight;\n const ctx = canvas.getContext(‘2d’);\n\n // Fill background.\n ctx.fillStyle = backgroundColor;\n ctx.fillRect(0, 0, canvasWidth, canvasHeight);\n\n if (mode === "logo") {\n // Draw the image at a fixed fraction of the device width.\n const displayWidth = targetWidth * logoScale;\n const scale = displayWidth / image.width;\n const displayHeight = image.height * scale;\n const x = (targetWidth - displayWidth) / 2;\n const y = (targetHeight - displayHeight) / 2;\n ctx.drawImage(image, x * dpr, y * dpr, displayWidth * dpr, displayHeight * dpr);\n } else if (mode === "cover") {\n // "Cover" mode: scale the image so it covers the canvas.\n const scale = Math.max(canvasWidth / image.width, canvasHeight / image.height);\n const scaledWidth = image.width * scale;\n const scaledHeight = image.height * scale;\n const x = (canvasWidth - scaledWidth) / 2;\n const y = (canvasHeight - scaledHeight) / 2;\n ctx.drawImage(image, x, y, scaledWidth, scaledHeight);\n } else {\n console.warn("pwacompat3: Unknown mode ‘" + mode + "’, defaulting to ‘logo’.");\n return generateSplash(image, backgroundColor, "logo", logoScale, orientation);\n }\n return canvas.toDataURL("image/png");\n }\n\n /\n * Injects a <link rel="apple-touch-startup-image"> tag into the document head.\n *\n * @param {string} orientation - "portrait" or "landscape".\n * @param {string} dataUri - The splash image data URI.\n */\n function injectSplashMeta(orientation, dataUri) {\n const link = document.createElement(‘link’);\n link.rel = "apple-touch-startup-image";\n // Basic media query for orientation.\n link.media = (orientation: ${orientation});\n link.href = dataUri;\n document.head.appendChild(link);\n }\n\n /**\n * Initializes pwacompat 3.0.\n *\n * Configuration is merged from:\n * (a) default values,\n * (b) manifest.pwacompat (if available),\n * (c) explicit options passed to init().\n *\n * @param {Object} options\n */\n function init(options) {\n // Default configuration.\n const defaults = {\n backgroundColor: "#ffffff",\n mode: "logo", // "logo" or "cover"\n logoScale: 0.7,\n forceBoth: true\n };\n\n fetchManifest().then(manifest => {\n let manifestDefaults = {};\n if (manifest && manifest.pwacompat) {\n // Use custom pwacompat settings from the manifest.\n manifestDefaults = manifest.pwacompat;\n } else if (manifest) {\n // Fallback: use standard manifest properties.\n if (manifest.background_color) {\n manifestDefaults.backgroundColor = manifest.background_color;\n }\n }\n // Merge: explicit options override manifestDefaults, which override defaults.\n const config = mergeOptions(defaults, mergeOptions(manifestDefaults, options));\n\n if (!config.splashSourceUrl) {\n console.error("pwacompat3: ‘splashSourceUrl’ is required (either in options or in manifest.pwacompat).");\n return;\n }\n\n // Load the splash source image.\n loadImage(config.splashSourceUrl).then(image => {\n // Generate splash images.\n const portraitData = generateSplash(image, config.backgroundColor, config.mode, config.logoScale, "portrait");\n injectSplashMeta("portrait", portraitData);\n if (config.forceBoth) {\n const landscapeData = generateSplash(image, config.backgroundColor, config.mode, config.logoScale, "landscape");\n injectSplashMeta("landscape", landscapeData);\n }\n // console.log("pwacompat3: Splash images generated and meta tags injected.");\n }).catch(err => {\n console.error("pwacompat3: Error loading splash source image:", err);\n });\n });\n }\n\n // Expose the public API.\n window.pwacompat = {\n init: init\n };\n\n// console.log("pwacompat3: Module loaded. Call pwacompat.init(options) to generate splash images.");\n})();\npwacompat.init()\n\n”
}



---
![](upload://gnMRfotSo38iY7nhxCNFTDAJ3E3.jpeg) **Dan Shockley:** 
I had trouble with this at first, but it looks like that 1st block above repeats the `pwacompat` key again outside of setting the manifest variable. Once I removed that, it worked.
Thank you!

---