Skip to content

Comments

Fix manifest URL generation for PWA apps with query parameter-based language codes#410

Open
jsbalrog wants to merge 9 commits intofrontierMasterfrom
fix/manifest-query-param-issue
Open

Fix manifest URL generation for PWA apps with query parameter-based language codes#410
jsbalrog wants to merge 9 commits intofrontierMasterfrom
fix/manifest-query-param-issue

Conversation

@jsbalrog
Copy link

@jsbalrog jsbalrog commented Jan 29, 2026

The Problem

PWA apps using query parameter-based language codes (like /africa?lang=en) were generating malformed manifest URLs, causing browser console errors. The issue occurred because appPath('') returns the full app path including query parameters (e.g., /africa?lang=en), and the layout template was directly concatenating /manifest.json, resulting in invalid URLs like /africa?lang=en/manifest.json instead of /africa/manifest.json.

The Solution

We now strip query parameters from the app path before concatenating with /manifest.json in the layout template.

Before:

<link rel="manifest" href="<%= typeof appPathOverride !== 'undefined' ? appPathOverride : appPath('') %>/manifest.json" type="application/manifest+json" crossorigin="use-credentials" />

After:

      <%
        // Construct manifest URL using URL constructor to extract relative path with query params
        // e.g., http://localhost:5006/africa?lang=en/manifest.json becomes /africa/manifest.json?lang=en
        var url = new URL(appPath('/manifest.json'));
        var manifestUrl = url.pathname + url.search;
      %>
      <link rel="manifest" href="<%= manifestUrl %>" type="application/manifest+json" crossorigin="use-credentials" />

Impact

  • Affected apps: PWA apps using query parameter-based language codes (currently: Africa, Pacific).
  • Breaking change: No.
  • Apps not affected: Apps using path-based language codes (like /en/some-app) are unaffected as they don't have query parameters in appPath().

IMPORTANT: Apps using this fix must also update their server.js to properly serve PWA assets and prevent redirects. Changes Required in client PWA App's server.js:

  1. Define PWA assets (add after urlLookup definition):
// PWA assets that need to be served directly and exempted from language redirects
const PWA_ASSETS = [
 'favicon.ico',
 'app-name-192x192.png',      // Replace with your app's icon names
 'app-name-512x512.png',
 'app-name-512x512-maskable.png',
 'app-name-screenshot1.png',
 'app-name-screenshot2.png',
 'app-name-screenshot3.png',
]
  1. Exempt assets from language redirects (in snowConfig):
pathsExemptedFromUrlLangs: ['/manifest.json', ...PWA_ASSETS.map((asset) => `/${asset}`)],
  1. Add routes to serve PWA assets (in postRoute section, BEFORE the catch-all * route):
// Serve manifest.json directly (ignore query parameters like ?lang=en)
snowApp.get('*/manifest.json', (_req, res) => {
  res.setHeader('Content-Type', 'application/manifest+json')
  res.sendFile(path.join(__dirname, 'public', 'manifest.json'))
})

// Serve PWA icon files directly from public directory
PWA_ASSETS.forEach((asset) => {
  snowApp.get(`*/${asset}`, (_req, res) => {
    res.sendFile(path.join(__dirname, 'public', asset))
  })
})

Why these changes are needed:

  • Without the exemptions, Snow redirects these requests to add ?lang=en.
  • Without the server.js routes, requests fall through to the catch-all SPA route, returning HTML instead of the actual files.
  • Using a PWA_ASSETS constant (or similar) ensures the list is maintained in one place.

Additional Context

  • Related to Snow's language code handling for PWA paths (configured in FS_CLIENT_APP_LANG_QUERY_PARAM_PATHS environment variable) in an app's .env file.
  • Apps will also need server-side changes, described above, to prevent redirects and properly serve PWA assets (handled in individual app PRs).
  • This fix ensures the HTML manifest link is correctly formatted; server-side configuration ensures the manifest is served without redirects.

@redbugz
Copy link

redbugz commented Jan 30, 2026

So the real problem is that we are indiscriminately concatenating paths instead of using proper URL hygiene. Can we use appPath('/manifest.json') instead? Otherwise we should put the appPath() result into the URL constructor and append the path the correct way? The problem isn't that there is a lang query on the manifest.json, it's that the string concatenation of URLs is a bad idea and we got bit our own bad behavior and generated improper URLs with string concatenation. So let's fix the string concatenation. If we still want to strip the lang param or all query params we can, but it won't matter or break things if it's there in the proper place. And we should use proper URL techniques to manipulate the URL. including removing the query params

@jsbalrog jsbalrog marked this pull request as ready for review February 18, 2026 14:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants