clangd doesn't consider .inl a valid C++ source (https://github.com/clangd/clangd/issues/16#issuecomment-512942589) this pull request adds support for that.
Until the export keyword is supported by compilers mentioned https://stackoverflow.com/questions/5416872/using-export-keyword-with-templates a common way of keeping header files cleaner is to move template definitions into .inl files. This seems to be a common practice. Some evidence of it being commonly used for this purpose.
https://www.randygaul.net/2015/01/31/c-keyword-inline-and-inl-files/
https://drake.mit.edu/cxx_inl.html
https://www.codeproject.com/Articles/48575/How-to-define-a-template-class-in-a-h-file-and-imp
https://stackoverflow.com/questions/31949731/very-confused-on-template-inl-file
even brdf-loader https://github.com/rgl-epfl/brdf-loader
Some other ways of separating definitions is https://github.com/RobotLocomotion/drake/issues/3141 where they say you should use .inl or .impl or -inl.h or -impl.h and this might be ok but then things like projectile can't find it because that only works with extensions.
One caveat of this is, the above methods of using .inl files means its not a complete translation unit so clangd still can't fully compile it so one has to add #include "header.hpp" at the top of .inl files to make it work but thats not a big deal.