Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create PWA manifest.json dynamic?

I have created a functionality using static variablevariables in manifest.json such as :

 -- name
 -- short_name
 -- start_url

And it's working fine for the "Add To Home Screen". When I set manifest.json variable dynamically, the add to screen does not work

Basically I have an e-commerce PWA. My requirement is the following: if a user visits the app url (ex: www.example.com/products/PRODUCT_NAME_A ), he should be able to create a shortcut link on home screen or many they want based on different URLs.

You can also check my code that I have done so far in javascript:



var domain = document.location.origin;
var currentUrl = window. location. href;

var myDynamicManifest = {
    "name": "My App",
    "short_name": "My App",
    "description": "This is my App",
    "start_url": currentUrl,
    "scope": ".",
    "background_color": "#5F6EDD",
    "theme_color": "#efbc4b",
    "orientation": "portrait",
    "display": "standalone",
    "lang": "en",
    "dir": "ltr",
    "icons": [
        {
          "src"     : domain + "/images/logo/logo_70x70.png",
          "sizes"   : "70x70",
          "type"    : "image/png"
        },
        {
          "src"     : domain + "/images/logo/logo_120x120.png",
          "sizes"   : "120x120",
          "type"    : "image/png"
        },
        {
          "src"     : domain + "/images/logo/logo_144x144.png",
          "sizes"   : "144x144",
          "type"    : "image/png"
        },

    ]
    }

const stringManifest = JSON.stringify(myDynamicManifest);

const blob = new Blob([stringManifest], {type: 'application/javascript'});

const manifestURL = URL.createObjectURL(blob);

document.querySelector('#manifest').setAttribute('href', manifestURL);

I expected the output being like: http://prntscr.com/oej48u

like image 552
Er Parwinder Hirkewal Avatar asked Dec 23 '22 22:12

Er Parwinder Hirkewal


1 Answers

I realize this is an old question. But, I thought I'd pass along how I addressed the issue. My front end is served via Netlify and the back-end API is all GCP Cloud Functions. I added a Cloud Function that responds to /manifest?startUrl=...&name=... and returns the right manifest.json contents. Then, in the single page app, it dynamically updates the header <link /> to point to the appropriate URL when the page loads or the user navigates around.

client side:

const manifest = document.getElementById('manifest');
const nextManifest = document.createElement('link');
nextManifest.id = 'manifest';
nextManifest.rel = 'manifest';
nextManifest.href =
  `https://<cloud function host>/manifest?startUrl=${
    encodeURIComponent(`/events/${token}`)
  }&name=${encodeURIComponent(event.name)}`;
manifest.parentNode.replaceChild(nextManifest, manifest);

server side:


const manifest = {
  "short_name": "Photo Feed",
  "name": "Photo Feed",
  "icons": [
    {
      "src": "shortcut-icon.png",
      "sizes": "16x16",
      "type": "image/png"
    },
    {
      "src": "mobile-app-icon.png",
      "sizes": "180x180",
      "type": "image/png"
    }
  ],
  "start_url": ".",
  "display": "standalone",
  "theme_color": "#591A0C",
  "background_color": "#06B8B3"
};

/**
 * Responds to any HTTP request.
 *
 * @param {!express:Request} req HTTP request context.
 * @param {!express:Response} res HTTP response context.
 */
exports.manifest = (req, res) => {
  res.set('Access-Control-Allow-Origin', '*');

  if (req.method === 'OPTIONS') {
    res.set('Access-Control-Allow-Methods', 'GET');
    res.set('Access-Control-Allow-Headers', 'Content-Type');
    res.set('Access-Control-Max-Age', '3600');
    res.status(204).send('');
    return;
  }

  if (req.method === 'GET') {
    // take /?startUrl=<url> and return a manifest file
    // with `star_url`, same with name
    if (req.query.startUrl) {
      res.json({
        ...manifest,
        short_name: req.query.name || manifest.short_name,
        name: req.query.name ? `${req.query.name} Photo Feed` : manifest.name,
        start_url: req.query.startUrl,
      });
    } else {
      res.json(manifest);
    }
  }

  res.status(405).send();
};
like image 106
Eric Soderberg Avatar answered Jan 13 '23 14:01

Eric Soderberg