diff --git a/config/Sources.cmake b/config/Sources.cmake
index 9a9f55747194ab9972254d5bf57ac11735607b06..27567beb5a09a5ba92698bcbf96d34193f56bb43 100644
--- a/config/Sources.cmake
+++ b/config/Sources.cmake
@@ -6,4 +6,6 @@ set(vkcv_sources
 		${vkcv_source}/vkcv/Window.cpp
 		${vkcv_source}/vkcv/CoreManager.hpp
 		${vkcv_source}/vkcv/CoreManager.cpp
+		${vkcv_source}/vkcv/ShaderProgram.hpp
+		${vkcv_source}/vkcv/ShaderProgram.cpp
 )
diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp
index cc592f468e0c3e95d64a1558404873c4ca19f8b9..6eadd66f03ad847a81555907082f91ca33fd3370 100644
--- a/projects/first_triangle/src/main.cpp
+++ b/projects/first_triangle/src/main.cpp
@@ -32,6 +32,10 @@ int main(int argc, const char** argv) {
 		default: std::cout << "Unknown GPU vendor?! Either you're on an exotic system or your driver is broken..." << std::endl;
 	}
 
+	vkcv::ShaderProgram shaderProgram = vkcv::ShaderProgram::create(context);
+	shaderProgram.addShader(VK_SHADER_STAGE_VERTEX_BIT, "../../../../../shaders/vert.spv");
+	shaderProgram.addShader(VK_SHADER_STAGE_FRAGMENT_BIT, "../../../../../shaders/frag.spv");
+
 	while (window.isWindowOpen()) {
 		window.pollEvents();
 	}
diff --git a/shaders/compile.bat b/shaders/compile.bat
new file mode 100644
index 0000000000000000000000000000000000000000..6f8f661d4c2600edfee3bd90198fe32472dd4141
--- /dev/null
+++ b/shaders/compile.bat
@@ -0,0 +1,3 @@
+C:\VulkanSDK\1.2.170.0\Bin32\glslc.exe shader.vert -o vert.spv
+C:\VulkanSDK\1.2.170.0\Bin32\glslc.exe shader.frag -o frag.spv
+pause
\ No newline at end of file
diff --git a/shaders/frag.spv b/shaders/frag.spv
new file mode 100644
index 0000000000000000000000000000000000000000..cb13e606fc0041e24ff6a63c0ec7dcca466732aa
Binary files /dev/null and b/shaders/frag.spv differ
diff --git a/shaders/shader.frag b/shaders/shader.frag
new file mode 100644
index 0000000000000000000000000000000000000000..3363876e688e04c0941066b5549ae4fd9b3f507a
--- /dev/null
+++ b/shaders/shader.frag
@@ -0,0 +1,10 @@
+#version 450
+#extension GL_ARB_separate_shader_objects : enable
+
+layout(location = 0) in vec3 fragColor;
+
+layout(location = 0) out vec4 outColor;
+
+void main()	{
+	outColor = vec4(fragColor, 1.0);
+}
\ No newline at end of file
diff --git a/shaders/shader.vert b/shaders/shader.vert
new file mode 100644
index 0000000000000000000000000000000000000000..9461e8f207aa283c258adcaff6359655fd62e9bb
--- /dev/null
+++ b/shaders/shader.vert
@@ -0,0 +1,12 @@
+#version 450
+#extension GL_ARB_separate_shader_objects : enable
+
+layout(location = 0) in vec2 inPosition;
+layout(location = 1) in vec3 inColor;
+
+layout(location = 0) out vec3 fragColor;
+
+void main()	{
+	gl_Position = vec4(inPosition, 0.0, 1.0);
+	fragColor = inColor;
+}
\ No newline at end of file
diff --git a/shaders/vert.spv b/shaders/vert.spv
new file mode 100644
index 0000000000000000000000000000000000000000..4e979164bba0448a8d9b7f58356c924163bd6df4
Binary files /dev/null and b/shaders/vert.spv differ
diff --git a/src/vkcv/ShaderProgram.cpp b/src/vkcv/ShaderProgram.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5bf995134d9a6af3002a92cbd158eb08862303f0
--- /dev/null
+++ b/src/vkcv/ShaderProgram.cpp
@@ -0,0 +1,104 @@
+/**
+ * @authors Simeon Hermann
+ * @file src/vkcv/ShaderProgram.cpp
+ * @brief ShaderProgram class to handle and prepare the shader stages for a graphics pipeline
+ */
+
+#include "ShaderProgram.hpp"
+#include <fstream>
+#include <iostream>
+
+
+
+std::vector<const char*> validationLayers = {
+	"VK_LAYER_KHRONOS_validation"
+};
+
+
+namespace vkcv {
+
+	ShaderProgram::ShaderProgram(vkcv::Context& context)
+		: m_context(context) 
+	{}
+
+	std::vector<char> ShaderProgram::readFile(const std::string& filepath) {
+		std::ifstream file(filepath, std::ios::ate | std::ios::binary);
+		if (!file.is_open()) {
+			throw std::runtime_error("The file could not be opened.");
+		}
+		size_t fileSize = (size_t)file.tellg();
+		std::vector<char> buffer(fileSize);
+		file.seekg(0);
+		file.read(buffer.data(), fileSize);
+		return buffer;
+	}
+
+	VkShaderModule ShaderProgram::createShaderModule(const std::vector<char>& shaderCode) {
+		VkShaderModuleCreateInfo createInfo{};
+		createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+		createInfo.codeSize = shaderCode.size();
+		createInfo.pCode = reinterpret_cast<const uint32_t*>(shaderCode.data());
+
+		VkShaderModule shaderModule;
+		if (vkCreateShaderModule(m_context.getDevice(), &createInfo, nullptr, &shaderModule) != VK_SUCCESS) {
+			throw std::runtime_error("Failed to create shader module!");
+		}
+		return shaderModule;
+	}
+
+	VkPipelineShaderStageCreateInfo ShaderProgram::createShaderStage(VkShaderModule& shaderModule, VkShaderStageFlagBits shaderStage) {
+		VkPipelineShaderStageCreateInfo shaderStageInfo{};
+		shaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+		shaderStageInfo.stage = shaderStage;
+		shaderStageInfo.module = shaderModule;
+		shaderStageInfo.pName = "main";
+		return shaderStageInfo;
+	}
+	
+	ShaderProgram::~ShaderProgram() {
+	}
+
+	ShaderProgram ShaderProgram::create(vkcv::Context& context) {
+		return ShaderProgram(context);
+	}
+
+	void ShaderProgram::addShader(VkShaderStageFlagBits shaderStage, const std::string& filepath) {
+		if (containsShaderStage(shaderStage)) {
+			throw std::runtime_error("Shader program already contains this particular shader stage.");
+		}
+		else {
+			auto shaderCode = readFile(filepath);
+			VkShaderModule shaderModule = createShaderModule(shaderCode);
+			VkPipelineShaderStageCreateInfo shaderInfo = createShaderStage(shaderModule, shaderStage);
+			m_shaderStagesList.push_back(shaderInfo);
+			vkDestroyShaderModule(m_context.getDevice(), shaderModule, nullptr);
+		}
+	}
+
+	bool ShaderProgram::containsShaderStage(VkShaderStageFlagBits shaderStage) {
+		for (int i = 0; i < m_shaderStagesList.size(); i++) {
+			if (m_shaderStagesList[i].stage == shaderStage) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	bool ShaderProgram::deleteShaderStage(VkShaderStageFlagBits shaderStage) {
+		for (int i = 0; i < m_shaderStagesList.size() - 1; i++) {
+			if (m_shaderStagesList[i].stage == shaderStage) {
+				m_shaderStagesList.erase(m_shaderStagesList.begin() + i);
+				return true;
+			}
+		}
+		return false;
+	}
+
+	std::vector<VkPipelineShaderStageCreateInfo> ShaderProgram::getShaderStages() {
+		return m_shaderStagesList;
+	}
+
+	int ShaderProgram::getShaderStagesCount() {
+		return m_shaderStagesList.size();
+	}
+}
diff --git a/src/vkcv/ShaderProgram.hpp b/src/vkcv/ShaderProgram.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..62c173bdaa542df90fd6664fe617dba9043ce036
--- /dev/null
+++ b/src/vkcv/ShaderProgram.hpp
@@ -0,0 +1,107 @@
+#pragma once
+/**
+ * @authors Simeon Hermann
+ * @file src/vkcv/ShaderProgram.hpp
+ * @brief ShaderProgram class to handle and prepare the shader stages for a graphics pipeline
+ */
+
+#define GLFW_INCLUDE_VULKAN
+#include <vector>
+#include <map>
+#include <vulkan/vulkan.hpp>
+#include "Context.hpp"
+
+namespace vkcv {
+
+	class ShaderProgram final {
+	private:
+
+		vkcv::Context& m_context;
+		std::vector<VkPipelineShaderStageCreateInfo> m_shaderStagesList;
+		/**
+		* Constructor of ShaderProgram requires a context for the logical device. 
+		* @param context of the app
+		*/
+		ShaderProgram(vkcv::Context& context);
+		
+		/**
+		* Reads the file of a given shader code. 
+		* Only used within the class. 
+		* @param[in] relative path to the shader code 
+		* @return vector of chars as a buffer for the code 
+		*/
+		std::vector<char> readFile(const std::string& filepath);
+
+		/**
+		* Creates a shader module that encapsulates the read shader code. 
+		* Only used within the class. 
+		* Shader modules are destroyed after respective shader stages are created. 
+		* @param[in] a vector of chars as a buffer for the code 
+		* @return shader module 
+		*/
+		VkShaderModule createShaderModule(const std::vector<char>& shaderCode);
+
+		/**
+		* Creates a shader stage (info struct) for the to be added shader. 
+		* Only used within the class. 
+		* @param[in] Shader module that encapsulates the shader code 
+		* @param[in] flag that signals the respective shaderStage 
+		* @return pipeline shader stage info struct 
+		*/ 
+		VkPipelineShaderStageCreateInfo createShaderStage(VkShaderModule& shaderModule, VkShaderStageFlagBits shaderStage);
+
+
+	public:
+
+		/**
+		* destructor of ShaderProgram, does nothing so far
+		*/
+		~ShaderProgram();
+
+		/**
+		* Creates a shader program.
+		* So far it only calls the constructor.
+		* @param[in] context of the app
+		*/
+		static ShaderProgram create(vkcv::Context& context);
+
+		/**
+		* Adds a shader into the shader program.
+		* The shader is only added if the shader program does not contain the particular shader stage already.
+		* Contains: (1) reading of the code, (2) creation of a shader module, (3) creation of a shader stage, (4) adding to the shader stage list, (5) destroying of the shader module
+		* @param[in] flag that signals the respective shaderStage (e.g. VK_SHADER_STAGE_VERTEX_BIT)
+		* @param[in] relative path to the shader code (e.g. "../../../../../shaders/vert.spv")
+		*/
+		void addShader(VkShaderStageFlagBits shaderStage, const std::string& filepath);
+
+		/**
+		* Tests if the shader program contains a certain shader stage.
+		* @param[in] flag that signals the respective shader stage (e.g. VK_SHADER_STAGE_VERTEX_BIT)
+		* @return boolean that is true if the shader program contains the shader stage
+		*/
+		bool containsShaderStage(VkShaderStageFlagBits shaderStage);
+
+		/**
+		* Deletes the given shader stage in the shader program.
+		* @param[in] flag that signals the respective shader stage (e.g. VK_SHADER_STAGE_VERTEX_BIT)
+		* @return boolean that is false if the shader stage was not found in the shader program
+		*/
+		bool deleteShaderStage(VkShaderStageFlagBits shaderStage);
+
+		/**
+		* Returns a list with all the shader stages in the shader program.
+		* Needed for the transfer to the pipeline.
+		* @return vector list with all shader stage info structs
+		*/
+		std::vector<VkPipelineShaderStageCreateInfo> getShaderStages();
+
+		/**
+		* Returns the number of shader stages in the shader program.
+		* Needed for the transfer to the pipeline.
+		* @return integer with the number of stages
+		*/
+		int getShaderStagesCount();
+
+
+	};
+}