diff --git a/config/Sources.cmake b/config/Sources.cmake
index b8c2dcbdf87a08225cebefa3197277715845e961..0d0a37876813861c605466566eced727a70f6488 100644
--- a/config/Sources.cmake
+++ b/config/Sources.cmake
@@ -19,6 +19,9 @@ set(vkcv_sources
 		${vkcv_include}/vkcv/Window.hpp
 		${vkcv_source}/vkcv/Window.cpp
 
+		${vkcv_include}/vkcv/Buffer.hpp
+		${vkcv_source}/vkcv/Buffer.cpp
+
 		${vkcv_include}/vkcv/SwapChain.hpp
 		${vkcv_source}/vkcv/SwapChain.cpp
 
diff --git a/include/vkcv/Buffer.hpp b/include/vkcv/Buffer.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..6647cbf2e2686edf615ace45e1c63c002f0fd457
--- /dev/null
+++ b/include/vkcv/Buffer.hpp
@@ -0,0 +1,163 @@
+#pragma once
+/**
+ * @authors Lars Hoerttrich
+ * @file include/vkcv/Buffer.hpp
+ * @brief template buffer class, template for type security, implemented here because template classes can't be written in .cpp
+ */
+#include "vkcv/Handles.hpp"
+#include <vulkan/vulkan.hpp>
+#include "vkcv/Context.hpp"
+
+
+
+namespace vkcv {
+	//Enum of buffertypes
+	enum BufferType { VERTEX, UNIFORM, STORAGE };
+
+	//Functions outsourced to Buffer.cpp file:
+	void outsourcedDestructor(vk::Device device, vk::DeviceMemory bufferMemory, vk::Buffer buffer);
+	vk::Buffer outsourcedCreateBuffer(vk::Device device, BufferType type, size_t size);
+	vk::DeviceMemory outsourcedAllocateMemory(vk::Device device, vk::PhysicalDevice physicalDevice, vk::MemoryRequirements memoryRequirements);
+
+	template<typename T>
+	class Buffer {
+	public:
+		//future bufferHandle struct
+		struct Handle {
+			uint64_t id;
+
+		};
+
+		// explicit destruction of default constructor
+		Buffer<T>() = delete;
+		// is never called directly
+		~Buffer<T>() noexcept {
+			outsourcedDestructor(m_Device, m_BufferMemory, m_Buffer);
+		}
+
+		Buffer<T>(const Buffer<T>& other) = delete; // copy-ctor
+		Buffer<T>(Buffer<T>&& other) noexcept :
+		        m_Buffer(other.m_Buffer),
+				m_BufferMemory(other.m_BufferMemory),
+				m_Device(other.m_Device),
+		        m_Type(other.m_Type),
+		        m_Size(other.m_Size),
+		        m_DataP(other.m_DataP)
+		{
+			other.m_Buffer = nullptr;
+			other.m_BufferMemory = nullptr;
+			other.m_Device = nullptr;
+			other.m_Type = vkcv::VERTEX; //set to 0
+			other.m_Size = 0;
+			other.m_DataP = nullptr;
+		} // move-ctor
+
+		Buffer<T>& operator=(const Buffer<T>& other) = delete; // copy assignment
+		Buffer<T>& operator=(Buffer<T>&& other) noexcept {
+			m_Buffer = other.m_Buffer;
+			m_BufferMemory = other.m_BufferMemory;
+			m_Device = other.m_Device;
+			m_Type = other.m_Type;
+			m_Size = other.m_Size;
+			m_DataP = other.m_DataP;
+
+			other.m_Buffer = nullptr;
+			other.m_BufferMemory = nullptr;
+			other.m_Device = nullptr;
+			other.m_Type = vkcv::VERTEX; //set to 0
+			other.m_Size = 0;
+			other.m_DataP = nullptr;
+
+		}// move assignment
+
+		BufferType getType() { return m_Type; };
+		size_t getSize() { return m_Size; };
+		
+		/**
+		 * Maps this buffers Memory, fills this buffer with @p data of type T and count @p count
+		 * unmaps afterwards.
+		 * @p data Pointer to data
+		 * @p count Amount of data of type T
+		 */
+		 // TODO: we will probably need staging-buffer here later (possible add in BufferManager later?)
+		void fill(T* data, size_t count) {
+			const vk::MemoryRequirements requirements = m_Device.getBufferMemoryRequirements(m_Buffer);
+			
+			// TODO: check if mapped already
+			m_DataP = static_cast<uint8_t*>(m_Device.mapMemory(m_BufferMemory, 0, requirements.size));
+			memcpy(m_DataP, data, sizeof(T) * count);
+			m_Device.unmapMemory(m_BufferMemory);
+		};
+		
+		T* map() {
+			const vk::MemoryRequirements requirements = m_Device.getBufferMemoryRequirements(m_Buffer);
+			
+			m_DataP = static_cast<uint8_t*>(m_Device.mapMemory(m_BufferMemory, 0, requirements.size));
+			// TODO: make sure to unmap before deallocation
+			
+			return reinterpret_cast<T*>(m_DataP);
+		};
+		
+		void unmap() {
+			m_Device.unmapMemory(m_BufferMemory);
+			// TODO: mark m_DataP as invalid?
+		};
+		
+		/**
+		 * * Create function of #Buffer requires a @p device, a @p physicalDevice, a @p buffer type and a @p size.		 *
+		 * @param device Vulkan-Device
+		 * @param physicalDevice Vulkan-PhysicalDevice
+		 * @param type Enum type of possible vkcv::BufferType
+		 * @param Size size of data
+		 */
+		static Buffer<T> create(vk::Device device, vk::PhysicalDevice physicalDevice, BufferType type, size_t size) {
+			vk::Buffer buffer = nullptr;
+			
+
+			buffer = outsourcedCreateBuffer(device, type, sizeof(T) * size);
+			
+			if (!buffer) {
+				//TODO: potential issue
+			}
+			
+			//get requirements for allocation
+			const vk::MemoryRequirements requirements = device.getBufferMemoryRequirements(buffer);
+			
+			vk::DeviceMemory memory= outsourcedAllocateMemory(device, physicalDevice, requirements);
+			
+			if (!memory) {
+				//TODO: other potential issue
+			}
+			
+			device.bindBufferMemory(buffer, memory, 0);
+			
+			return Buffer<T>(buffer, memory, device, type, size);
+		}
+
+	private:
+		vk::Buffer m_Buffer;
+		vk::DeviceMemory m_BufferMemory;
+		vk::Device m_Device;
+		BufferType m_Type;
+		size_t m_Size=0;
+		uint8_t* m_DataP;
+
+		/**
+		 * * Constructor of #Buffer requires a @p buffer, a @p memory, @p device, @ requirement, a @p buffer type and a @p size.
+		 * @param buffer Vulkan-Buffer
+		 * @param memory Vulkan-DeviceMemory
+		 * @param device Vulkan-Device
+		 * @param requirement Vulkan-MemoryRequirements
+		 * @param type Enum type of possible vkcv::BufferType
+		 * @param Size size of data
+		 */
+		Buffer<T>(vk::Buffer buffer, vk::DeviceMemory memory, vk::Device device, BufferType type, size_t size) :
+				m_Buffer(buffer),
+				m_BufferMemory(memory),
+				m_Device(device),
+				m_Type(type),
+				m_Size(size),
+				m_DataP(nullptr)
+		{}	
+	};
+}
diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index 0b29819d357a7aa9494690e89bde8907a99e143c..45e555151584e60f4edd29058e5a59e076f9fafc 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -12,6 +12,7 @@
 #include "vkcv/Window.hpp"
 #include "vkcv/PassConfig.hpp"
 #include "vkcv/Handles.hpp"
+#include "vkcv/Buffer.hpp"
 #include "vkcv/PipelineConfig.hpp"
 #include "CommandResources.hpp"
 #include "SyncResources.hpp"
@@ -19,9 +20,6 @@
 
 namespace vkcv
 {
-    // TODO:
-    class Buffer;
-
     // forward declarations
     class PassManager;
     class PipelineManager;
@@ -138,8 +136,16 @@ namespace vkcv
         [[nodiscard]]
         PassHandle createPass(const PassConfig &config);
 
-        // TODO:
-        BufferHandle createBuffer(const Buffer &buf);
+        /**
+            * Creates a #Buffer with data-type T and @p bufferType 
+            * @param bufferType Type of Buffer created
+            * @param size Amount of Data of type T
+            * return Buffer-Object
+            */
+        template<typename T>
+        Buffer<T> createBuffer(vkcv::BufferType bufferType,size_t size) {
+        	return Buffer<T>::create(m_Context.getDevice(), m_Context.getPhysicalDevice(), bufferType, size);
+        }
 
 		/**
 		 * @brief start recording command buffers and increment frame index
diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp
index fb9d764c6f130c3436f9b76c903e39bcd68d3ac6..3c3f91de9ac1c4490859559db2bca5bdd089ecfa 100644
--- a/projects/first_triangle/src/main.cpp
+++ b/projects/first_triangle/src/main.cpp
@@ -28,6 +28,17 @@ int main(int argc, const char** argv) {
 	const vk::Instance& instance = context.getInstance();
 	const vk::PhysicalDevice& physicalDevice = context.getPhysicalDevice();
 	const vk::Device& device = context.getDevice();
+	
+	struct vec3 {
+		float x, y, z;
+	};
+	
+	auto buffer = core.createBuffer<vec3>(vkcv::BufferType::VERTEX, 3);
+	
+	vec3* m = buffer.map();
+	m[0] = { 0, 0, 0 };
+	m[0] = { 0, 0, 0 };
+	m[0] = { 0, 0, 0 };
 
 	std::cout << "Physical device: " << physicalDevice.getProperties().deviceName << std::endl;
 
diff --git a/src/vkcv/Buffer.cpp b/src/vkcv/Buffer.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..956f680064b30ac5e22ce41c622e2cb96ccecd46
--- /dev/null
+++ b/src/vkcv/Buffer.cpp
@@ -0,0 +1,61 @@
+/**
+ * @authors Lars Hoerttrich
+ * @file src/vkcv/Buffer.cpp
+ * @brief Implementation of template buffer class, template for type security
+ */
+#include"vkcv/Buffer.hpp"
+
+namespace vkcv {
+
+	/**
+	 * @brief searches memory type index for buffer allocation, inspired by vulkan tutorial and "https://github.com/KhronosGroup/Vulkan-Hpp/blob/master/samples/utils/utils.hpp"
+	 * @param physicalMemoryProperties Memory Properties of physical device
+	 * @param typeBits
+	 * @param requirements Property flags that are required
+	 * @return memory type index for Buffer
+	 */
+	uint32_t searchMemoryType(vk::PhysicalDeviceMemoryProperties const& physicalMemoryProperties, uint32_t typeBits, vk::MemoryPropertyFlags requirements) {
+		uint32_t memoryTypeIndex = uint32_t(0);
+		for (uint32_t i = 0; i < physicalMemoryProperties.memoryTypeCount; i++)
+		{
+			if ((typeBits & 1) &&
+				((physicalMemoryProperties.memoryTypes[i].propertyFlags & requirements) == requirements))
+			{
+				memoryTypeIndex = i;
+				break;
+			}
+			typeBits >>= 1;
+		}
+		return memoryTypeIndex;
+	}
+
+	void outsourcedDestructor(vk::Device device, vk::DeviceMemory bufferMemory, vk::Buffer buffer)
+	{
+		if (device) {
+			device.freeMemory(bufferMemory);
+			device.destroyBuffer(buffer);
+		}
+	}
+
+	vk::Buffer outsourcedCreateBuffer(vk::Device device, BufferType type, size_t size)
+	{
+		switch (type) {
+		case VERTEX: {
+			//create vertex buffer
+			return device.createBuffer(vk::BufferCreateInfo(vk::BufferCreateFlags(), size, vk::BufferUsageFlagBits::eVertexBuffer));
+		}
+		default: {
+			// TODO: maybe an issue
+		}
+		}
+
+		return vk::Buffer(); //should never be reached
+	}
+
+	vk::DeviceMemory outsourcedAllocateMemory(vk::Device device, vk::PhysicalDevice physicalDevice, vk::MemoryRequirements memoryRequirements)
+	{
+		//find Memory Type
+		uint32_t memoryType = searchMemoryType(physicalDevice.getMemoryProperties(), memoryRequirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent);
+		return device.allocateMemory(vk::MemoryAllocateInfo(memoryRequirements.size, memoryType));
+	}
+}
\ No newline at end of file