Server-render and SEO


Hey everyone, just wondering if using the “server-render” package will allow Meteor compete with basic html/wordpress/etc pages when it comes to SEO or are there still some hurtles to overcome for search engines to see Meteor-based websites as intended?



I am wondering about this too. Also, are there any good tutorials about getting this working with react-router v3 or v4? Or are you better off just using FlowRouter (I’d rather use a more popular non-meteor solution if possible though)


I can show you how we use it in our application:


import React from 'react';
import {App} from "../imports/ui/app";
import {Helmet} from 'react-helmet';

if(Meteor.isClient) {

    import { render } from 'react-dom';

    render(<App />, document.getElementById('app'));

} else {

    import { renderToString } from "react-dom/server";
    import { onPageLoad } from "meteor/server-render";
    import NodeCache from 'node-cache';

    const renderCache = new NodeCache({stdTTL: 432000}); // 5 days

    onPageLoad(sink => {

        const path = sink.request.url.path;
        let htmlString = renderCache.get(path);
        if(!htmlString) {
            htmlString = renderToString(<App location={path} />);
            const helmet = Helmet.renderStatic(); // Needs to be called after renderToString

            renderCache.set(path + "_title",helmet.title.toString());
            renderCache.set(path + "_meta",helmet.meta.toString());
            renderCache.set(path + "_link",;

        sink.appendToHead(renderCache.get(path + "_title"));
        sink.appendToHead(renderCache.get(path + "_meta"));
        sink.appendToHead(renderCache.get(path + "_link"));
        sink.renderIntoElementById("app", htmlString);


And within your routes (React-Router):

import {browserHistory, createMemoryHistory, Router} from 'react-router';

class Routes extends React.Component {

    history = (Meteor.isClient) ? browserHistory : createMemoryHistory(this.props.location);

    render() {

       return (
           <Router history={this.history}>
              [...your routes...]

Meteor Scaling - Fusion Mode [Status: Beta]

Wow. That looks a lot more straight forward than I was expecting.

If you don’t mind me asking, what’s going on in the appendToHead calls you are doing for _title, _meta, and _link? Are those specific to Helmet (never used it before)? Or are you doing something home made here?


yeah, we add the meta/link tags to the output. On the first part, we cache those values too:

renderCache.set(path + "_title",helmet.title.toString());

path + “_title” is the key for the memory cache. At the end we add all generated meta/link tags to our response from the server:

sink.appendToHead(renderCache.get(path + "_title"));

Helmet has a doc for how you can use it with SSR. It’s pretty easy. The only thing I’m missing is how I can manipulate the HTML tag to add the lang attribute.


Hey X
Thanks to @benjamn for ssr. Besides Julian Ćwirko’s work with ssr and meteor which uses redux at - your use of @XTA ssr and meteor with is exceptional – great work. Is there any chance that you would be prepared share a basic boilerplate or submit your alternative ssr example to the meteor blog. Awesome work and keep it.


How are you getting those routes to work? You’re not importing it in main.js.