diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
new file mode 100644
index 0000000000000000000000000000000000000000..1347afbaaa2626ef6d797742b03adcbc9e25fb86
--- /dev/null
+++ b/.github/CONTRIBUTING.md
@@ -0,0 +1,31 @@
+# Contribution Guidelines
+
+We welcome contributions from everyone to this repository, and we thank you for dedicating
+your time to the improvement of this repository and for sharing your work with everyone in
+our community.
+
+## Issue Tracking
+
+Please report issues to the issue tracker here. Use the provided template to ensure we have
+a reproducible and actionable issue report.
+
+## Pull Requests
+
+Please use pull requests from branches within this repository or from branches on your own
+forks.
+* Consider submitting multiple pull requests frequently in order to keep the number of
+  changes limited and self-contained.
+* A number of mandatory tests will be run on each pull request. We cannot bypass these
+  tests, not even for core developers.
+* All pull requests, also those by core developers, are required to pass a review by at
+  least one (other) core developer.
+
+Please create a pull request (or an issue) as soon as you start working on a new feature or
+bug fix. You can mark the pull request as a "draft pull request" in those cases. This helps
+letting developers and other users know that someone is working on this feature and avoids
+duplicate work.
+
+## Coding Conventions
+
+* All code in this repository should compile without warnings (including unused variables).
+* All code in this repository must be formatted using the clang-format conventions.
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
new file mode 100644
index 0000000000000000000000000000000000000000..7f6a824083e4defe732be987a4cf2f122004e82d
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -0,0 +1,23 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+### Environment: (where does this bug occur, have you tried other environments)
+- Which branch (`main` for latest released):
+- Which revision (`HEAD` for the most recent):
+- Any specific OS or system where the issue occurs?
+- Any special versions of ROOT or Geant4?
+
+### Steps to reproduce: (give a step by step account of how to trigger the bug)
+1.
+2.
+
+### Expected Result: (what do you expect when you execute the steps above)
+
+
+### Actual Result: (what do you get when you execute the steps above)
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ea4644e401caa2543eca149b97edce133683cd5a
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,11 @@
+blank_issues_enabled: false
+contact_links:
+  - name: EIC Detector Collaboration Mattermost
+    url: https://eic.cloud.mattermost.com
+    about: Please ask and answer questions here.
+  - name: EIC Detector Collaboration Computing and Software Meetings
+    url: https://indico.bnl.gov/category/410
+    about: We hold weekly computing and software meetings.
+  - name: EIC Detector Collaboration Simulation, Production and QA Meetings
+    url: https://indico.bnl.gov/category/416
+    about: We hold weekly simulation, software, and QA meetings.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
new file mode 100644
index 0000000000000000000000000000000000000000..bbcbbe7d61558adde3cbfd0c7a63a67c27ed6d30
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -0,0 +1,20 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.
diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md
new file mode 100644
index 0000000000000000000000000000000000000000..1c49e40dd7ffd5ee246015dac76acfa2231d7b6e
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md
@@ -0,0 +1,23 @@
+---
+name: Pull request
+about: Create a pull request to merge bug fixes or new features
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+### What kind of change does this PR introduce?
+- [ ] Bug fix (issue #__)
+- [ ] New feature (issue #__)
+- [ ] Documentation update
+- [ ] Other: __
+
+### Please check if this PR fulfills the following:
+- [ ] Tests for the changes have been added
+- [ ] Documentation has been added / updated
+- [ ] Changes have been communicated to collaborators
+
+### Does this PR introduce breaking changes? What changes might users need to make to their code?
+
+### Does this PR change default behavior?
diff --git a/.github/workflows/linux-eic-shell.yml b/.github/workflows/linux-eic-shell.yml
new file mode 100644
index 0000000000000000000000000000000000000000..044091faa4723d0b3ace1fdbe4c1605d36d08c10
--- /dev/null
+++ b/.github/workflows/linux-eic-shell.yml
@@ -0,0 +1,18 @@
+name: linux-eic-shell
+
+on: [push, pull_request]
+
+jobs:
+  build-and-check-overlap:
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@v2
+    - uses: cvmfs-contrib/github-action-cvmfs@v2
+    - uses: eic/run-cvmfs-osg-eic-shell@main
+      with:
+        platform-release: "jug_xl:nightly"
+        run: |
+          cmake -B build -S . -DCMAKE_INSTALL_PREFIX=install
+          cmake --build build -- install
+          export LD_LIBRARY_PATH=${PWD}/install/lib:${LD_LIBRARY_PATH}
+          checkOverlaps -c install/share/ip6/eic_ip6.xml
diff --git a/.github/workflows/linux-lcg.yml b/.github/workflows/linux-lcg.yml
new file mode 100644
index 0000000000000000000000000000000000000000..73a8ccc9c1eb0807e1838f636211b74f6e899826
--- /dev/null
+++ b/.github/workflows/linux-lcg.yml
@@ -0,0 +1,42 @@
+name: linux-lcg
+
+on: [push, pull_request]
+
+jobs:
+  ubuntu-2004:
+    runs-on: ubuntu-20.04
+    strategy:
+      fail-fast: false
+      matrix:
+        LCG: ["LCG_101/x86_64-ubuntu2004-gcc9-opt",
+              "LCG_99/x86_64-ubuntu2004-gcc9-opt"]
+    steps:
+    - uses: actions/checkout@v2
+    - 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: |
+          cmake -B build -S .
+          cmake --build build -- install
+
+  ubuntu-2204:
+    runs-on: ubuntu-22.04
+    strategy:
+      fail-fast: false
+      matrix:
+        LCG: ["LCG_101/x86_64-ubuntu2004-gcc9-opt",
+              "LCG_99/x86_64-ubuntu2004-gcc9-opt"]
+    steps:
+    - uses: actions/checkout@v2
+    - 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: |
+          cmake -B build -S .
+          cmake --build build -- install
diff --git a/.github/workflows/macos-lcg.yml b/.github/workflows/macos-lcg.yml
new file mode 100644
index 0000000000000000000000000000000000000000..593c84513e57714d1816ccfc327bf36ec65d2301
--- /dev/null
+++ b/.github/workflows/macos-lcg.yml
@@ -0,0 +1,22 @@
+name: macos-lcg
+
+on: [push, pull_request]
+
+jobs:
+  macos-1015:
+    runs-on: macos-10.15
+    strategy:
+      fail-fast: false
+      matrix:
+        LCG: ["LCG_101/x86_64-mac1015-clang120-opt"]
+    steps:
+    - uses: actions/checkout@v2
+    - 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: |
+          cmake -B build -S .
+          cmake --build build -- install
diff --git a/src/B0Preshower_geo.cpp b/src/B0Preshower_geo.cpp
index 49a2657b6d428559b97a4343e4a1595951725a79..3b3ee6a092777b3485aa0bcc3dcdd20deaf42725 100644
--- a/src/B0Preshower_geo.cpp
+++ b/src/B0Preshower_geo.cpp
@@ -64,7 +64,7 @@ static Ref_t create_B0Preshower(Detector& description, xml_h e, SensitiveDetecto
     m_volume.setVisAttributes(description.visAttributes(x_mod.visStr()));
 
     Solid frame_s;
-    if (x_mod.hasChild("frame")) {
+    if (x_mod.hasChild(_U(frame))) {
       // build frame from trd (assumed to be smaller)
       xml_comp_t m_frame         = x_mod.child(_U(frame));
       xml_comp_t f_pos           = m_frame.child(_U(position));
diff --git a/src/B0Tracker_geo.cpp b/src/B0Tracker_geo.cpp
index ac62313e437c3553f51860ce4b786a91106e25a7..0cc558879f348d19456fddcae2dce7867a370a7a 100644
--- a/src/B0Tracker_geo.cpp
+++ b/src/B0Tracker_geo.cpp
@@ -74,7 +74,7 @@ static Ref_t create_B0Tracker(Detector& description, xml_h e, SensitiveDetector
     m_volume.setVisAttributes(description.visAttributes(x_mod.visStr()));
 
     Solid frame_s;
-    if (x_mod.hasChild("frame")) {
+    if (x_mod.hasChild(_U(frame))) {
       // build frame from trd (assumed to be smaller)
       xml_comp_t m_frame         = x_mod.child(_U(frame));
       xml_comp_t f_pos           = m_frame.child(_U(position));
diff --git a/src/CylindricalDipoleMagnet_geo.cpp b/src/CylindricalDipoleMagnet_geo.cpp
index f9a52eb4ce1b3027ffa17a6a0acf2fb5ae250705..35440e9d63b278b9cffe475ef0debd73f677165f 100644
--- a/src/CylindricalDipoleMagnet_geo.cpp
+++ b/src/CylindricalDipoleMagnet_geo.cpp
@@ -39,8 +39,8 @@ static Ref_t build_magnet(Detector& dtor, xml_h e, SensitiveDetector /* sens */)
 
   const string module_name = "Quad_magnet";
 
-  const string yoke_vis = dd4hep::getAttrOrDefault(x_det, _Unicode(vis), "GreenVis");
-  const string coil_vis = dd4hep::getAttrOrDefault(coil, _Unicode(vis), "RedVis");
+  const string yoke_vis = dd4hep::getAttrOrDefault<std::string>(x_det, _Unicode(vis), "GreenVis");
+  const string coil_vis = dd4hep::getAttrOrDefault<std::string>(coil, _Unicode(vis), "RedVis");
 
   sdet.setAttributes(dtor, assembly, x_det.regionStr(), x_det.limitsStr(), yoke_vis);
 
diff --git a/src/ForwardRomanPot_geo.cpp b/src/ForwardRomanPot_geo.cpp
index feffcd0975e7bb997e876151838142fd49f39c2d..66be89430904757421b70496dd2108c1888b3bca 100644
--- a/src/ForwardRomanPot_geo.cpp
+++ b/src/ForwardRomanPot_geo.cpp
@@ -60,7 +60,7 @@ static Ref_t create_detector(Detector& description, xml_h e, SensitiveDetector s
       c_vol.setVisAttributes(description.visAttributes(c.visStr()));
 
       Position c_position(0, 0.0, comp_z_pos + c_thick / 2.0);
-      if (c.hasChild("position")) {
+      if (c.hasChild(_U(position))) {
         xml_comp_t c_pos = c.child(_U(position));
         c_position       = Position(c_pos.x(), c_pos.y(), c_pos.z());
       }
@@ -97,7 +97,7 @@ static Ref_t create_detector(Detector& description, xml_h e, SensitiveDetector s
       double      dz         = getAttrOrDefault(x_array, _Unicode(dz), 0 * mm);
       double      arr_width  = getAttrOrDefault(x_array, _Unicode(width), 3.2 * cm);
       double      arr_height = getAttrOrDefault(x_array, _Unicode(height), 3.2 * cm);
-      std::string arr_module = getAttrOrDefault(x_array, _Unicode(module), "");
+      std::string arr_module = getAttrOrDefault<std::string>(x_array, _Unicode(module), "");
       // TODO: add check here
       auto        arr_vol  = modules[arr_module];
       Placements& sensVols = sensitives[arr_module];
@@ -156,7 +156,7 @@ static Ref_t create_detector(Detector& description, xml_h e, SensitiveDetector s
       xml_comp_t c_pos  = x_comp.position(false);
 
       // string     ma_name = x_comp.nameStr();
-      string comp_assembly = getAttrOrDefault(x_comp, _Unicode(assembly), "");
+      string comp_assembly = getAttrOrDefault<std::string>(x_comp, _Unicode(assembly), "");
 
       auto comp_vol = module_assemblies[comp_assembly];
       // auto de       = ;
diff --git a/src/OffMomentumTracker_geo.cpp b/src/OffMomentumTracker_geo.cpp
index 10f61ca817acced2504f9e71e8aa3107d0c34c29..2649c360427f51585e1f0aceccb2653f5759bf93 100644
--- a/src/OffMomentumTracker_geo.cpp
+++ b/src/OffMomentumTracker_geo.cpp
@@ -57,7 +57,7 @@ static Ref_t create_OffMomentumTracker(Detector& description, xml_h e, Sensitive
     xml_dim_t   support_pos(x_support.child(_U(position), false));
     xml_dim_t   support_rot(x_support.child(_U(rotation), false));
     Solid       support_solid;
-    if (x_support.hasChild("shape")) {
+    if (x_support.hasChild(_U(shape))) {
       xml_comp_t shape(x_support.child(_U(shape)));
       string     shape_type = shape.typeStr();
       support_solid         = xml::createShape(description, shape_type, shape);
@@ -102,7 +102,7 @@ static Ref_t create_OffMomentumTracker(Detector& description, xml_h e, Sensitive
     m_volume.setVisAttributes(description.visAttributes(x_mod.visStr()));
 
     // Solid  frame_s;
-    if (x_mod.hasChild("frame")) {
+    if (x_mod.hasChild(_U(frame))) {
       // todo
       // build frame from trd (assumed to be smaller)
       // xml_comp_t m_frame         = x_mod.child(_U(frame));
diff --git a/src/TaggerCalWSi_geo.cpp b/src/TaggerCalWSi_geo.cpp
index 3918836609c48c967cab096294ae7e09dfc1f0db..7ff9697cd1a67b9f37185f687728b252b54d395d 100644
--- a/src/TaggerCalWSi_geo.cpp
+++ b/src/TaggerCalWSi_geo.cpp
@@ -1,4 +1,3 @@
-
 #include "DD4hep/DetFactoryHelper.h"
 #include "DD4hep/OpticalSurfaces.h"
 #include "DD4hep/Printout.h"
@@ -64,7 +63,7 @@ static Ref_t createDetector(Detector& desc, xml_h e, SensitiveDetector sens)
   }
 
   // mother volume for calorimeter
-  std::string   mother_nam = dd4hep::getAttrOrDefault(x_det, _Unicode(place_into), "");
+  std::string   mother_nam = dd4hep::getAttrOrDefault<std::string>(x_det, _Unicode(place_into), "");
   VolumeManager man        = VolumeManager::getVolumeManager(desc);
   DetElement    mdet       = man.detector().child(mother_nam);
 
diff --git a/src/TaggerTracker_geo.cpp b/src/TaggerTracker_geo.cpp
index 1badea22ac80bd962aadbe7db3e97fcfbd667f67..44e11481c6f249daca1d8859b62dc2b116d7a9d9 100644
--- a/src/TaggerTracker_geo.cpp
+++ b/src/TaggerTracker_geo.cpp
@@ -39,8 +39,8 @@ static Ref_t createDetector(Detector& desc, xml_h e, SensitiveDetector sens)
   int N_layers = 0;
   for (xml_coll_t lay(x_det, _Unicode(trackLayer)); lay; ++lay, ++N_layers) {
 
-    string layerType      = dd4hep::getAttrOrDefault(lay, _Unicode(type), "timepix");
-    string layerVis       = dd4hep::getAttrOrDefault(lay, _Unicode(vis), "GreenVis");
+    string layerType      = dd4hep::getAttrOrDefault<std::string>(lay, _Unicode(type), "timepix");
+    string layerVis       = dd4hep::getAttrOrDefault<std::string>(lay, _Unicode(vis), "GreenVis");
     double layerZ         = dd4hep::getAttrOrDefault(lay, _Unicode(z), 0);
     double layerThickness = dd4hep::getAttrOrDefault(lay, _Unicode(sensor_thickness), 200 * um);
 
@@ -56,7 +56,7 @@ static Ref_t createDetector(Detector& desc, xml_h e, SensitiveDetector sens)
   }
 
   // mother volume for the tracker
-  std::string   mother_nam = dd4hep::getAttrOrDefault(x_det, _Unicode(place_into), "");
+  std::string   mother_nam = dd4hep::getAttrOrDefault<std::string>(x_det, _Unicode(place_into), "");
   VolumeManager man        = VolumeManager::getVolumeManager(desc);
   DetElement    mdet       = man.detector().child(mother_nam);
 
diff --git a/src/ZeroDegreeCalorimeterEcalWSciFi_geo.cpp b/src/ZeroDegreeCalorimeterEcalWSciFi_geo.cpp
index 4a848168cbe61c97bc34788d471e78eb28a9c974..ab67563d49075e5c3c0e8c74d54fd04bc8471096 100644
--- a/src/ZeroDegreeCalorimeterEcalWSciFi_geo.cpp
+++ b/src/ZeroDegreeCalorimeterEcalWSciFi_geo.cpp
@@ -47,7 +47,7 @@ static Ref_t create_detector(Detector& desc, xml::Handle_t handle, SensitiveDete
   modVol.setVisAttributes(desc.visAttributes(mod_x.visStr()));
   // modVol.setSensitiveDetector(sens);
 
-  if (mod_x.hasChild("fiber")) {
+  if (mod_x.hasChild(_Unicode(fiber))) {
     auto   fiber_x  = mod_x.child(_Unicode(fiber));
     auto   fr       = fiber_x.attr<double>(_Unicode(radius));
     auto   fsx      = fiber_x.attr<double>(_Unicode(spacex));
diff --git a/src/ZeroDegreeCalorimeterSampling_geo.cpp b/src/ZeroDegreeCalorimeterSampling_geo.cpp
index 5eff3a1bba1c8c82523320df0ce85bd3b7edc687..b9deb91cb012884b8c179126262728d5901f16dc 100644
--- a/src/ZeroDegreeCalorimeterSampling_geo.cpp
+++ b/src/ZeroDegreeCalorimeterSampling_geo.cpp
@@ -73,7 +73,7 @@ static Ref_t createDetector(Detector& desc, xml_h e, SensitiveDetector sens)
         ++slice_num;
       }
 
-      string layer_vis = dd4hep::getAttrOrDefault(x_layer, _Unicode(vis), "InvisibleWithDaughters");
+      string layer_vis = dd4hep::getAttrOrDefault<std::string>(x_layer, _Unicode(vis), "InvisibleWithDaughters");
       layer_vol.setAttributes(desc, x_layer.regionStr(), x_layer.limitsStr(), layer_vis);
       pv = envelopeVol.placeVolume(
           layer_vol,