diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..9cbe5077139237928e7d6c2a843526b547ec5282
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+.project
+.cproject
+.idea/
+
+build/
+cmake-build-debug/
+cmake-build-release/
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000000000000000000000000000000000000..b44e47387fc30a41c3f5c8d09b5ad525b354f233
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "lib/glfw"]
+	path = lib/glfw
+	url = https://github.com/glfw/glfw.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5ebce0ba8054e3fcce8be4f9c7299038422e5c73
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,44 @@
+cmake_minimum_required(VERSION 3.16)
+project(vkcv)
+
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+message("-- Language: [ C++ " ${CMAKE_CXX_STANDARD} " ]")
+
+set(vkcv_config ${PROJECT_SOURCE_DIR}/config)
+set(vkcv_config_ext ${vkcv_config}/ext)
+
+set(vkcv_lib lib)
+
+set(vkcv_source ${PROJECT_SOURCE_DIR}/src)
+
+set(vkcv_flags ${CMAKE_CXX_FLAGS})
+
+include(${vkcv_config}/Sources.cmake)
+include(${vkcv_config}/Libraries.cmake)
+
+set(CMAKE_CXX_FLAGS ${vkcv_flags})
+
+message("-- Flags: [ ${CMAKE_CXX_FLAGS} ]")
+
+add_compile_definitions(${vkcv_definitions})
+
+if (vkcv_directories)
+	include_directories(${vkcv_directories})
+endif()
+
+add_library(vkcv SHARED ${vkcv_sources})
+
+if(MSVC)
+  #enable multicore compilation on visual studio
+  target_compile_options(vkcv PRIVATE "/MP" "/openmp")
+
+  #set source groups to create proper filters in visual studio
+  source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${vkcv_sources})
+endif()
+
+target_include_directories(vkcv SYSTEM BEFORE PRIVATE ${vkcv_includes})
+target_link_libraries(vkcv ${vkcv_libraries})
+
+add_subdirectory(projects)
diff --git a/config/Libraries.cmake b/config/Libraries.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..3b4c75ead3998641e3868ade305f281b3ce1bd93
--- /dev/null
+++ b/config/Libraries.cmake
@@ -0,0 +1,32 @@
+set(vkcv_config_lib ${vkcv_config}/lib)
+
+set(vkcv_lib_path ${PROJECT_SOURCE_DIR}/${vkcv_lib})
+
+if(NOT WIN32)
+	set(vkcv_libraries stdc++fs)
+	
+	# optimization for loading times
+	list(APPEND vkcv_flags -pthread)
+	list(APPEND vkcv_flags -fopenmp)
+endif()
+
+set(vkcv_config_msg " - Library: ")
+
+include(${vkcv_config_lib}/GLFW.cmake)    # glfw-x11 / glfw-wayland					# libglfw3-dev
+include(${vkcv_config_lib}/Vulkan.cmake)  # vulkan-intel / vulkan-radeon / nvidia	# libvulkan-dev
+
+if (vkcv_flags)
+    list(REMOVE_DUPLICATES vkcv_flags)
+endif()
+
+if (vkcv_includes)
+    list(REMOVE_DUPLICATES vkcv_includes)
+endif ()
+
+include(${vkcv_config_ext}/CheckLibraries.cmake)
+
+if (vkcv_definitions)
+    list(REMOVE_DUPLICATES vkcv_definitions)
+endif ()
+
+list(JOIN vkcv_flags " " vkcv_flags)
diff --git a/config/Sources.cmake b/config/Sources.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..f25104e9df248d07dd0cd864d56645db8ed422d7
--- /dev/null
+++ b/config/Sources.cmake
@@ -0,0 +1,5 @@
+
+set(vkcv_sources
+		${vkcv_source}/vkcv/Context.hpp
+		${vkcv_source}/vkcv/Context.cpp
+)
diff --git a/config/ext/CheckLibraries.cmake b/config/ext/CheckLibraries.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..97950d1123f126cc555f376b86c90ed1acb2628e
--- /dev/null
+++ b/config/ext/CheckLibraries.cmake
@@ -0,0 +1,53 @@
+
+list(REMOVE_DUPLICATES vkcv_libraries)
+
+foreach (a_lib IN LISTS vkcv_libraries)
+    if (NOT EXISTS "${a_lib}")
+        string(REGEX MATCH ^/usr/lib/x86_64-linux-gnu/.*$ vkcv_usr_lib_u_match ${a_lib})
+
+        if (vkcv_usr_lib_u_match)
+            string(SUBSTRING ${vkcv_usr_lib_u_match} 26 -1 a_lib)
+
+            list(REMOVE_ITEM vkcv_libraries ${vkcv_usr_lib_u_match})
+            list(APPEND vkcv_libraries_ext ${a_lib})
+        else ()
+            string(REGEX MATCH ^/usr/lib/.*$ vkcv_usr_lib_match ${a_lib})
+            string(REGEX MATCH ^/lib/.*$ a_lib_match ${a_lib})
+
+            if (vkcv_usr_lib_match)
+                list(REMOVE_ITEM vkcv_libraries ${a_lib})
+
+                string(SUBSTRING ${vkcv_usr_lib_match} 8 -1 a_lib)
+                set(a_lib "/usr/lib/x86_64-linux-gnu${a_lib}")
+
+                if (EXISTS ${a_lib})
+                    list(APPEND vkcv_libraries_ext ${a_lib})
+                endif ()
+            elseif (a_lib_match)
+                list(REMOVE_ITEM vkcv_libraries ${a_lib})
+
+                string(SUBSTRING ${a_lib_match} 4 -1 a_lib)
+                set(a_lib "/usr/lib/x86_64-linux-gnu${a_lib}")
+
+                if (EXISTS ${a_lib})
+                    list(APPEND vkcv_libraries_ext ${a_lib})
+                endif ()
+            else ()
+                string(REGEX MATCH ^-l.*$ a_lib_match ${a_lib})
+
+                if (a_lib_match)
+                    string(SUBSTRING ${a_lib_match} 2 -1 a_lib)
+
+                    list(REMOVE_ITEM vkcv_libraries ${a_lib_match})
+                    list(APPEND vkcv_libraries_ext ${a_lib})
+                endif ()
+            endif ()
+        endif ()
+    endif ()
+endforeach ()
+
+foreach (a_lib IN LISTS vkcv_libraries_ext)
+    list(APPEND vkcv_libraries ${a_lib})
+endforeach ()
+
+
diff --git a/config/lib/GLFW.cmake b/config/lib/GLFW.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..1b68d8aa97ba59158a7bd805ab2470f554f705aa
--- /dev/null
+++ b/config/lib/GLFW.cmake
@@ -0,0 +1,18 @@
+
+find_package(glfw3 QUIET)
+
+if (glfw3_FOUND)
+    list(APPEND vkcv_libraries glfw)
+
+    message(${vkcv_config_msg} " GLFW    -   " ${glfw3_VERSION})
+else()
+    if (EXISTS "${vkcv_lib_path}/glfw")
+        add_subdirectory(${vkcv_lib}/glfw)
+
+        list(APPEND vkcv_libraries glfw)
+
+        message(${vkcv_config_msg} " GLFW    -   " ${glfw3_VERSION})
+    else()
+        message(WARNING "GLFW is required..! Update the submodules!")
+    endif ()
+endif ()
diff --git a/config/lib/Vulkan.cmake b/config/lib/Vulkan.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..e8fe4aee3a949fa7bf9906558f8a0c558eb47cf2
--- /dev/null
+++ b/config/lib/Vulkan.cmake
@@ -0,0 +1,9 @@
+
+find_package(Vulkan REQUIRED)
+
+if (Vulkan_FOUND)
+    list(APPEND vkcv_includes ${Vulkan_INCLUDE_DIR})
+    list(APPEND vkcv_libraries ${Vulkan_LIBRARIES})
+
+    message(${vkcv_config_msg} " Vulkan  -   ")
+endif ()
diff --git a/lib/glfw b/lib/glfw
new file mode 160000
index 0000000000000000000000000000000000000000..0e9ec7788b4985a0df698080258e4091d18dcc3b
--- /dev/null
+++ b/lib/glfw
@@ -0,0 +1 @@
+Subproject commit 0e9ec7788b4985a0df698080258e4091d18dcc3b
diff --git a/projects/CMakeLists.txt b/projects/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..27305956cac6670331096364a6658a90efcc831b
--- /dev/null
+++ b/projects/CMakeLists.txt
@@ -0,0 +1,2 @@
+
+add_subdirectory(first_triangle)
diff --git a/projects/first_triangle/CMakeLists.txt b/projects/first_triangle/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..c5a9046881dbab737b357b8a3cd875a9c6b284ae
--- /dev/null
+++ b/projects/first_triangle/CMakeLists.txt
@@ -0,0 +1,10 @@
+cmake_minimum_required(VERSION 3.16)
+project(first_triangle)
+
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+add_executable(first_triangle src/main.cpp)
+
+target_include_directories(first_triangle SYSTEM BEFORE PRIVATE ${vkcv_source} ${vkcv_includes})
+target_link_libraries(first_triangle vkcv ${vkcv_libraries})
diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..25e26a682943f4b095b647034eb7aaa18342a3af
--- /dev/null
+++ b/projects/first_triangle/src/main.cpp
@@ -0,0 +1,14 @@
+
+#include <iostream>
+#include <vkcv/Context.hpp>
+
+int main(int argc, const char** argv) {
+	vkcv::Context context = vkcv::Context::create(
+			"First Triangle",
+			VK_MAKE_VERSION(0, 0, 1)
+	);
+
+	std::cout << "Hello world" << std::endl;
+
+	return 0;
+}
diff --git a/src/vkcv/Context.cpp b/src/vkcv/Context.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bfad8c96c322f8004c26dd7f7f0e9ba50b65aab3
--- /dev/null
+++ b/src/vkcv/Context.cpp
@@ -0,0 +1,56 @@
+
+#include "Context.hpp"
+
+namespace vkcv {
+
+	Context::Context(vk::Instance instance, vk::PhysicalDevice physicalDevice, vk::Device device)
+	: m_instance(instance), m_physicalDevice(physicalDevice), m_device(device)
+	{}
+
+	Context::~Context() {
+		m_device.destroy();
+		m_instance.destroy();
+	}
+	
+	Context Context::create(const char* applicationName, uint32_t applicationVersion) {
+		const vk::ApplicationInfo applicationInfo (
+				applicationName,
+				applicationVersion,
+				"vkCV",
+				VK_MAKE_VERSION(0, 0, 1),
+				VK_HEADER_VERSION_COMPLETE
+		);
+		
+		// TODO: enable validation layers in debug build and add required extensions
+		const vk::InstanceCreateInfo instanceCreateInfo (
+				vk::InstanceCreateFlags(),
+				&applicationInfo,
+				0,
+				nullptr,
+				0,
+				nullptr
+		);
+		
+		vk::Instance instance = vk::createInstance(instanceCreateInfo);
+		
+		// TODO: search for the best physical device (discrete GPU)
+		vk::PhysicalDevice physicalDevice = instance.enumeratePhysicalDevices()[0];
+		
+		// TODO: create required queues, add validation layers and required extensions
+		const vk::DeviceCreateInfo deviceCreateInfo (
+				vk::DeviceCreateFlags(),
+				0,
+				nullptr,
+				0,
+				nullptr,
+				0,
+				nullptr,
+				nullptr
+		);
+		
+		vk::Device device = physicalDevice.createDevice(deviceCreateInfo);
+		
+		return Context(instance, physicalDevice, device);
+	}
+
+}
diff --git a/src/vkcv/Context.hpp b/src/vkcv/Context.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..f3736276770af720442452a66708a2bbcd58fd04
--- /dev/null
+++ b/src/vkcv/Context.hpp
@@ -0,0 +1,28 @@
+#pragma once
+
+#include <vulkan/vulkan.hpp>
+
+namespace vkcv {
+
+	class Context final {
+	private:
+		vk::Instance m_instance;
+		vk::PhysicalDevice m_physicalDevice;
+		vk::Device m_device;
+		
+		Context(vk::Instance instance, vk::PhysicalDevice physicalDevice, vk::Device device);
+
+	public:
+		Context(const Context &other) = delete;
+		Context(Context &&other) = default;
+
+		virtual ~Context();
+
+		Context& operator=(const Context &other) = delete;
+		Context& operator=(Context &&other) = default;
+		
+		static Context create(const char* applicationName, uint32_t applicationVersion);
+		
+	};
+
+}