Guidance for FHIR IG Creation
0.1.0 - CI Build International flag

Guidance for FHIR IG Creation, published by HL7 International - FHIR Management Group. This guide is not an authorized publication; it is the continuous build for version 0.1.0 built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/FHIR/ig-guidance/ and changes regularly. See the Directory of published versions

Using the HL7 Templates

Overview

This template uses three primary inputs to determine the rendering of an implementation guide:

  • the implementation guide resource itself;
  • a set of resources that provide the computable description of what systems adhering to the implementation guide are expected to do; and
  • a set of additional descriptive pages that provide non-computable guidance to software developers and other users of the implementation guide

The result is a set of HTML pages that, together, provide a human-readable (and navigable) description of the IG's rules and contents.

This section of the implementation guide is broken into two sub-sections. The first describes how to author an implementation guide that leverages one of the standard templates. The second provides a walkthrough of the pages within the rendered implementation guide.

Authoring with templates

The process of authoring implementation guides is an iterative sequence of steps where artifacts are first created and edited and then the "publication process" is run (or the "IG is 'built'") to produce a rendered view of the content as well as a set of feedback on the IG's quality, such as whether the artifacts and examples validate correctly, whether links resolve, etc.

After reviewing the rendered content and/or quality feedback, the IG author goes back to the editing process until they are comfortable with the content, at which point the content generated by the publication process can be distributed or posted for use by the target community.

Directory Structure

The content used by (and produced by) the publication process is organized into a set of directories. The template depends on the source content being organized into a specific set of source folders. The temporary work products and final results of the publication process will also be put into a standard named set of folders.

The base directory structure for the IG publisher is as follows:

Folder Description
[igroot]

The root folder can be anywhere in the user's directory structure. However, it needs to be a folder where the user has free permission to create and edit files without additional administrative privileges.

In addition to containing the folders below, this folder holds a number of files related to the execution of the publication process and that support the automated execution of the process on continuous integration build environments.

[igroot]/input Folder where all source files are maintained. This is the only folder that needs to exist for a 'new' project. The contents of this folder should generally be managed under source control. (For HL7, this will be Git.)
[igroot]/input-cache Contains downloaded and/or generated files that are typically retained across multiple runs of the publisher. Some of the contents of this folder will typically also be managed under source control for performance reasons. (Further discussion below.)
[igroot]/output This contains the results of the publication process. The content in this folder is a set of static web pages and other artifacts that are intended to be posted/shared with those who need to read/use the implementation guide. The output folder will not be described here - essentially it contains whatever the IG publication process defines it to contain.
[igroot]/temp Contains files produced as part of the publication process. The contents of this folder are wiped and re-generated each time the publication process is run. They are retained after the publication run for diagnostic/debugging purposes in the event of issues with the publication process. However, the content can freely be deleted to make extra space. Editing files in this folder has no effect as the contents are wiped and replaced as part of each publication run.
[igroot]/template This contains files retrieved from the template repository that determine how source files are modified as part of the publication process and what the rendered view of different artifacts will look like, including color scheme, formatting, navigation, etc. Like the temp folder, it is regenerated for each run of the publication process and is only retained for diagnostic/debugging purposes. It can also be deleted to free space. Editing files in this folder has no effect as the contents are wiped and replaced as part of each publication run.

Authors may include additional folders at the root level, but they will be ignored by the publication process.

The contents of the temp and template folder are not described here as only those who author and maintain Implementation Guide templates will need to concern themselves with the contents of those locations. The remaining directories are discussed in more detail below.

[igroot]

This contains several files that drive the publication process. It may also contain additional files relating to source control or other processes. The files are listed in the order in which they're typically authored/used rather than in alphabetical order.

Several of the files below should be consistent across most/all implementation guides that use this publication framework. However, they cannot easily be shared across IGs. (Or at least we haven't figured out a good way to do that yet.) These files are all marked by **. Implementers are encouraged to download the version of these files found in the sample-ig implementation guide or at least to merge changes occasionally pushed to that IG with their own versions.

File Description
ig.ini

This key file has two key parameters:

  • "ig" indicates the path to the file containing the implementation guide XML or JSON file. (Typically this will be in the 'input' folder.)
  • "template" specifies the id, URL or local filepath of the IG template to use as part of the publication process. The 'id' approach can only be used if the template is 'trusted' by the IG Publisher and is managed in FHIR.org's continuous integration build (CI-build) environment

In addition, it may contain an optional third parameter: usage-stats-opt-out. If set to 'true', publishing this IG will not share usage stats about resources, extensions, operations, etc. with HL7. This information is used by HL7 to understand what portions of the FHIR specification are being used. No personal information is shared. Note that opt-out does not apply to any spec built using the FHIR ci-build infrastructure, or to any specifications for HL7 or IHE (as judged the presence of 'hl7.', 'ihe.' or 'argonaut.' in the package name.

_updatePublisher[.bat | .sh]**

This process retrieves the current version of the HL7 IG Publisher. It must be run before the publication process can be launched. The IG Publisher changes on a regular basis as enhancements are made and bugs are fixed. A warning will appear in the publication output if the version of the publisher used is out of date. A severely out-of-date publisher may occasionally cause the build process to fail. (So the first step in any publication failure is to make sure you're running with the latest publisher.)

The publisher will be stored in one of two locations. The default is to place it in the [igroot]/input-cache folder. However, for authors responsible for multiple IG repositories, this means keeping a copy of the publisher in each IG project (which consumes 80+ MB per IG) and also means downloading the IG separately for each IG. To mitigate this, the IGPublisher can also be placed as a sibling to the [igroot] folder. Simply move the [igroot]/input-cache/org.hl7.fhir.publisher.jar to the parent of the [igroot] folder. Once this is done for one IG, it will become the default location for all IGs that share that common parent folder. If any copies of the org.hl7.fhir.publisher.jar remain within the input-cache folders of any other child implementation guide folders, they can safely be deleted.

_genonce[.bat | .sh]** This initiates the publication process. Launching the .bat file (Windows) or .sh file (Unix/Mac) will launch HL7's IGPublisher program and build/publish the IG one time. This process checks for whether the publisher is found in the parent folder of the IG or within the input-cache folder. If found in neither place, an error will be raised and _updatepublisher will need to be run. This process also does a quick check to determine whether the machine on which the publisher is running has access to the HL7 terminology server or not and, if not, disables terminology lookup. This will allow the publication process to run when not connected to the internet or when the terminology server is down, however it means that some terminology validation will be skipped.
_gencontinuous[.bat | .sh]** This initiates the publication process. Launching the .bat file (Windows) or .sh file (Unix/Mac) will launch HL7's IGPublisher program in 'continuous' mode. See Invoking the IG Publisher.
package-list.json This file is needed for those projects publishing in HL7's continuous integration environment. It provides versioning and history information. The contents of the file are defined in Confluence.

HL7 international and many FHIR.org projects make use of Github as a source control environment. For those projects, the following additional files will likely be in your [igroot] folder:

File Description
.gitignore** This identifies files that should not be committed to source control (e.g. the files in the temp and template folders)
LICENSE A standard file used by Github to indicate what open-source license applies to the contents of the repository. For implementation guides published by HL7 International (including accelerator projects such as Da Vinci that use the HL7 ballot process), this must refer to HL7's FHIR license and the CC0 license.
README.md This provides a short description of the project for those browsing the Github environment
.git This is a hidden folder containing internal files used to manage the local Git repository and its linkage to the cloud-based repository.
[igroot]/input

The files that define the content of the IG, as well as those that guide the publication process are all found in this folder. The key contents are as follows:

File / Folder Description
[ig-id].[xml | json] This is the Implementation Guide resource. It defines key resource metadata, including the base table of contents for the IG. Specific requirements for the id and contents of this resource when used with the HL7 template are found below
ignoreWarnings.txt This file can be populated with any QA warning and information messages that should be ignored by the publication process. See QA for more details
[resource folder(s)]

There are several folders that can be used to contain resource content. In some cases, none of the folders will be present (because the IG doesn't define any resources). In other cases, many will be present. The choice of which folders to use (and what to put in them) is driven by author convenience. Some authors will prefer to shove all resources into the 'resources' folder. Others will prefer to split contents apart based on the type of artifact. This will be particularly common when different users are expected to maintain different types of artifacts. No checking is done about which artifact types are allowed in each folder. However, to minimize confusion, only artifacts that are 'appropriate' based on the name of the folder should go in that folder. I.e. Don't throw SearchParameter instances in the 'vocabulary' folder.

These folders will be searched for files in XML, JSON or TTL format that contain resource definitions. They will also be searched for Excel spreadsheets saved as XML which contain FHIR resources and/or extensions. See resource formats for details.

The potential 'resource' folder names supported by the template are:

  • capabilities (for CapabilityStatements/Conformance resources)
  • examples
  • extensions
  • models (for logical models)
  • operations
  • profiles
  • resources (for anything/everything or whatever doesn't fit one of the other folders)
  • vocabulary (for code systems & value sets)
[page folder(s)]

Like resources, there are also several folders that can be used to contain resource content. At least one of these folders MUST be present because all IGs must have at least an index page. Some IGs will have several. The choice of which folders to use (and what to put in them) is driven by author convenience. Some authors will prefer to shove all page content into the 'pages' folder. Others will prefer to split contents apart based on the type of content - generally to make it easier to find files.

Narrative content for the IG can be authored using either markdown (.md files) or XHTML (.xml files). See narrative formats. The processing of the content of the page folders will vary. Those .md and .xml files named to act as intro sections or notes sections will be injected into the base web pages for their respective resources. Other .md and .xml files will be processed and turned into HTML pages representing the narrative content for the IG. All other files will be copied to the output folder unchanged.

Additional guidance on what sort of pages to create - as well as how to organize them can be found below

The potential 'page' folder names supported by the template are:

  • pages (for the markdown or XHTML page content)
  • pagecontent (same purpose as pages - use whichever name you prefer)
  • intro-notes (intended for -intro and -notes files -see below for more details.
  • images (for jpg, png and other image files - or any binary content that should be copied to the published website.
includes

This is a special folder for content that will appear multiple places within the IG. In general, most of this is handled by the template itself. However, in some cases, it will be necessary for the same content to appear on multiple pages within the same IG. Such markdown and/or XHTML content can be placed here and then referenced using Liquid within other 'page' files within the IG. This is 'advanced' behavior and authors planning to do this should read the Shared Content section.

However, there is one file that all igs will need - menu.xml. This is an XHTML file that defines the content of the main menu. It is an XHTML unordered list. To see what one might look like, look at the sample-ig. Guidance on how best to structure IG menus can be found here.

NOTE: The representation of menus is more complicated than we'd like it to be - we hope to come up with a simpler way to represent this content in the future.

images-source This folder isn't actually used by the publication process at all. None of the content of this folder will ever be migrated to the published HTML site. However, it is strongly recommended that IGs have this folder anyhow. It is intended to include the source files used to generate any .jpg, .png or other images (or any 'generated' content) found in the pages or resources folders of the IG. This ensures that all content needed to maintain the IG is included in source control.
[igroot]/input-cache

This section of the IG won't cover the content of this folder in great detail. The main things to know are:

  • What subset of the content of this folder should be managed in source control?
  • What subset of the content in this folder might you occasionally need to delete?
File / Folder Description
org.hl7.fhir.publisher.jar This is the copy of the IG Publisher that is retrieved by the _updatePublisher[.bat|.sh] process (unless the publisher is shared in the IG's parent folder by multiple other IGs. This file should generally not be included in source control because a) it will cause commits and updates to be super slow; and b) it wastes lots of space in source control. If there's a need to retrieve previous copies of the IGPublisher (e.g. because the current version happens to be broken), historical versions can be found here. (After you download the desired version, move it into either [igroot]/input-cache or the parent folder and rename it to org.hl7.fhir.publisher.jar.) There should be no reason to delete this file - instead run _updatePublisher to grab the current version. Though you can delete the file if you're running short of harddrive space and won't need to re-run the publish process any time soon.
schemas

This folder will be generated after successfully (or even partially - provided the 'onGenerate' portion completes) running the IGPublisher. It will contain the XML and JSON schemas for the current FHIR release as well as all FHIR releases referenced by the implementation guide file. Its primary purpose is to provide schemas that can be referenced by the source files in the 'input' folder to allow validation when creating or editing the files.

This folder may be committed to source control to slightly improve performance. There should be no need to delete these files as the publication process will automatically update them if they're out of date.

txcache This folder will be generated during the resource validation process. It caches results of the terminology validation to improve performance on subsequent invocations. This folder SHOULD be committed to source control. However, it may occasionally need to be deleted. Once a cache entry for a given code system is created, it won't be updated - even if the underlying code system or value set changes. Prior to major publication milestones, such as balloting or official publication, the cache folder should be deleted and the build process should be run from scratch.

File content

This section describes in more detail the content expectations for the different types of files listed above.

The implementation guide
Todo - explain key metadata that must be present, use of groupings, extensions to refer to specific spreadsheets, use of ids to refer to resources, ordering of resources, defaulting of metadata for resources, toc being the root page, where index should go, where artifacts should go, position of pages in determining TOC hierarchy and order and section numbers, what parameters must be present, what parameters may be present. (Will probably want multiple subsections here.)
Resource formats

The primary mechanism for maintaining resources is authoring content in one of the official FHIR syntaxes. Content can be authored in either the 'current' draft version of FHIR (as of the time the publisher being used was released) or using one of the 'official' versions of FHIR (no earlier than DSTU2). It can be authored in XML, JSON or (if you really really want to...) Turtle. While schema references are not normally permitted in HL7 instances, they are allowed when authoring in the IG framework. This is generally the preferred mechanism because these files are easily managed in source control and because they can be consumed by most FHIR-based tools - though what versions and formats they support may vary.

For profiles and extensions, there is a second option that is available, at least for now - spreadsheets. Details on the mechanism for authoring spreadsheet files can be found here and here.

Narrative content

FHIR supports the authoring of page content (as well as intro and notes content) using two mechanisms: XHTML and Markdown.

XHTML is an XML-validatable version of HTML 4. FHIR constraints the XHTML content permitted to exclude active content (buttons, scripts, etc.) If these are needed, the relevant files must be defined in a trusted IG template and then referenced in the relevant files. XHTML provides complete control over the rendering of the page content - as it reflects exactly what will appear in the generated pages. It can also be validated using XML schema validation tools. However, it requires a certain degree of technical expertise to use.

Markdown is a text base syntax that uses specific text conventions to indicate how content should be rendered as XHTML. For example, a line starting with the "*" character, surrounded with appropriate whitespace, will be rendered as an XHTML un-ordered list item. The IG Publisher (or specifically, Jekyll) makes use of a markdown flavor called Kramdown. Guidance on writing Kramdown can be found here. Markdown is often very intuitive for authoring simple content. However, it is not validatable and small formatting errors can have a significant impact on how content is rendered. As well, sophisticated rendering (e.g. controlling table appearance) can be as complex as XHTML or may require injection of XHTML into the markdown. XHTML within markdown cannot be validated.

Regardless of which format is used, content should be organized under hierarchical headings. Because of how the templates work, headings in page content or intros or notes should always start at the third level. I.e. in markdown, they should start with ### and in HTML they should start with <h3>.

Liquid

Regardless of whether narrative content is authored using XHTML or markdown, it can also contain embedded Liquid commands. Most IG authors won't need to worry much about liquid as it is managed as part of the template process. Guidance on using liquid for more sophisticated capabilities is covered in the section of this IG that deals with authoring templates. However, even simple IGs may find a need for liquid in two circumstances:

  • When authoring page content, it's often desirable to be able to embed hyperlinks to the FHIR specification the IG is based on or to artifacts from higher level implementation guides the current guide depends on. However, over the course of an IG's lifetime, it may evolve to depend on different versions of the core FHIR specification and/or higher-level IGs. This is particularly true when authoring against the continuous integration build but needing to publish against frozen ballot snapshots or other releases. To simplify this process, best practice is to never hard-code the URLs of any FHIR version or higher-level IG into the web pages. Instead, the URLs (and, if relevant, their version names) are referenced by Liquid variables. The following table lists variables that are commonly referenced in IGs. (Full documentation on available variables can be found in the templates section.)

    Variable Use
    {{site.data.fhir.path}} The URL for the version of FHIR referenced by the implementation guide. The URL includes the trailing '/', so when referencing the files withing the IG, the format should be "{{site.data.fhir.path}}resourcelist.html" - i.e. no slash between '}}' and the file within FHIR being referenced
    {{site.data.fhir.version}} The version of FHIR referenced by the implementation guide
    {{site.data.fhir.[dependencyId]}} This gives the base URL of the implementation guide dependency listed in this IG with the specified 'id' attribute.
  • If page content includes content wrapped by curly braces {} - most commonly when showing example JSON content - Liquid processing can cause issues. That's because liquid commands are delimited by curly braces. If embedding JSON examples (or other curly-braced content) in your page content, put the string before the curly-braced content to disable Liquid processing and then put after the curly-braced content to turn liquid processing back on.

    NOTE: It's essential to turn liquid processing back on after turning it off, even if your page doesn't us Liquid. That's because content inserted around your pages (e.g. the standard page footer) will likely make use of Liquid.

Page files

Page files take on the name of the page as it will appear in the final publication, with the exception that the ".md" or ".xml" extension will be changed to a ".html" extension. I.e. a page named "background.xml" will become "background.html" in the final publication. Every IG *must* have a page called "index.[md|xml]" that defines the home page. In addition to defining the page file, each page must also be listed in the implementation guide itself, as described here. Recommendations on what pages should exist and what they should be named is covered in the Best practice portion of this IG.

Intros and Usage Notes

In addition to defining the narrative for individual pages, it's also possible to define narrative content that appears on the pages created for each resource - either before the resource description (intro text) or after the resource description (note text). This can work for any type of resource - profiles, extensions, value sets, examples, etc. The 'intro' section should provide additional information about what the artifact is for, how it relates to other artifacts, when it should be used vs. not, etc. The 'notes' section is to provide additional or specialized guidance.

The filenames for the intro and notes are [ArtifactType]-[id]-[suffix].[extension] where artifact type is the artifact in pascal case (e.g. ValueSet), the id is the resource id, the suffix is 'intro' for introduction and 'notes' for notes. The extension is either md or xml depending on whether it's markdown or xhtml.

Handling errors and warnings


In general you should attempt to address errors, warnings, and informational messages in the qa.html and qa.txt files through changes to your IG. Sometimes this is not possible or practical. For example, inevitably, some errors wil result from reported, but unresolved issues with the IG publisher or HL7 terminology services. Similarly the informational messages are instructions to the author to check certain things, but once checked, they contribute little to the QA reiew of an IG.

Warnings and information messages, and some errors, can be silenced by including them in the input/ignoreWarnings.txt file. Example content for this file is shown below, and includes full messages copied from the qa.txt file, along with explanatory text in '#' prefixed comments. The lines in the file should be grouped so that an explanatory comment precedes a series of messages that are to be ignored.

The content of the ignoreWarnings.txt file is included in the QA report to support review of the IG.


== Suppressed Messages ==
# Errors to suppress
# This is a known IG Publisher error
ERROR: /Users/skravitz/git/davinci-pdex-plan-net/fsh/build/output/searchform.html#/html/body/div/div/a/img/div/div/nav/div/div/ul/li/a at Line 64, column 21: The link 'history.html' for "History" cannot be resolved

# These are actual warnings to surpress
# The display values for NUCC Provider Taxonomy have been updated, and the HL7 Terminology server does not yet incorporate the updated values.

# The changes are all of the form adding a role at the end of the display name, so for example "Family Medicine" becomes "Family Medicine Physician"
WARNING: HealthcareService/BurrClinicServices: HealthcareService.specialty[0]: The display "Family Medicine" is not a valid display for the code {http://nucc.org/provider-taxonomy}207Q00000X - should be one of ["Family Medicine Physician"] (from http://tx.fhir.org/r4)

# Informational -- these examples are in the IG because they are examples of the referenced profiles. They are generated using FSH, so their profiles are correct by construction
INFORMATION: Endpoint/AcmeOfCTPortalEndpoint: Endpoint: Validate resource against profile http://hl7.org/fhir/us/davinci-pdex-plan-net/StructureDefinition/plannet-Endpoint

Using the IG publisher

todo - point to pages for installing pre-reqs (JDK 1.8+, Ruby, Jekyll). Also point to page on Git. Also talk about memory. Publisher options - explain the options that *can* be passed to the IGPublisher command line