diff --git a/CMakeLists.txt b/CMakeLists.txt
index 24fafb8f6b951c56c500664c39f64011b597e054..8a733abdfff2a70241370c9f6cf8e190ab4ef589 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,15 +5,23 @@ list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake )
 
 find_package( PystencilsSfg REQUIRED )
 
-set( SfgConfigModule ${CMAKE_BINARY_DIR}/CodegenConfig.py )
+set( 
+    WALBERLA_CODEGEN_CONFIG_MODULE
+    ${CMAKE_BINARY_DIR}/CodegenConfig.py
+    CACHE
+    FILEPATH
+    "Path to waLBerla-wide codegen config module" 
+)
+mark_as_advanced( WALBERLA_CODEGEN_CONFIG_MODULE )
+
 configure_file(
     ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CodegenConfig.template.py
-    ${SfgConfigModule}
+    ${WALBERLA_CODEGEN_CONFIG_MODULE}
 )
 
-message( STATUS "Wrote project-wide code generator configuration to ${SfgConfigModule}" )
+message( STATUS "Wrote project-wide code generator configuration to ${WALBERLA_CODEGEN_CONFIG_MODULE}" )
 
-set( PystencilsSfg_CONFIG_MODULE ${SfgConfigModule} PARENT_SCOPE )
+include( CodegenFunctions )
 
 add_library( sfg_walberla INTERFACE )
 
diff --git a/cmake/CodegenFunctions.cmake b/cmake/CodegenFunctions.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..318dad835d95d23a005201f887bfd7a7c78e1db6
--- /dev/null
+++ b/cmake/CodegenFunctions.cmake
@@ -0,0 +1,21 @@
+#[[
+Register code generation scripts for a CMake target.
+
+Signature:
+
+```
+walberla_generate_sources( <target> 
+    SCRIPTS script1.py [script2.py ...]
+    [DEPENDS dependency1.py [dependency2.py...] ]
+    [FILE_EXTENSIONS <header-extension> <impl-extension>]
+    [OUTPUT_MODE <standalone|inline|header-only>]
+)
+```
+
+This is a wrapper around `pystencilssfg_generate_target_sources`
+without the `CONFIG_MODULE` parameter.
+See also https://pycodegen.pages.i10git.cs.fau.de/pystencils-sfg/usage/project_integration.html#add-generator-scripts
+#]]
+function(walberla_generate_sources TARGET)
+    pystencilssfg_generate_target_sources(${ARGV} CONFIG_MODULE $CACHE{WALBERLA_CODEGEN_CONFIG_MODULE})
+endfunction()
diff --git a/examples/GeneratorScriptBasics/BasicCodegen.py b/examples/GeneratorScriptBasics/BasicCodegen.py
index 61b2e312aeed674fa3961f1ac59b7a67b0ea6d76..3151d551cf0c539ddc00f539967d8e1d52848f22 100644
--- a/examples/GeneratorScriptBasics/BasicCodegen.py
+++ b/examples/GeneratorScriptBasics/BasicCodegen.py
@@ -1,7 +1,7 @@
 from pystencilssfg import SourceFileGenerator
-from sfg_walberla import WalberlaBuildConfig
 
 with SourceFileGenerator() as sfg:
-    build_config = WalberlaBuildConfig.from_sfg(sfg)
+    sfg.include("core/DataTypes.h")
+    sfg.namespace("gen")
+    sfg.code("constexpr walberla::uint_t MAGIC_NUMBER = 0xcafe;")
 
-    print(build_config)
diff --git a/examples/GeneratorScriptBasics/BasicCodegenApp.cpp b/examples/GeneratorScriptBasics/BasicCodegenApp.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0cb852b61fda67ad65a4ba18612acf40f23f7882
--- /dev/null
+++ b/examples/GeneratorScriptBasics/BasicCodegenApp.cpp
@@ -0,0 +1,6 @@
+#include "gen/Ex_GeneratorScriptBasics/BasicCodegen.hpp"
+#include <iostream>
+
+int main(void) {
+    std::cout << gen::MAGIC_NUMBER << std::endl;
+}
diff --git a/examples/GeneratorScriptBasics/CMakeLists.txt b/examples/GeneratorScriptBasics/CMakeLists.txt
index 118434c7bc3af7560b4de6d91ada4971d7c803d9..5804fe28101f15e23ead12756d362a476ff823c5 100644
--- a/examples/GeneratorScriptBasics/CMakeLists.txt
+++ b/examples/GeneratorScriptBasics/CMakeLists.txt
@@ -1,12 +1,6 @@
 add_executable( Ex_GeneratorScriptBasics )
-# target_sources( Ex_GeneratorScriptBasics PRIVATE Ex_GeneratorScriptBasics.cpp )
+target_sources( Ex_GeneratorScriptBasics PRIVATE BasicCodegenApp.cpp )
 
-pystencilssfg_generate_target_sources( Ex_GeneratorScriptBasics 
+walberla_generate_sources( Ex_GeneratorScriptBasics 
     SCRIPTS BasicCodegen.py
-)
-
-target_link_libraries(
-    Ex_GeneratorScriptBasics
-    PRIVATE 
-    core blockforest sfg_walberla 
-)
+)
\ No newline at end of file
diff --git a/examples/GeneratorScriptBasics/GeneratorScriptBasics.md b/examples/GeneratorScriptBasics/GeneratorScriptBasics.md
index 1dc4edeefdc6e4ad4247338e1dd24d3deb967b80..32b0680cb2f1c82e3b22b1b60e4b9da510ff2ffd 100644
--- a/examples/GeneratorScriptBasics/GeneratorScriptBasics.md
+++ b/examples/GeneratorScriptBasics/GeneratorScriptBasics.md
@@ -1,8 +1,14 @@
 # Getting Started with Generator Scripts
 
-This chapter aims to give an introduction on working with 
+This chapter aims to give an introduction on working with *generator scripts*,
+which are the driving force of the next-codegen system in waLBerla.
 
-## Files
+In the course of this guide, we will
+ - set up the basic structure of a generator script;
+ - register that script with CMake;
+ - and include the generated files into a simple *Hello World*-like application.
+
+:::{dropdown} Get The Files
 
 {download}`GeneratorScriptBasics.zip </zipped-examples/GeneratorScriptBasics.zip>`.
 
@@ -12,13 +18,73 @@ This example comprises the following files:
  - `BasicCodegen.py`: A sample code generation script;
  - `CMakeLists.txt`: The CMake build system configuration.
 
-## CMake Target Definition
+:::
+
+## Our First Generator Script
+
+Create and open the file `BasicCodegen.py` and populate it with the following basic code:
 
-:::{card} `CMakeLists.txt`
-::::{literalinclude} CMakeLists.txt
+```{literalinclude} BasicCodegen.py
+:caption: BasicCodegen.py
+```
+
+Let's take this apart.
+- In line 1, we import the `SourceFileGenerator`, which is the object responsible for running code generation
+  and interacting with the build system.
+  It is exposed by [pystencils-sfg][pystencils-sfg], a lower-level package that `sfg-walberla` relies on.
+- In line 3, we enter code generation mode by opening up a managed block controlled by the `SourceFileGenerator`.
+  It gives us the `sfg` object, which is our primary interaction point with the code generation engine.
+- In lines 4 to 6, we use the `sfg` object to do three things:
+    - Include a header file; this will cause the respective `#include` directive to be generated.
+    - Set the namespace; this will place all generated code into the `gen` namespace.
+    - Define a constant; this will print the definition verbatim into the output header file.
+
+To see the generator script in effect, we need to create a CMake target and a simple application we can include it into.
+Create both the `BasicCodegenApp.cpp` and `CMakeLists.txt` files, open up `CMakeLists.txt`, and add the following:
+
+:::{literalinclude} CMakeLists.txt
 :language: CMake
-::::
+:caption: CMakeLists.txt
+:emphasize-lines: 4-6
 :::
 
+At first, we create a new executable target called `Ex_GeneratorScriptBasics`
+and add the `BasicCodegen.cpp` source file to it.
+To us code generators, however, the second part is more interesting:
+we register our generator script `BasicCodegen.py` at the target using
+`walberla_generate_sources`.
+This will cause the build system to execute the generator script during build,
+compile its generated sources,
+and make its generated headers available to us.
+
+To observe this, add the following to your `BasicCodegenApp.cpp`:
+
+```{literalinclude} BasicCodegenApp.cpp
+:caption: BasicCodegenApp.cpp
+```
+
+Don't worry if your IDE tells you `BasicCodegen.hpp` does not exist yet;
+the file will be generated in a moment.
+Use CMake to build the application `Ex_GeneratorScriptBasics` and run it, and you should see it print `51966`
+to stdout.
+
+Let's take a look at what is happening during the build.
+Your CMake build output should contain a line somewhat like this:
+
+```
+Generating sfg_sources/gen/Ex_GeneratorScriptBasics/BasicCodegen.hpp, sfg_sources/gen/Ex_GeneratorScriptBasics/BasicCodegen.cpp
+```
+
+This indicates that the generator script was executed and produced exactly two files below the `sfg_sources` directory:
+- a header file `gen/Ex_GeneratorScriptBasics/BasicCodegen.hpp`, which is the one we included into our application, and
+- a source file ``gen/Ex_GeneratorScriptBasics/BasicCodegen.cpp`, which at this time is still empty
+  because we haven't yet defined any kernels or functions.
+
+The `walberla_generate_sources` CMake command made sure that the `sfg_sources` directory was placed in your
+target's include path, so you can include the generated files.
+
+That covers the basics of setting up and running a code generator script;
+you're all set now to generate and run your first numerical kernels.
 
-[sfg_add_gen_scripts]: https://pycodegen.pages.i10git.cs.fau.de/pystencils-sfg/usage/project_integration.html#add-generator-scripts "pystencils-sfg Documentation"
\ No newline at end of file
+[pystencils-sfg]: https://pycodegen.pages.i10git.cs.fau.de/pystencils-sfg/index.html
+[sfg_add_gen_scripts]: https://pycodegen.pages.i10git.cs.fau.de/pystencils-sfg/usage/project_integration.html#add-generator-scripts "pystencils-sfg Documentation"
diff --git a/examples/conf.py b/examples/conf.py
index ca204c777c94d36dfc0e19b74202b8c5cea70ba7..cfa54f38b4a54d40be07e51cb183f088bdf36c32 100644
--- a/examples/conf.py
+++ b/examples/conf.py
@@ -26,7 +26,8 @@ exclude_patterns = ["build"]
 myst_enable_extensions = [
     "colon_fence",
     "dollarmath",
-    "attrs_inline"
+    "attrs_inline",
+    "attrs_block",
 ]
 
 # -- Options for HTML output -------------------------------------------------