Build apps

Using LinkedDataHub as a low-code platform for Knowledge Graph applications

Every component in LinkedDataHub is data-driven and was designed with extensibility in mind. You can override behavior (e.g. Java method or XSLT template) without having to modify LinkedDataHub's codebase, and more importantly, without having to write the same logic from scratch.

The following sections are split by component/layer and explain how to extend them when building bespoke apps.


You can go a long way just by mounting files (e.g. config files, ontologies, stylesheets) into LinkedDataHub's default Docker setup. But you may also want to build a dedicated Docker image for your app using LinkedDataHub as the base. Usually this is done to COPY files inside the the image or RUN additional commands.

Here's an sample Dockerfile that copies custom stylesheets into the app's Docker image:

FROM atomgraph/linkeddatahub:4.0.0

USER root

RUN curl -fsSL | bash - && \
    apt-get update --allow-releaseinfo-change && \
    apt-get install -y nodejs && \
    rm -rf /var/lib/apt/lists/* && \
    mkdir /home/ldh && chown ldh:ldh /home/ldh

USER ldh

RUN npm install saxon-js && \
    npm install xslt3


COPY --chown=ldh:ldh files/layout.xsl net/example/xsl/layout.xsl
COPY --chown=ldh:ldh files/client.xsl net/example/xsl/client.xsl

# pre-processing stylesheets in order to inline XML entities which SaxonJS does not support
RUN curl${SAXON_VERSION}/Saxon-HE-${SAXON_VERSION}.jar -O && \
    cat com/atomgraph/linkeddatahub/xsl/client.xsl | grep 'xsl:import' | cut -d '"' -f 2 | xargs -I{} java -cp Saxon-HE-${SAXON_VERSION}.jar net.sf.saxon.Query -qs:"." -s:com/atomgraph/linkeddatahub/xsl/{} -o:com/atomgraph/linkeddatahub/xsl/{} && \
    cat com/atomgraph/linkeddatahub/xsl/client.xsl | grep 'xsl:include' | cut -d '"' -f 2 | xargs -I{} java -cp Saxon-HE-${SAXON_VERSION}.jar net.sf.saxon.Query -qs:"." -s:com/atomgraph/linkeddatahub/xsl/{} -o:com/atomgraph/linkeddatahub/xsl/{} && \
    java -cp Saxon-HE-${SAXON_VERSION}.jar net.sf.saxon.Query -qs:"." -s:com/atomgraph/linkeddatahub/xsl/client.xsl -o:com/atomgraph/linkeddatahub/xsl/client.xsl && \
    java -cp Saxon-HE-${SAXON_VERSION}.jar net.sf.saxon.Query -qs:"." -s:net/example/xsl/client.xsl -o:net/example/xsl/client.xsl && \
    npx xslt3 -t -xsl:net/example/xsl/client.xsl -export:net/example/xsl/client.xsl.sef.json -nogo -ns:##html5 -relocate:on && \
    rm Saxon-HE-${SAXON_VERSION}.jar && \
    setfacl -Rm user:ldh:rwx net/example/xsl



The Java layer of LinkedDataHub is a Maven project with a webapp layout. The codebase uses JAX-RS, specifically Jersey 3, as the HTTP/REST framework and uses Apache Jena for RDF I/O.

If you want to extend the Java codebase, for example to add a custom REST endpoint, you need to create a new Maven project with LinkedDataHub as dependency:


After adding the new endpoint, you'll also need to extend the LinkedDataHub's JAX-RS application (com.atomgraph.linkeddatahub.Application) and register your class there.

By convention, static files (e.g. stylesheets, images) are placed in the src/main/webapp/static/ folder in the codebase, which then becomes /usr/local/tomcat/webapps/ROOT/static/ within the webapp deployed in the Docker container, and is available as ${base}static/ over HTTP.

This means that if you want to deploy static files as part of your LinkedDataHub app, you will have to either mount them into the /usr/local/tomcat/webapps/ROOT/static/ folder in the container, or copy them into a custom Docker image to the same effect.

You can allow Java debugger access using configuration properties.


LinkedDataHub uses XSLT 3.0 for UI rendering both on the server- and on the client-side.

You can specify a custom server-side XSLT 3.0 stylesheet in the dataspace configuration.

You can reuse LinkedDataHub's stylesheets by importing them as explained in the change layout user guide.


The default server-side stylesheet layout.xsl and its imports can be found in the src/main/webapp/static/com/atomgraph/linkeddatahub/xsl/bootstrap/2.3.2 folder.


Client-side stylesheets are used to implement the interactive parts of the UI (event handling, AJAX calls etc.) using the IXSL extension provided by the SaxonJS library. This way the frontend is made completely declarative and does not require almost any Javascript code, with exceptions of 3rd party libraries such as Google Charts and OpenLayers.

Client-side stylesheets share common document-, resource-, and property-level templates with the server-side stylesheets. The client-side stylesheet may not contain any XML entity declarations (limitation of SaxonJS) and must be compiled into a SEF file before it can be run by the SaxonJS runtime. By default, the URL of the client-side SEF stylesheet can be specified as the $client-stylesheet param of the document-level server-side xhtml:Script template.


You can modify or extend the default RDF datasets used by LinkedDataHub. However, a better practice is to use the CLI scripts to create documents and to import CSV and RDF data.

See the LinkedDataHub app repository for more examples.