This blog post provides perspective on implementing data-driven web navigation with headless content management systems.
Hierarchical Data-Driven Navigation
Web navigation refers to elements that allow visitors to navigate the site including tab strips, eyebrows, toebrows, accordion menus, breadcrumbs, both visual and XML site maps, and so forth. Data-driven navigation refers to presentation components that use data from the CMS – specifically, parent/child relationships between records – to determine what links to render and in what markup nesting structures.
The navigational user interfaces of most web sites typically reflect hierarchical information architecture that function like filesystem directories and subdirectories. For example, a tab strip or accordion at the top of every page may contain links to the main sections of the website, such as /products, /services, /about, and so forth. When the mouse hovers over a tab such as /about, a flyout menu may show its children, such as /about/jobs, /about/investment, and so forth.
Whether called entries, items, or otherwise, Content Management Systems (CMS) expose records. All records have unique identifiers, and some records have URLs. Some products provide CMS user interfaces and application programming interfaces (API) that represent parent/children relationships between records. In web content management, URLs map to records, though not all records have URLs. To avoid hard-coding the mapping between URLs and record identifiers, the solution must contain two pieces of logic: one to determine the URL of a record and another to determine the record from a URL.
CMS that Represent Record Hierarchies
If the CMS represents records in hierarchies, then a slug field or other record property containing only characters that are safe in URL path elements can determine the URL of each record. For example, if a record named jobs is a child of a record named about, then the URL of jobs is /about/jobs. With a CMS that provides a hierarchy, to determine the record associated with a URL, code invokes the CMS vendor’s API.
CMS that Do Not Represent Record Hieararchies
CMS products that do not expose hierarchies between records often include a URL field for use in the content type definitions in which developers specify the fields that make up types of records. CMS users or programming logic enters values into this URL field to specify the URL of each record. To access the parent of a record, code can query for any record(s) with the URL of the current record truncated at the last slash character. To access the children of a record, code can query for records of all content types that have URLs that contain the URL of the current record plus a single additional slash followed by any value. With a CMS that does not provide a hierarchy, code can query the CMS for records of one or more content types with a value in the URL field that matches the path in the URL requested by the client (browser). A search index with fields specific to navigation can improve performance and simplify development. For example, all navigational presentation components could use a search index that contains fields for the URL and unique identifier of each records associated with a content type that has the URL field.
Whether or not the CMS represents records in hierarchies, all CMS support storing relationships between records. Just because the CMS provides a URL field does not mean that the solution must use that field to store the URL of each record. If the CMS does not represent data as a hierarchy, then developers can add a child field to the content types, allowing CMS users to select children records for each record. If each record also has a slug, then this approach can define the URLs of each record. For example, if the record that represents the home page specifies that the record named about is one of its children, then the URL of the about record is /about; if the about record specifies that jobs is one of its children, then the URL of the jobs record is /about/jobs. The order of records selected in the children field can affect the order in which links to those records appear in navigation elements. Developers can use these references between records to determine URLs and construct navigational elements that depend on hierarchical relationships between records that do not have URLs. In such cases, it may be appropriate to include a field to specify the parent of any record that can appear in the hierarchy. This can assist developers in writing code that walks up the hierarchy (for example, to create a breadcrumb) and in cases where a record could appear as a child under numerous other records but has one primary parent.
Whether and how a solution represents data as a hierarchy affect how developers access data. In general, even with caching, greater the number of records accessed, the worse the performance of the solution. The fact that navigational elements depend on data from numerous records provides another argument in support of using a search index to determine data to present in navigation. In addition to the URLs and identifiers of each record, the search index can contain fields for the text or other content to use in links to those records.
In the interests of saving time and keeping this blog post short, I may have oversimplified, and I often overlook options. If you have any suggestions for determining URLs for records and determining the record associated with a URL with headless content management systems, please comment on this blog post.