Q server

About Targets

With Q we want to provide the possibility to render visual elements based on the same data for diverse targets, i.e. differently styled websites, different devices (desktop, info screens, mobile) and different applications (browser, native apps).

So, in a nutshell we have to deal with two groups of target specifics.

Styling related specifics

For each tool - target - environment combination, additional rendering info can be configured in the config passed as app.tools to Hapi.server(). We use config/tools.js for this. It works the same for targets. The additional rendering info can be configured in the config passed as app.targets to Hapi.server(). The config is stored in config/targets.js. See our demo implementation for details. This additionalRenderingInfo object will be merged with the object returned from the defined endpoint of the tool before getting sent back to the client. We use this to apply the stylesheets of our styleguide system to theme the rendered output for different publications.

Tools

const tools = {
  $filter: 'env',
  production: {
    election_executive: {
    //...
    endpoint: {
      $filter: 'target',
      $default: false,
      demo1: {
        path: '/rendering-info/html-static', // endpoint path to get rendering info for this specific target
        additionalRenderingInfo: {
          stylesheets: [ // target specific stylesheets to load
            {
              url: 'https://service.sophie.nzz.ch/bundle/sophie-q@^1,sophie-font@^1,sophie-color@^1.css'
            },
            {
              content: '.q-item { color: #f5f5f5; background-color: #f5f5f5; }'
            },
            function(item, toolRuntimeConfig) {
              return {
                content: '.q-item { some styles generated at runtime }'
              }
            }
          ],
          scripts: [
            function(item, toolRuntimeConfig) {
              return {
                content: `console.log(${JSON.stringify(item)}`
              }
            }
          ]
        }
      },
      demo2: {
        path: '/rendering-info/html-static',
        additionalRenderingInfo: {
          stylesheets: [
            {
              url: 'https://service.sophie.nzz.ch/bundle/sophie-color@^1.css'
            },
            {
              content: '.q-item { color: #f5f5f5; background-color: #f5f5f5; }'
            },
            {
              content: '.s-font-note { color: black; font-size: 14px; }'
            }
          ]
        }
      }
    }
  //...
  }
  //...
}

Targets

const targets = {
  demo1: {
    label: "Demo 1",
    type: "Web",
    context: {
      //stylesheets
    },
    additionalRenderingInfo: {
      sophieModules: {
        $filter: "env",
        $default: [
          {
            url: "https://service.sophie.nzz.ch/bundle/sophie-q%23master.css"
          }
        ],
        production: [
          {
            url: "https://service.sophie.nzz.ch/bundle/sophie-q@^1.css"
          }
        ]
      }
    }
  }
};

Technology related specifics

Depending on the technical scope of a target different forms of rendering information may be provided by each tool. E.g. if your target cannot render any markup you may deliver an image instead. Please see Rendering Info? for details on that topic.

For that purpose you have to define an endpoint for each target and tool combination in config/tools.js of your Q server implementation. Otherwise, Q server will respond with Not implemented when trying to get rendering information for a Q item of a particular tool type and target.

Of course all of the specified endpoints per tool have to be implemented as well in the tool itself.

In the following example both targets - demo1 and demo2 - get its rendering info from the same endpoint of tool election executive

const tools = {
  //...
    election_executive: {
      //...
      endpoint: {
        $filter: 'target',
        $default: false,
        demo1: {
          path: '/rendering-info/html-static', // endpoint path to get rendering info for this specific target
          //...
        },
        demo2: {
          path: '/rendering-info/html-static',
          //...
        },
        demo3: {
          url: 'https://some-other-service.example.com/rendering-info', // you can use url to use an external service providing the rendering information
          //...
        }
      }
  //...
}

Preview in Q editor

To have a preview environment that matches your target as close as possible, you can configure stylesheets and scripts that will be loaded within the Shadow Root of the preview element in Q editor in config/targets.js. Use these to load any stylesheets and scripts that may influence the behaviour of your visual element when embedded in the target environment. Any stylesheets and scripts configured in context will be loaded in the preview.

const targets = {
  demo1: {
    label: "Demo 1",
    type: "web",
    context: {
      stylesheets: [
        /*{
          url: 'url to stylesheet specific for target'
        }*/
      ]
    },
    browserLoaderUrl: "https://q.nzz.ch/Q-demo-loader/loader1.js" // used to generate embed code to graphic
  },
  demo2: {
    label: "Demo 2",
    type: "web",
    context: {
      stylesheets: [
        /*{
          url: 'url to stylesheet specific for target'
        }*/
      ]
    },
    browserLoaderUrl: "https://q.nzz.ch/Q-demo-loader/loader2.js" // used to generate embed code to graphic
  }
};