diff --git a/ProcessLib/SourceTerms/SourceTermBuilder.cpp b/ProcessLib/SourceTerms/SourceTermBuilder.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6a9340858c0d2843e4fe0885790eaf4d92f74917
--- /dev/null
+++ b/ProcessLib/SourceTerms/SourceTermBuilder.cpp
@@ -0,0 +1,98 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2017, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#include "SourceTermBuilder.h"
+#include "SourceTermConfig.h"
+#include "CreateNodalSourceTerm.h"
+#include "NodalSourceTerm.h"
+#include "MeshGeoToolsLib/BoundaryElementsSearcher.h"
+#include "MeshGeoToolsLib/CreateSearchLength.h"
+#include "MeshGeoToolsLib/MeshNodeSearcher.h"
+#include "MeshGeoToolsLib/SearchLength.h"
+
+namespace ProcessLib
+{
+std::unique_ptr<NodalSourceTerm> SourceTermBuilder::createSourceTerm(
+    const SourceTermConfig& config,
+    const NumLib::LocalToGlobalIndexMap& dof_table, const MeshLib::Mesh& mesh,
+    const int variable_id, const unsigned integration_order,
+    const unsigned shapefunction_order)
+{
+    //! \ogs_file_param{prj__process_variables__process_variable__source_terms__source_term__type}
+    auto const type = config.config.peekConfigParameter<std::string>("type");
+
+    if (type == "Nodal")
+    {
+        return createNodalSourceTerm(config, dof_table, mesh, variable_id,
+                                     integration_order, shapefunction_order);
+    }
+
+    OGS_FATAL("Unknown source term type: `%s'.", type.c_str());
+}
+
+std::unique_ptr<NodalSourceTerm> SourceTermBuilder::createNodalSourceTerm(
+    const SourceTermConfig& config,
+    const NumLib::LocalToGlobalIndexMap& dof_table, const MeshLib::Mesh& mesh,
+    const int variable_id, const unsigned /*integration_order*/,
+    const unsigned /*shapefunction_order*/)
+{
+    std::unique_ptr<MeshGeoToolsLib::SearchLength> search_length_algorithm =
+        MeshGeoToolsLib::createSearchLengthAlgorithm(config.config, mesh);
+
+    MeshGeoToolsLib::MeshNodeSearcher const& mesh_node_searcher =
+        MeshGeoToolsLib::MeshNodeSearcher::getMeshNodeSearcher(
+            mesh, std::move(search_length_algorithm));
+
+    // Find nodes' ids on the given mesh on which this source term is defined.
+    std::vector<std::size_t> ids =
+        mesh_node_searcher.getMeshNodeIDs(config.geometry);
+
+    // Filter out ids, which are not part of mesh subsets corresponding to
+    // the variable_id and component_id.
+
+    // Sorted ids of all mesh_subsets.
+    std::vector<std::size_t> sorted_nodes_ids;
+
+    auto const& mesh_subsets =
+        dof_table.getMeshSubsets(variable_id, *config.component_id);
+    for (auto const& mesh_subset : mesh_subsets)
+    {
+        auto const& nodes = mesh_subset->getNodes();
+        sorted_nodes_ids.reserve(sorted_nodes_ids.size() + nodes.size());
+        std::transform(std::begin(nodes), std::end(nodes),
+                       std::back_inserter(sorted_nodes_ids),
+                       [](MeshLib::Node* const n) { return n->getID(); });
+    }
+    std::sort(std::begin(sorted_nodes_ids), std::end(sorted_nodes_ids));
+
+    auto ids_new_end_iterator = std::end(ids);
+    ids_new_end_iterator = std::remove_if(
+        std::begin(ids), ids_new_end_iterator,
+        [&sorted_nodes_ids](std::size_t const node_id) {
+            return !std::binary_search(std::begin(sorted_nodes_ids),
+                                       std::end(sorted_nodes_ids), node_id);
+        });
+    ids.erase(ids_new_end_iterator, std::end(ids));
+
+    DBUG(
+        "Found %d nodes for nodal source term for the variable %d and "
+        "component %d",
+        ids.size(), variable_id, *config.component_id);
+
+    if (ids.size() != 1)
+        OGS_FATAL(
+            "Found %d nodes for nodal source term, but exactly one node is "
+            "required.");
+
+    return ProcessLib::createNodalSourceTerm(
+        config.config, dof_table, mesh.getID(), ids[0], variable_id,
+        *config.component_id);
+}
+
+}  // ProcessLib
diff --git a/ProcessLib/SourceTerms/SourceTermBuilder.h b/ProcessLib/SourceTerms/SourceTermBuilder.h
new file mode 100644
index 0000000000000000000000000000000000000000..dbc0981f8f160af066cc662ec92fd6d92b324804
--- /dev/null
+++ b/ProcessLib/SourceTerms/SourceTermBuilder.h
@@ -0,0 +1,60 @@
+/**
+ * \copyright
+ * Copyright (c) 2012-2017, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ */
+
+#pragma once
+
+#include "NodalSourceTerm.h"
+
+namespace GeoLib
+{
+class GeoObject;
+}
+
+namespace MeshLib
+{
+class Element;
+class Mesh;
+}
+
+namespace MeshGeoToolsLib
+{
+class BoundaryElementsSearcher;
+}
+
+namespace NumLib
+{
+class LocalToGlobalIndexMap;
+template <typename>
+struct IndexValueVector;
+}
+
+namespace ProcessLib
+{
+struct SourceTermConfig;
+
+class SourceTermBuilder
+{
+public:
+    virtual ~SourceTermBuilder() = default;
+
+    virtual std::unique_ptr<NodalSourceTerm> createSourceTerm(
+        const SourceTermConfig& config,
+        const NumLib::LocalToGlobalIndexMap& dof_table,
+        const MeshLib::Mesh& mesh, const int variable_id,
+        const unsigned integration_order, const unsigned shapefunction_order);
+
+protected:
+    virtual std::unique_ptr<NodalSourceTerm> createNodalSourceTerm(
+        const SourceTermConfig& config,
+        const NumLib::LocalToGlobalIndexMap& dof_table,
+        const MeshLib::Mesh& mesh, const int variable_id,
+        const unsigned integration_order, const unsigned shapefunction_order);
+};
+
+}  // ProcessLib