diff --git a/CMakeLists.txt b/CMakeLists.txt
index f9e705726123ca02a17edeab80e8f9ebe52c6ecb..5a7a53f0ee7e5181f346853fdb8e0616a8bc4b54 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,19 +7,20 @@ list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake )
 
 include( PrepareSFG )
 
-add_library( sfg_walberla INTERFACE )
+add_library( walberla_codegen INTERFACE )
+add_library( walberla::codegen ALIAS walberla_codegen )
 
-target_sources( sfg_walberla
+target_sources( walberla_codegen
     INTERFACE
     include/sfg/SparseIteration.hpp
     include/sfg/GenericHbbBoundary.hpp
     include/sfg/IrregularFreeSlip.hpp
 )
 
-target_include_directories( sfg_walberla INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include )
+target_include_directories( walberla_codegen INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include )
 
 target_link_libraries(
-    sfg_walberla
+    walberla_codegen
     INTERFACE
-    core stencil domain_decomposition blockforest field
+    walberla::core walberla::stencil walberla::domain_decomposition walberla::blockforest walberla::field
 )
diff --git a/cmake/codegen-requirements.txt b/cmake/codegen-requirements.txt
index 70dd9bb4285bca1dea8f12f657581df8bb1c0379..d123706a2914a702ec849cef4e57ae8da97ea2ad 100644
--- a/cmake/codegen-requirements.txt
+++ b/cmake/codegen-requirements.txt
@@ -4,5 +4,5 @@ git+https://i10git.cs.fau.de/pycodegen/pystencils.git@v2.0-dev
 # lbmpy: feature branch for pystencils-2.0 compatibility
 git+https://i10git.cs.fau.de/pycodegen/lbmpy.git@fhennig/pystencils2.0-compat
 
-# pystencils-sfg: (development branch with updated CMake modules and cpptypes)
-git+https://i10git.cs.fau.de/pycodegen/pystencils-sfg.git@e467692fe48479ba2867d7a2e753e6be7dea4132
+# pystencils-sfg: latest supported revision
+git+https://i10git.cs.fau.de/pycodegen/pystencils-sfg.git@8949bedba3a8704dff520580202fc273fb0202de
diff --git a/src/sfg_walberla/api.py b/src/sfg_walberla/api.py
index 207c433230b72df39c1927664e7878c010cb896f..0120b23a0c5f4a0a4246ccafcc5d3ffa1d930572 100644
--- a/src/sfg_walberla/api.py
+++ b/src/sfg_walberla/api.py
@@ -12,10 +12,9 @@ from pystencils.types import (
     PsStructType,
 )
 from pystencilssfg.lang import (
-    IFieldExtraction,
     AugExpr,
-    SrcField,
-    SrcVector,
+    SupportsFieldExtraction,
+    SupportsVectorExtraction,
     Ref,
     ExprLike,
     cpptype,
@@ -38,7 +37,7 @@ class _PlainCppClass(AugExpr):
         super().__init__(dtype)
 
 
-class Vector2(SrcVector):
+class Vector2(AugExpr, SupportsVectorExtraction):
     _template = cpptype("walberla::Vector2< {element_type} >", "core/math/Vector2.h")
 
     def __init__(
@@ -48,14 +47,14 @@ class Vector2(SrcVector):
         dtype = self._template(element_type=element_type, const=const, ref=ref)
         super().__init__(dtype)
 
-    def extract_component(self, coordinate: int) -> AugExpr:
+    def _extract_component(self, coordinate: int) -> AugExpr:
         if coordinate > 1:
             raise ValueError(f"Cannot extract component {coordinate} from Vector2")
 
         return AugExpr(self._element_type).bind("{}[{}]", self, coordinate)
 
 
-class Vector3(SrcVector):
+class Vector3(AugExpr, SupportsVectorExtraction):
     _template = cpptype("walberla::Vector3< {element_type} >", "core/math/Vector3.h")
 
     def __init__(
@@ -65,7 +64,7 @@ class Vector3(SrcVector):
         dtype = self._template(element_type=element_type, const=const, ref=ref)
         super().__init__(dtype)
 
-    def extract_component(self, coordinate: int) -> AugExpr:
+    def _extract_component(self, coordinate: int) -> AugExpr:
         if coordinate > 2:
             raise ValueError(f"Cannot extract component {coordinate} from Vector3")
 
@@ -184,7 +183,7 @@ class StructuredBlockForest(AugExpr):
         return AugExpr(uint_t).bind("{}.getLevel({})", self, block)
 
 
-class GenericWalberlaField(SrcField):
+class GenericWalberlaField(AugExpr, SupportsFieldExtraction):
     """Common base class for GhostLayerField and GpuField defining their shared interface."""
 
     def __init__(
@@ -209,6 +208,8 @@ class GenericWalberlaField(SrcField):
 
         super().__init__(obj_type)
 
+        self._extraction = GhostLayerFieldExtraction(self, None)
+
     @property
     def _a(self) -> AugExpr:
         """Member access"""
@@ -221,10 +222,16 @@ class GenericWalberlaField(SrcField):
     def field_type(self) -> PsCustomType:
         return self._field_type
 
-    def get_extraction(self) -> IFieldExtraction:
-        return GhostLayerFieldExtraction(self, None)
+    def _extract_ptr(self) -> AugExpr:
+        return self._extraction._extract_ptr()
+
+    def _extract_size(self, coordinate: int) -> AugExpr | None:
+        return self._extraction._extract_size(coordinate)
 
-    def with_cell_interval(self, ci: CellInterval | None):
+    def _extract_stride(self, coordinate: int) -> AugExpr | None:
+        return self._extraction._extract_stride(coordinate)
+
+    def with_cell_interval(self, ci: CellInterval | None) -> GhostLayerFieldExtraction:
         return GhostLayerFieldExtraction(self, ci)
 
     def cloneUninitialized(self) -> AugExpr:
@@ -292,7 +299,7 @@ class GpuFieldPtr(GenericWalberlaField):
         super().__init__(element_type, field_type, ptr=True)
 
 
-class GhostLayerFieldExtraction(IFieldExtraction):
+class GhostLayerFieldExtraction(SupportsFieldExtraction):
     def __init__(
         self,
         field_ptr: AugExpr,
@@ -301,7 +308,7 @@ class GhostLayerFieldExtraction(IFieldExtraction):
         self._field_ptr = field_ptr
         self._ci = cell_interval
 
-    def ptr(self) -> AugExpr:
+    def _extract_ptr(self) -> AugExpr:
         data_at: AugExpr | str
         if self._ci is not None:
             ci = self._ci
@@ -311,7 +318,7 @@ class GhostLayerFieldExtraction(IFieldExtraction):
 
         return AugExpr.format("{}->dataAt({})", self._field_ptr, data_at)
 
-    def size(self, coordinate: int) -> AugExpr | None:
+    def _extract_size(self, coordinate: int) -> AugExpr | None:
         size_call = ["xSize()", "ySize()", "zSize()", "fSize()"][coordinate]
 
         if self._ci is not None and coordinate < 3:
@@ -319,7 +326,7 @@ class GhostLayerFieldExtraction(IFieldExtraction):
         else:
             return AugExpr.format("{}->{}", self._field_ptr, size_call)
 
-    def stride(self, coordinate: int) -> AugExpr | None:
+    def _extract_stride(self, coordinate: int) -> AugExpr | None:
         stride_call = ("xStride()", "yStride()", "zStride()", "fStride()")[coordinate]
         return AugExpr.format("{}->{}", self._field_ptr, stride_call)
 
@@ -352,7 +359,7 @@ class SparseIndexList(AugExpr):
         return BlockDataID().bind("{}.bufferId()", self)
 
 
-class IndexListBufferPtr(SrcField):
+class IndexListBufferPtr(AugExpr, SupportsFieldExtraction):
     _template = cpptype(
         "walberla::sfg::internal::IndexListBuffer< {IndexStruct} >",
         "sfg/SparseIteration.hpp",
@@ -374,26 +381,22 @@ class IndexListBufferPtr(SrcField):
     def vector(self) -> AugExpr:
         return AugExpr().format("{}->vector()", self)
 
-    def get_extraction(self) -> IFieldExtraction:
-        class IdxVectorExtraction(IFieldExtraction):
-            def ptr(_) -> AugExpr:
-                return self.pointerCpu()
-
-            def size(_, coordinate: int) -> AugExpr | None:
-                if coordinate == 0:
-                    return AugExpr.format("{}.size()", self.vector())
-                elif coordinate == 1:
-                    return AugExpr.format("1")
-                else:
-                    raise ValueError()
-
-            def stride(_, coordinate: int) -> AugExpr | None:
-                if coordinate <= 1:
-                    return AugExpr.format("1")
-                else:
-                    raise ValueError()
-
-        return IdxVectorExtraction()
+    def _extract_ptr(self) -> AugExpr:
+        return self.pointerCpu()
+
+    def _extract_size(self, coordinate: int) -> AugExpr | None:
+        if coordinate == 0:
+            return AugExpr.format("{}.size()", self.vector())
+        elif coordinate == 1:
+            return AugExpr.format("1")
+        else:
+            raise ValueError()
+
+    def _extract_stride(self, coordinate: int) -> AugExpr | None:
+        if coordinate <= 1:
+            return AugExpr.format("1")
+        else:
+            raise ValueError()
 
 
 CellIdx = PsStructType(
diff --git a/src/sfg_walberla/boundaries/freeslip.py b/src/sfg_walberla/boundaries/freeslip.py
index 863d49eb13c812721d96b5541d14654f7247888e..cfdc946bcb889212b36a500a8c46d071ffbeb5da 100644
--- a/src/sfg_walberla/boundaries/freeslip.py
+++ b/src/sfg_walberla/boundaries/freeslip.py
@@ -91,9 +91,11 @@ class FreeSlip(CustomGenerator):
             sfg.private(
                 sfg.method(
                     "irregularFromIndexVector",
-                    returns=sweep_type.get_dtype(),
-                    inline=True,
-                )(sfg.expr("return {};", sweep_type.ctor(**sweep_ctor_args))),
+                )
+                .returns(sweep_type.get_dtype())
+                .inline()(
+                    sfg.expr("return {};", sweep_type.ctor(**sweep_ctor_args))
+                ),
             ),
         )
 
diff --git a/src/sfg_walberla/boundaries/hbb.py b/src/sfg_walberla/boundaries/hbb.py
index d041f1b19a67df5da2107d4563c5b3b560b2d6f5..bce5c1d136129c8de6d400f5e88e9085c7638834 100644
--- a/src/sfg_walberla/boundaries/hbb.py
+++ b/src/sfg_walberla/boundaries/hbb.py
@@ -1,15 +1,12 @@
 """Code generation for half-way bounce-back LBM boundary conditions in waLBerla"""
 
-from pystencils import Field, FieldType, TypedSymbol, Target, AssignmentCollection, DynamicType
-
-from pystencils.types import PsStructType, create_type
+from pystencils import Field, FieldType, TypedSymbol, Target, AssignmentCollection
 
 from pystencilssfg import SfgComposer
 from pystencilssfg.composer.class_composer import SfgClassComposer
 from pystencilssfg.composer.custom import CustomGenerator
 from pystencilssfg.lang import AugExpr
 
-from lbmpy import LBStencil
 from lbmpy.methods import AbstractLbMethod
 from lbmpy.boundaries.boundaryconditions import LbBoundary
 from lbmpy.advanced_streaming.indexing import Timestep
diff --git a/src/sfg_walberla/reflection.py b/src/sfg_walberla/reflection.py
index 13e422d94cf2329d339a23077a51a13553928652..1b8d2021d8381bf8d5cf8a8430f8e2d33d177779 100644
--- a/src/sfg_walberla/reflection.py
+++ b/src/sfg_walberla/reflection.py
@@ -5,14 +5,9 @@ from pystencilssfg.ir import SfgClass
 
 class GeneratedClassWrapperBase(CppClass):
     _class: SfgClass
-    _namespace: str | None
 
     def __init_subclass__(cls) -> None:
-        typename = (
-            f"{cls._namespace}::{cls._class.class_name}"
-            if cls._namespace is not None
-            else cls._class.class_name
-        )
+        typename = cls._class.fqname
         cls.template = cpptype(typename)
 
     def ctor(self, **kwargs) -> AugExpr:
@@ -22,7 +17,7 @@ class GeneratedClassWrapperBase(CppClass):
                 break
         else:
             raise Exception(
-                f"No constructor of class {self._class.class_name} matches the argument names {kwargs.keys()}"
+                f"No constructor of class {self._class.fqname} matches the argument names {kwargs.keys()}"
             )
 
         ctor_args = [kwargs[name] for name in ctor_argnames]
diff --git a/src/sfg_walberla/sweep.py b/src/sfg_walberla/sweep.py
index a79d133f4381deea94d06e96ff57c33531e73e26..07d037d7708a7ea94a6b520f02eb6a77a037b329 100644
--- a/src/sfg_walberla/sweep.py
+++ b/src/sfg_walberla/sweep.py
@@ -28,10 +28,9 @@ from pystencilssfg.lang import (
     SfgVar,
     AugExpr,
     Ref,
-    SrcVector,
     strip_ptr_ref,
+    SupportsVectorExtraction,
 )
-from pystencilssfg.lang.types import CppTypeFactory, cpptype
 from .reflection import GeneratedClassWrapperBase
 from .api import (
     StructuredBlockForest,
@@ -74,22 +73,19 @@ class SweepClassProperties:
 
             if self.getter:
                 methods.append(
-                    sfg.method(
-                        f"{self.name}",
-                        returns=Ref(constify(self.dtype)),
-                        const=True,
-                        inline=True,
-                    )(f"return {self.name}_;")
+                    sfg.method(f"{self.name}")
+                    .returns(Ref(constify(self.dtype)))
+                    .const()
+                    .inline()(f"return {self.name}_;")
                 )
 
             if self.setter:
                 methods.append(
-                    sfg.method(
-                        f"{self.name}",
-                        returns=Ref(self.dtype),
-                        const=False,
-                        inline=True,
-                    )(f"return {self.name}_;")
+                    sfg.method(f"{self.name}")
+                    .returns(Ref(self.dtype))
+                    .inline()(
+                        f"return {self.name}_;"
+                    )
                 )
 
             return methods
@@ -325,11 +321,9 @@ class ShadowFieldCache:
             cache_ptrs.append(sfg.var(cache_ptr_name, unique_ptr_type))
 
             getters.append(
-                sfg.method(
-                    self._getter(orig_name),
-                    returns=orig.wlb_field_ptr.get_dtype(),
-                    inline=True,
-                )(
+                sfg.method(self._getter(orig_name))
+                .returns(orig.wlb_field_ptr.get_dtype())
+                .inline()(
                     sfg.branch(f"{cache_ptr_name} == nullptr")(
                         AugExpr.format(
                             "{}.reset({});",
@@ -350,7 +344,9 @@ class ShadowFieldCache:
         return f"shadow_{str(orig)}_"
 
 
-def combine_vectors(scalars: set[SfgVar]) -> dict[SrcVector, tuple[SfgVar, ...]]:
+def combine_vectors(
+    scalars: set[SfgVar],
+) -> dict[SupportsVectorExtraction, tuple[SfgVar, ...]]:
     """Attempt to combine vector component symbols into vectors.
 
     This function modifies the `scalars` parameter in-place by removing grouped scalar
@@ -367,7 +363,7 @@ def combine_vectors(scalars: set[SfgVar]) -> dict[SrcVector, tuple[SfgVar, ...]]
         except ValueError:
             pass
 
-    all_vectors: dict[SrcVector, tuple[SfgVar, ...]] = dict()
+    all_vectors: dict[SupportsVectorExtraction, tuple[SfgVar, ...]] = dict()
 
     for name, entries in potential_vectors.items():
         entries = sorted(entries, key=lambda t: t[0])
@@ -618,12 +614,13 @@ class Sweep(CustomGenerator):
             *shadows_cache.render(sfg),
         )
 
-        gen_class = sfg.context.get_class(self._name)
+        gen_class = sfg._cursor.get_entity(self._name)
         assert gen_class is not None
+        from pystencilssfg.ir.entities import SfgClass
+        assert isinstance(gen_class, SfgClass)
 
         class GenClassWrapper(GeneratedClassWrapperBase):
             _class = gen_class
-            _namespace = sfg.context.fully_qualified_namespace
 
         self._generated_class = GenClassWrapper
 
diff --git a/tests/FreeSlip/CMakeLists.txt b/tests/FreeSlip/CMakeLists.txt
index e47cae2e1bef502e62a8b64dd2dea7f9fa396151..8401480e24c54fcabb7a0ddca0762b32c56a74fc 100644
--- a/tests/FreeSlip/CMakeLists.txt
+++ b/tests/FreeSlip/CMakeLists.txt
@@ -1,6 +1,6 @@
 add_executable( TestIrregularFreeSlip TestIrregularFreeSlip.cpp )
 walberla_generate_sources( TestIrregularFreeSlip SCRIPTS IrregularFreeSlip.py )
-target_link_libraries( TestIrregularFreeSlip core blockforest field geometry sfg_walberla )
+target_link_libraries( TestIrregularFreeSlip PRIVATE walberla::core walberla::blockforest walberla::field walberla::geometry walberla::codegen )
 add_test( NAME TestIrregularFreeSlip COMMAND TestIrregularFreeSlip )
 
 add_dependencies( SfgTests TestIrregularFreeSlip )
diff --git a/user_manual/examples/ForceDrivenChannel/CMakeLists.txt b/user_manual/examples/ForceDrivenChannel/CMakeLists.txt
index 3e21d3e157882b198cb7099828e15beade497ac6..dc8b9295f23c3c71d92a6d60bf6c30424d08ba31 100644
--- a/user_manual/examples/ForceDrivenChannel/CMakeLists.txt
+++ b/user_manual/examples/ForceDrivenChannel/CMakeLists.txt
@@ -10,5 +10,5 @@ walberla_generate_sources( Ex_ForceDrivenChannel
 target_link_libraries(
     Ex_ForceDrivenChannel
     PRIVATE 
-    core stencil blockforest geometry vtk sfg_walberla 
+    walberla::core walberla::stencil walberla::blockforest walberla::geometry walberla::vtk walberla::codegen 
 )
diff --git a/user_manual/examples/FreeSlipBubble/CMakeLists.txt b/user_manual/examples/FreeSlipBubble/CMakeLists.txt
index cd3e7af346973a31ce122c55531821489e74ce14..a47e511dc3dfcd129c09b81c7f1322e0c3e54221 100644
--- a/user_manual/examples/FreeSlipBubble/CMakeLists.txt
+++ b/user_manual/examples/FreeSlipBubble/CMakeLists.txt
@@ -3,4 +3,4 @@ walberla_link_files_to_builddir( *.prm )
 add_executable( FreeSlipBubble FreeSlipBubble.cpp )
 
 walberla_generate_sources( FreeSlipBubble SCRIPTS LbmAlgorithms.py )
-target_link_libraries( FreeSlipBubble core blockforest field geometry stencil sfg_walberla )
+target_link_libraries( FreeSlipBubble walberla::core walberla::blockforest walberla::field walberla::geometry walberla::stencil walberla::codegen )
diff --git a/user_manual/examples/SparseSpiral/CMakeLists.txt b/user_manual/examples/SparseSpiral/CMakeLists.txt
index 6ec9191dc263b3eee1015fa00433cbc1987a71a1..d973f8a173863aa58081f49ac47ab0c23e0c0866 100644
--- a/user_manual/examples/SparseSpiral/CMakeLists.txt
+++ b/user_manual/examples/SparseSpiral/CMakeLists.txt
@@ -1,5 +1,5 @@
 
 add_executable( SparseSpiral SparseSpiral.cpp )
 walberla_generate_sources( SparseSpiral SCRIPTS SpiralSweep.py )
-target_link_libraries( SparseSpiral PRIVATE core blockforest field vtk sfg_walberla )
+target_link_libraries( SparseSpiral PRIVATE walberla::core walberla::blockforest walberla::field walberla::vtk walberla::codegen )