diff --git a/.github/workflows/linux-lcg.yml b/.github/workflows/linux-lcg.yml
new file mode 100644
index 0000000000000000000000000000000000000000..74c87d3f122dbe4381a3022270530f78491409b1
--- /dev/null
+++ b/.github/workflows/linux-lcg.yml
@@ -0,0 +1,32 @@
+name: linux-lcg
+
+on:
+  push:
+    branches:
+      - master
+
+jobs:
+  build-lcg-docs:
+    runs-on: ubuntu-20.04
+    strategy:
+      fail-fast: false
+      matrix:
+        LCG: ["LCG_101/x86_64-ubuntu2004-gcc9-opt"]
+    steps:
+    - uses: actions/checkout@v3
+    - uses: cvmfs-contrib/github-action-cvmfs@v2
+      with:
+        cvmfs_repositories: 'sft.cern.ch,geant4.cern.ch'
+    - uses: aidasoft/run-lcg-view@v1
+      with:
+        release-platform: ${{ matrix.LCG }}
+        run: |
+          PREFIX=${PWD}/install
+          cmake -B build -S . -DCMAKE_INSTALL_PREFIX=${PREFIX}
+          cmake --build build -- install
+          cmake --build build -- docs
+    - uses: actions/upload-artifact@v3
+      with:
+        name: build-lcg-docs
+        path: build/docs/html/
+        if-no-files-found: error
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 48c3d8682252395ea4481c8fc8927c6007eaed90..7599a8260a24711b74c7afff800b2a8d95a14364 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -65,13 +65,23 @@ install(FILES
   "${PROJECT_BINARY_DIR}/libeicdDict_rdict.pcm"
   DESTINATION "${CMAKE_INSTALL_LIBDIR}" COMPONENT dev)
 
-add_custom_target( doc_doxygen #ALL 
-  COMMAND doxygen ${CMAKE_SOURCE_DIR}/docs/Doxyfile
-  WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
-  COMMENT "Generating API documentation with Doxygen"
-  VERBATIM )
-
-
+# -------------------------
+# install class documentation
+
+find_package(Doxygen COMPONENTS dot)
+if(DOXYGEN_FOUND)
+  configure_file(
+    ${CMAKE_SOURCE_DIR}/docs/Doxyfile.in
+    ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
+    @ONLY)
+  add_custom_target(docs ALL
+    COMMAND doxygen ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
+    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+    COMMENT "Generating API documentation with Doxygen"
+    VERBATIM)
+else()
+  message(STATUS "Doxygen not found; no documentation will be built.")
+endif()
 
 # -------------------------
 # install library config
diff --git a/docs/Doxyfile b/docs/Doxyfile.in
similarity index 99%
rename from docs/Doxyfile
rename to docs/Doxyfile.in
index b074d4cf068cffd3f6e5b712dfd81af1ac6c22e9..571d0aea07fe961a2192fcf23358f7c2b775d740 100644
--- a/docs/Doxyfile
+++ b/docs/Doxyfile.in
@@ -58,7 +58,7 @@ PROJECT_BRIEF          = "EIC data model"
 # entered, it will be relative to the location where doxygen was started. If
 # left blank the current directory will be used.
 
-OUTPUT_DIRECTORY       = docs
+OUTPUT_DIRECTORY       = @CMAKE_CURRENT_BINARY_DIR@/docs
 
 # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
 # directories (in 2 levels) under the output directory of each output format and
@@ -864,11 +864,10 @@ WARN_LOGFILE           =
 # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
 # Note: If this tag is empty the current directory is searched.
 
-INPUT                  = src \
-                         eicd \
-                         ../README.md \
-                         ../source \
-                         page.dox
+INPUT                  = README.md \
+                         @CMAKE_CURRENT_BINARY_DIR@/src \
+                         @CMAKE_CURRENT_BINARY_DIR@/eicd \
+                         @CMAKE_CURRENT_BINARY_DIR@/utils
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@@ -989,7 +988,7 @@ EXCLUDE_SYMBOLS        =
 # that contain example code fragments that are included (see the \include
 # command).
 
-EXAMPLE_PATH           = ../.
+EXAMPLE_PATH           = .
 
 # If the value of the EXAMPLE_PATH tag contains directories, you can use the
 # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
@@ -1065,7 +1064,7 @@ FILTER_SOURCE_PATTERNS =
 # (index.html). This can be useful if you have a project on for instance GitHub
 # and want to reuse the introduction page also for the doxygen output.
 
-USE_MDFILE_AS_MAINPAGE = ../README.md
+USE_MDFILE_AS_MAINPAGE = @CMAKE_CURRENT_SOURCE_DIR@/README.md
 
 #---------------------------------------------------------------------------
 # Configuration options related to source browsing
@@ -1252,7 +1251,7 @@ HTML_FILE_EXTENSION    = .html
 # of the possible markers and block names see the documentation.
 # This tag requires that the tag GENERATE_HTML is set to YES.
 
-HTML_HEADER            = doxygen-custom/header.html
+HTML_HEADER            = docs/doxygen-custom/header.html
 
 # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
 # generated HTML page. If the tag is left blank doxygen will generate a standard
@@ -1287,9 +1286,9 @@ HTML_STYLESHEET        =
 # list). For an example see the documentation.
 # This tag requires that the tag GENERATE_HTML is set to YES.
 
-HTML_EXTRA_STYLESHEET  = doxygen-awesome.css \
-                         doxygen-awesome-sidebar-only.css \
-                         doxygen-custom/custom.css
+HTML_EXTRA_STYLESHEET  = docs/doxygen-awesome.css \
+                         docs/doxygen-awesome-sidebar-only.css \
+                         docs/doxygen-custom/custom.css
 
 # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
 # other source files which should be copied to the HTML output directory. Note