ostrio:flow-router-meta

Change meta tags, links to styles (CSS) and scripts on the fly within flow-router


Keywords
css, flow-router, js, meta-tags, metadata, meteor, meteor-package, meteorjs, opengraph, reactive-meta-tags, schema-org, seo, seo-meta, seo-middleware
License
BSD-3-Clause
Install
meteor add ostrio:flow-router-meta@=2.0.0

Documentation

Reactive meta tags, JavaScript and CSSs for Meteor and flow-router-extra

Change meta tags on the fly within flow-router-extra. This package can create meta tags, script and link tags as well.

This package may also help to use dynamic CSSs and JSs, so you may use different style sheets - for different routes.

Important Notice: This package oriented to work with flow-router-extra. It is extended fork of kadira:flow-router.

This package supports meta, script and link options (properties) defined on methods below, ordered by prioritization:

  • FlowRouter.route() [overrides all]
  • FlowRouter.group()
  • FlowRouter.globals [might be overridden by any above]

Note: this package implies ostrio:flow-router-title package.

ToC:

Install:

meteor add ostrio:flow-router-meta

Demo application:

ES6 Import:

import { FlowRouterMeta } from 'meteor/ostrio:flow-router-meta';

Usage:

You need to initialize FlowRouterMeta and FlowRouterTitle classes by passing FlowRouter object. Right after creating all your routes:

FlowRouter.route('/', {
  action: function () { /* ... */ },
  title: "Title"
  /* ... */
});

new FlowRouterMeta(FlowRouter);
new FlowRouterTitle(FlowRouter);

Set CSS and JS per route:

// Set default JS and CSS for all routes
FlowRouter.globals.push({
  link: {
    twbs: {
      rel: 'stylesheet',
      href: 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css'
    }
  },
  script: {
    twbs: 'https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js'
  }
});

// Rewrite default JS and CSS, for second route, via controller:
FlowRouter.route('/secondPage', {
  name: 'secondPage',
  action: function(params, query) {
    return this.render('layout', 'secondPage');
  },
  link: {
    twbs: {
      rel: 'stylesheet',
      href: 'https://maxcdn.bootstrapcdn.com/bootstrap/2.2.0/css/bootstrap.min.css'
    }
  },
  script: {
    twbs: 'https://maxcdn.bootstrapcdn.com/bootstrap/2.2.0/js/bootstrap.min.js'
  }
});

// Rewrite default JS and CSS, for route group:
var group = FlowRouter.group({
  link: {
    twbs: {
      rel: 'stylesheet',
      href: 'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha/css/bootstrap.min.css'
    }
  },
  script: {
    twbs: 'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha/js/bootstrap.min.js'
  }
});

group.route('/groupPage1', {
  name: 'groupPage1',
  action: function(params, query) {
    return this.render('layout', 'groupPage1');
  }
});

Use function as value:

FlowRouter.route('/routePath', {
  name: 'routeName',
  meta: {
    url: {
      property: 'og:url',
      itemprop: 'url',
      content: function() {
        return document.location.href;
      }
    }
  },
  link: {
    canonical: function() {
      return document.location.href;
    }
  }
});

Use function context:

Read about data hook.

FlowRouter.route('/post/:_id', {
  name: 'post',
  waitOn: function(params) {
    return [Meteor.subscribe('post', params._id)];
  },
  data: function(params) {
    return Collection.Posts.findOne(params._id);
  },
  meta: {
    keywords: {
      name: 'keywords',
      itemprop: 'keywords',
      content: function(params, query, data) {
        if (data == null) {
          data = {};
        }
        return data.keywords;
      }
    }
  },
  title: function(params, query, data) {
    if (data == null) {
      data = {};
    }
    if (data) {
      return data.title;
    } else {
      return '404: Page not found';
    }
  }
});

Other examples:

Set only name and content attributes on meta tag:

FlowRouter.route('/routePath', {
  name: 'routeName',
  meta: {
    name: 'content'
  }
});

Set only rel and href attributes on link tag:

FlowRouter.route('/routePath', {
  name: 'routeName',
  link: {
    rel: 'http://example.com'
  }
});

Set multiple attributes on meta tag:

FlowRouter.route('/routePath', {
  name: 'routeName',
  meta: {
    uniqueName: {
      name: 'name',
      content: 'value',
      property: 'og:name',
      itemprop: 'name'
    }
  }
});

Set multiple attributes on link tag:

FlowRouter.route('/routePath', {
  name: 'routeName',
  link: {
    uniqueName: {
      rel: 'name',
      sizes: 'value',
      href: 'value',
      type: 'value'
    }
  }
});

Bootstrap configuration:

FlowRouter.route('/routePath', {
  name: 'routeName',
  meta: {
    // <meta charset="UTF-8">
    charset: {
      charset: 'UTF-8'
    },

    // <meta name="keywords" content="Awes..">
    keywords: {
      name: 'keywords',
      itemprop: 'keywords',
      content: 'Awesome, Meteor, based, app'
    },

    // <meta name="description" itemprop="description" property="og:description" content="Default desc..">
    description: {
      name: 'description',
      itemprop: 'description',
      property: 'og:description',
      content: 'Default description'
    },
    image: {
      name: 'twitter:image',
      itemprop: 'image',
      property: 'og:image',
      content: 'http://example.com'
    },
    'og:type': 'website',
    'og:title': function() {
      return document.title;
    },
    'og:site_name': 'My Awesome Site',
    url: {
      property: 'og:url',
      itemprop: 'url',
      content: function() {
        return window.location.href;
      }
    },
    'twitter:card': 'summary',
    'twitter:title': function() {
      return document.title;
    },
    'twitter:description': 'Default description',
    'twitter:site': {
      name: 'twitter:site',
      value: '@twitterAccountName'
    },
    'twitter:creator': {
      name: 'twitter:creator',
      value: '@twitterAccountName'
    },
    'http-equiv': {
      'http-equiv': 'X-UA-Compatible',
      content: 'IE=edge,chrome=1'
    },
    robots: 'index, follow',
    google: 'notranslate'
  },
  link: {
    // <link href="https://maxcdn.bootstrapcdn.com/..." rel="stylesheet">
    stylesheet: "https://maxcdn.bootstrapcdn.com/bootstrap/2.3.2/css/bootstrap.min.css",

    // <link rel="canonical" href="http://example.com">
    canonical: function() {
      return document.location.href;
    },

    // <link rel="image" sizes="500x500" href="http://example.com">
    image: {
      rel: 'image',
      sizes: '500x500',
      href: 'http://example.com'
    },
    publisher: 'http://plus.google...',
    'shortcut icon': {
      rel: 'shortcut icon',
      type: 'image/x-icon',
      href: 'http://example.com'
    },
    'icon': {
      rel: 'icon',
      type: 'image/png',
      href: 'http://example.com'
    },
    'apple-touch-icon-144': {
      rel: 'apple-touch-icon',
      sizes: '144x144',
      href: 'http://example.com'
    },
    'apple-touch-icon-114': {
      rel: 'apple-touch-icon',
      sizes: '114x114',
      href: 'http://example.com'
    },
    'apple-touch-icon-72': {
      rel: 'apple-touch-icon',
      sizes: '72x72',
      href: 'http://example.com'
    },
    'apple-touch-icon-57': {
      rel: 'apple-touch-icon',
      sizes: '57x57',
      href: 'http://example.com'
    }
  },
  script: {
    twbs: 'https://maxcdn.bootstrapcdn.com/bootstrap/2.3.2/js/bootstrap.min.js',
    d3: {
      src: 'https://d3js.org/d3.v3.min.js',
      charset: 'utf-8'
    }
  }
});