code: function composer(componentMap) {
  
      return buildTemplateData;
  
      /**
       * Accepts a Hapi request object (containing Windshield config information) and
       * resolves everything Hapi/Vision needs to render an HTML page.
       *
       * @callback {buildTemplateData}
       * @param {Request} request - Hapi request object
       * @returns {Promise.<TemplateData>}
       */
      async function buildTemplateData(request) {
          const filterFn = composePageFilter(request);
          const pageContext = await resolvePageContext(request);
          const renderer = componentMap.composeFactory(pageContext, request);
          const renderedComponentCollection = await renderComponentSchema(pageContext.associations, renderer);
  
          // we only need the data to be in this intermediary format to support
          // the filtering logic.  We should streamline this out but that would
          // be a breaking change.
          const rawPageObject = {
              attributes: pageContext.attributes,
              assoc: renderedComponentCollection,
              layout: pageContext.layout,
              exported: renderedComponentCollection.exportedData
          };
  
          if (process.env.WINDSHIELD_DEBUG) {
              request.server.log('info', JSON.stringify(rawPageObject, null, 4));
          }
  
          const {assoc, attributes, layout} = await filterFn(rawPageObject);
          const template = path.join('layouts', layout);
  
          return {
              template,
              data: {
                  attributes,
                  assoc: assoc.markup,
                  exported: assoc.exported
              }
          };
      }
  }
docs: An object describing a template file and data that can be used to compile the template
  
  @typedef {Object} TemplateData
  @property {string} template        - The path to a Handlebars template file
  @property {object} data            - The data that will be used to compile the template into HTML
  @property {object} data.attributes
  @property {object} data.exported
  @property {Object.<string, string>} data.assoc - Hashmap of association names and HTML markup
   
  Composes a function that processes a Hapi request using Windshield adapters and context.
  
  We can't define the function we need at run-time, so this function will build it for
  us when we're ready.
  
  @param {ComponentMap} componentMap - Description of all available Windshield components
  @returns {buildTemplateData}