The FHIR team provides an IG Publishing tool that takes the source of an implementation guide content and converts it to published IG that contains:

  • A set of human readable files for the Implementation Guide
  • An NPM package file "package.tgz" that represents the computer processable portions of the IG, along with several other different collateral files that may be useful for implementers 
  • The entire IG output is is provided as

The IG publisher doesn't address the process of building the source of the implementation guide; other tools exist to address this issue: Sushi, Simplifier, Trifolia, or the source can be edited using text/json/xml editors. 

The outcome of the publishing process is a set of HTML files that represent the implementation guide. These files are not suitable for posting to a web server - see Publishing to a Web Server below.

Alternatively, you may use the IG publisher to validate and render a set of Profiles, value sets etc without building a formal IG (see command line mode)

If you wish to publish an IG through HL7 or the FHIR Foundation, you should also familiarize yourself with the FHIR Implementation Guide Publishing Requirements. Other organizations have their own guides.

This page focuses on the way the content is managed. For information about executing the IG publisher, see IG Publisher CLI

HL7 also maintains a specification that provides guidance and best practices on IG development, profiling, terminology use, etc. in the IG-Guidance IG.

Managing Implementation Guides

Typically, implementation guide publishing works like this:

  • the master source for an implementation guide is in a public GitHub repository
  • it is edited as a variety of text files using text editor and specialist editors (common formats: json, xml, fsh, fml, ini, yaml etc) 
  • guide authors can run their own local build and share the set of files ( is automatically produced, for convenience) with anyone they want to
  • a CI build is published so everyone can see the output - see [Auto-IG-Publisher Documentation]
  • when formal milestones are achieved, the Implementation Guide is published to the canonical web site for the IG (typically,,, or, but need not be) (See Standard FHIR Publishing Layout Pattern for additional guidance)

Non-public Implementation guides can still use the IG build, but cannot use the CI Build infrastructure

For IGs developed on the infrastructure, see the Simplifier Implementation Guide documentation for publishing details.


If you want an example of IG source, you can look in one of the following places:

Validating without publishing

There is an alternative mode, where you run the IG publisher against a collection of conformance resources (profiles, logical models, value sets etc) without defining an implementation guide. This allows you to validate a set of profiles, and see what they look like. To run the IG publisher in this mode:

 java -jar publisher.jar -source [source] -destination [dest] (-tx [url])

Where source is a directory containing the conformance resources, destination is where to put the generated output (validation.html is the most important). In this case, the IG publisher uses its own internal control file and renders a simple version of the output.

Operation of the IG Publisher

Once running, the publisher:

  • reads the ini file which tells which IG to open, and which template to use
  • reads the IG
  • places the template in the template folder
  • processes any spreadsheets, bundles, and logical models
  • loads all the resources in the IG
  • processes code systems, value sets, structure definitions, structure maps
  • validates the all resources in the IG and produces an HTML QA file with any errors encountered
  • for each resource in the IG, generates a set of files - renderings of the artifact for possible inclusion in the published IG, plus the outputs defined above
  • generates summary output
  • gets the tool (Jekyll) to generate the final output. The Jekyll source is in /pages by default

If you'd like to use another website generation tool, discuss your tool of choice with Grahame Grieve.

IG INI file

When starting the publisher from the command line, it can be pointed at a ini file :

java -jar publisher.jar -ini ig.ini

(When using the template approach, this is the command line executed by the _genOnce.bat / .sh script.)

ig.ini is a file that contains 2 parameters:

  • where to find the IG
  • which template to use

ig.ini parameters

The IG.ini file defines the path of the ig source, and the template (including "official" or local templates, and including supporting specific versions of the template).

The sample IG contains a documented example for the ig.ini:

Terminology Service Cache

The IG Publisher uses a terminology server to support it's operations at In order to improve operational performance, the IG publisher caches the outcome of all interactions with the terminology server. This makes a substantial difference to the performance of the publication, but also means that there's a risk of the terminology content becoming stale.

IG authors can choose to put the terminology cache into version control. This means that all builds (either by authors or by CI builds) get the same content, and reduces the load on the terminology server. Also, all authors get fully efficient publication. This also means that flushing the terminology cache is under the control of the editors process. It also means that editors have to commit the contents of the txCache when committing. Note that there is never any reason not to simply commit whatever changes have happened, and no user review is needed on this.

Note that the CI build does not maintain it's own persistent cache; if the terminology cache is not in version control, it will not have a terminology cache.

There are several ways to delete the terminology service cache:

  • find the directory and manually delete content from it (e.g. all files). This is can be done safely at any time
  • run the IG Publisher with the parameter -resetTx - this clears the folder
  • run the IG Publisher with the parameter -resetTxErrors - this clears the folder of any errors from the terminology server but keeps successful operations
  • the terminology cache will be flushed completely when the terminology server is upgraded

Fragment Codes

Note: as of July 2023, this list is not comprehensive 

There will be one each of these fragments for each resource type that is found:

  • xml: XML version of the resource (all resource types)
  • json: JSON version of the resource (all resource types)
  • ttl: Turtle version of the resource (all resource types)
  • xml-html: html representation of XML version of the resource (all resource types)
  • json-html: html representation of JSON version of the resource (all resource types)
  • ttl-html: html representation of Turtle version of the resource (all resource types)
  • html: narrative of resource as html
  • summary: An html summary for the resource (all conformance resources)
  • content: An HTML representation of the content in resource (code system, concept map, structure map)
  • xref: A list of all the places where the resource is used (all conformance resources)
  • cld: An HTML representation of the content in resource (value set)
  • expansion: The expansion of the value set (Value set)
  • shex: ShEx statement for the structure (Structure Definition)
  • sch: schematron statement for the structure (Structure Definition)
  • java: Java Class for the structure (Structure Definition)
  • json-schema: JSON Schema statement for the structure (Structure Definition)
  • header: Description of the identification of the structure (Structure Definition)
  • diff: Logical Table of the diff (Structure Definition)
  • snapshot: Logical Table of the snapshot (Structure Definition)
  • pseudo-xml: XML template for the snapshot (Structure Definition);
  • pseudo-json: JSON template for the snapshot (Structure Definition)
  • pseudo-ttl: Turtle template for the snapshot (Structure Definition)
  • uml: UML diagram for the structure (Structure Definition)
  • tx: Terminology Notes for the structure (Structure Definition) (all elements, snapshot)
  • tx-must-support: Terminology Notes for the structure (Structure Definition) (must-support elements, snapshot)
  • tx-diff: Terminology Notes for the structure (Structure Definition) (all elements, differential)
  • tx-diff-must-support : Terminology Notes for the structure (Structure Definition) (must-support elements, differential)
  • inv: invariant summary for the structure (Structure Definition)
  • dict: Detailed Element Definitions (Structure Definition)
  • dict-active: Detailed Element Definitions (Structure Definition), but only including elements with max cardinality > 0
  • maps: Presentation of the mappings (Structure Definition)
  • span: Presentation of all profiles a profile refers to (StructureDefinition where derivation = constraint)
  • spanall: Presentation of all profiles & base resources a profile refers to (StructureDefinition where derivation = constraint)
  • script: Script language rendition of a StructureMap (StructureMap)
  • profiles: List of Profiles generated from a StructureMap (StructureMap)
  • maturity: Banner with resource maturity (all resources)
  • history: a table with a list of changes to the resource (or empty, if no related Provenance resources are found - see below)
  • for each list in the IG, the publisher can produce the following fragments:
    • list-list - a list with descriptions
    • list-list-simple: a list with no descriptions
    • list-table-xx - a table, with 2 columns for name and description
    • Note that for lists, 3 variants are produce, in the order of the list, and in alphabetical by type/id and name

In addition, the publisher produces the following set of fragments for listing all the content:

  • list-[type].xhtml
  • list-simple-[type].xhtml
  • table-[type].xhtml

These 3 are also produced with a -mm (e.g. list-[type]-mm.xhtml) that includes maturity levels for each resource, where it is known. (note that the maturity numbers are in an <a> tag with class="fmm", for styling purposes)

If there are any structure definitions of the right type, the publisher will also produce the following:

  • table-profiles.xhtml & list-profiles.xhtml
  • table-extensions.xhtml & list-extensions.xhtml
  • table-logicals.xhtml & list-logicals.xhtml

Also, -mm variants (see above) are produced for these as well


For Jekyll, some data files are also generated. The data from these is available when generating pages. e.g.

 {{ }} 

inserts the version of the FHIR specification used by the build. The following data is available:

  • path : path to the main FHIR specification
  • canonical : canonical path to this specification
  • packageId : package id for this IG
  • errorCount : number of errors in the build file (not including HTML validation errors)
  • version : version of FHIR
  • revision : revision of FHIR
  • versionFull : version-revision
  • igVer : business version of the IG
  • toolingVersion : version of the publisher used
  • toolingRevision : Revision of the publisher used
  • toolingVersionFull : toolingVersion (toolingRevision)
  • totalFiles : total number of files found by the build
  • processedFiles : number of files genrated by the build
  • genDate : timestamp of generation (so date stamps in the pages can match those in the conformance resources)
  • genDay : date of the generation
  • ig.title : Full human title for the IG
  • ig.status : FHIR status of the IG (e.g. 'active')
  • ig.experimental : Value from ImplementationGuide.experimental
  • ig.publisher : The string from ImplementationGuide.publisher
  • ig.gitstatus : The git branch published from
  • : From the same ImplementationGuide element
  • ig.description : From ImplementationGuide.description

Within the same file, there will also be variables created for each implementation guide dependency based on the dependency 'id'.  For example, if your implementation guide has a dependency that looks like this:

    <dependsOn id="uscore">
        <uri value=""/>
        <packageId value=""/>
        <version value="3.1.1"/>


  "dependsOn": [
      "id": "uscore",
      "uri": "",
      "packageId": "",
      "version": "3.1.1"

Then you can also access

To access other dependencies, simply substitute "uscore" with whatever the 'id' is for the specific dependency.

Also, a file generated for the structure definitions. Each structure definition is listed by it's id, along with the following data for each id. For example this is some Jekyll liquid syntax to access the Resource type from an example instance using the type parameter from the list below.

   include list-{{{{[id]}}.type | slugify }}.xhtml
  • url : full canonical url for the structure
  • name : the name given for it
  • path : the path to it in the built html
  • kind : the kind (complex data type, resource, logical model)
  • type : the base type
  • base : the url for structure definition from which it derives
  • basename : the name of the structure definition from which it derives
  • basepath : the url to the structure definition from which it derives
  • status : the status (draft, active, retired)
  • date : the date in the resource
  • publisher : the stated publisher
  • copyright : the stated copyright for the resource
  • description : the description for the resource
  • contextType : the type of context associated with an extension structure definition
  • contexts : an array of paths for each allowed context path for an extension

History Entries

You can add a list of change history for any artifact. These appear in the -history tab for that artifact. To add change history entries, create Provenance resource(s) for each change history entry, with .target pointing to the artifact(s), of who made the change, and .reason.text as the explanation of what or why the change happened. The history entries will be sorted on the .occurredDateTime. These Provenance resources must not be marked as examples (i.e., Sushi Usage #definition, or implementation guide exampleBoolean=false). These Provenance can be carried in a Bundle of type "collection".

"resourceType" : "Provenance",
"id" : "{id}", // make sure it is unique
"target" : [{ "reference" : "{{type}}/{{id}}" }],
"occurredDateTime" : "{{when change made}}", // mandatory
"reason" : [{
"text": "{{text comments}}"
"activity" : { // mandatory
"coding" : [{
"system": "",
"code" : "UPDATE"
"agent" : [{
"type" : {
"coding": [{
"system": "",
"actor" : {
"display" : "{{author}}"
"type" : {
"coding": [{
"system": "",
"actor" : {
"display" : "{{committee}}"

Rules for Implementation Guides


Canonical URL

The Implementation Guide must nominate a canonical URL, which we'll refer to as [canonical]. This canonical URL is used throughout all the resources (this is enforced by the publisher). The canonical URL should point to the current version of the IG that you're publishing, so if someone enters the canonical URL into their browser, they will get the IG home page (for example,

If possible, this should also be a FHIR server hosting resources - so a GET of [canonical]/[Type]/[id] should return a FHIR resource. For example, would give you a sample Patient resource used throughout the specification.


The ImplementationGuide.url element in your ImplementationGuide resource should be set to [canonical]/ImplementationGuide/[id], and that should redirect you to the base URL when entered into the browser - for example, entering ImplementationGuide.url of in the browser should take you to


Each Implementation Guide is also responsible for maintaining it's own published history. The standard way that this works for FHIR should be followed by the implementation guides:

  • The current copy of the specification lives at [canonical]
  • the published version history lives at [canonical]/directory.html (or similar name) and is manually maintained. It lists the current version, maybe the dev version location, and a history of past milestones
  • the past milestones live at [canonical]/[id] where id is either a milestone name like "stu1" or a date (recommended format = YYYY)
  • at least the home page of all the versions (current or historical) references the published version history in a prominent location

The IG publisher is only able to produce a single snapshot of the IG at a time - so in order to create your history, you'll need to manually move old versions to [canonical]/[id] and update the [canonical]/directory.html with a link to it.


All the generated fragments are generated assuming that the standard FHIR styles in fhir.css apply to the specified classes in the generated content. To keep the content valid, the simplest way is to include fhir.css in all your html pages as a style reference. But you don't have to do this; if you have some other styling system, you can make arrangements for the correct css definitions - which are deliberately very static - to be made available in some other form. You can even replace the styles completely and use your own.

Note, however this warning: The FHIR team does not provide support for replacing any CSS styles. In order to assist with this, for every generated fragment, there is a matching .html file created in the qa directory. The FHIR team will respond to any issue relating to incorrect display of the content of the qa html files. If the content does not appear correctly in the IG, but does appear correctly in the qa files, then this is assumed to be a problem with the IG styling, and not the problem of the IG Publisher authors.

For further information, see under templates


Notes about troubleshooting:

  1. before doing any trouble shooting, make sure you are running the latest IG publisher for the version of FHIR you are using
  2. Jekyll may not run if you have spaces your file path. Move to root directory, or eliminate spaces.
  3. if the Jekyll part of the build fails, it fails completely, and the old output is left in place
  4. if the build completes, and there's problems in the output, first, work through all the errors in the validation output before you ask for help
  5. Jekyll error "Permission denied @unlink_internal" - you have a file locked in the temp or output directory. Close any files in editors, and ensure you are only running one publisher
  6. If you're going to ask Grahame for help send the file fhir-ig-publishing.log in your temp directory to along with a detailed description of what the problem is. (Alternatively, run the GUI version click, wait for the end ofthe run, and the click on the 'Debug Summary' button which puts the log on the clipboard so you can send pate it into your email)

Before you ask about any terminology or dependency related issues, delete the content of your txCache directory, and run the IG publisher again


The IG publisher performs 3 sorts of logging:

  • basic progress logging to stdout (what you see)
  • A full log to [tmp]/fhir-ig-publishing-tmp.log
  • in case of build failure, a debugging report to fhir-ig-publishing.log

You can change to amount of logging that goes to stdout using parameters in the IG.

Where the options are any of these words:

  • init: log extra details about the IG publisher initialization sequence
  • progress: log extra details about the sequence of actions taken by the IG publisher
  • context: log each time a resource is added to the context (e.g. support validation)
  • html: log HTML link checking details
  • tx: detailed messages from the terminology sub-system

This is particularly useful when debugging the auto-build when all you get is the stdout.

  • No labels