diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000000000000000000000000000000000000..c79960ba591547bdc0f2059cecf9bb643b9bf9c2
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,10 @@
+*.blend filter=lfs diff=lfs merge=lfs -text
+*.blend1 filter=lfs diff=lfs merge=lfs -text
+*.bin filter=lfs diff=lfs merge=lfs -text
+*.glb filter=lfs diff=lfs merge=lfs -text
+*.jpg filter=lfs diff=lfs merge=lfs -text
+*.png filter=lfs diff=lfs merge=lfs -text
+*.tif filter=lfs diff=lfs merge=lfs -text
+*.psd filter=lfs diff=lfs merge=lfs -text
+*.gltf filter=lfs diff=lfs merge=lfs
+
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..b160aa4348dcd5e7117c56e0e045211f4854c8e4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,28 @@
+# IDE specific files
+.project
+.cproject
+.vs/
+.vscode/
+.idea/
+.editorconfig
+
+# build directories
+bin/
+build/
+cmake-build-debug/
+cmake-build-release/
+
+# VS build files and binaries
+*.exe
+*.ilk
+*.pdb
+
+# GUI configuration files
+imgui.ini
+
+# Generated source and header files for shaders
+*.hxx
+*.cxx
+
+# Cache for different tasks like source code indexing
+.cache/
diff --git a/first_triangle/.gitignore b/first_triangle/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..7e24fd7b853bfb0a29d8b30879ef1cb95ad141c0
--- /dev/null
+++ b/first_triangle/.gitignore
@@ -0,0 +1 @@
+first_triangle
\ No newline at end of file
diff --git a/first_triangle/CMakeLists.txt b/first_triangle/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5a97308b9d942cb27c23640db6241564f9a7c7b9
--- /dev/null
+++ b/first_triangle/CMakeLists.txt
@@ -0,0 +1,25 @@
+cmake_minimum_required(VERSION 3.16)
+project(first_triangle)
+
+# setting c++ standard for the project
+set(CMAKE_CXX_STANDARD 20)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+# adding source files to the project
+add_project(first_triangle src/main.cpp)
+
+# including headers of dependencies and the VkCV framework
+target_include_directories(first_triangle SYSTEM BEFORE PRIVATE 
+	${vkcv_include} 
+	${vkcv_includes}
+	${vkcv_camera_include} 
+	${vkcv_shader_compiler_include} 
+	${vkcv_gui_include}
+)
+
+# linking with libraries from all dependencies and the VkCV framework
+target_link_libraries(first_triangle 
+	vkcv_camera 
+	vkcv_shader_compiler 
+	vkcv_gui
+)
diff --git a/first_triangle/shaders/shader.frag b/first_triangle/shaders/shader.frag
new file mode 100644
index 0000000000000000000000000000000000000000..080678beb011afe4b03aed3bf7ae7148b77932dc
--- /dev/null
+++ b/first_triangle/shaders/shader.frag
@@ -0,0 +1,9 @@
+#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/first_triangle/shaders/shader.vert b/first_triangle/shaders/shader.vert
new file mode 100644
index 0000000000000000000000000000000000000000..e129186a4f9b9f8ceca180391210ccaf2953c08e
--- /dev/null
+++ b/first_triangle/shaders/shader.vert
@@ -0,0 +1,25 @@
+#version 450
+#extension GL_ARB_separate_shader_objects : enable
+
+layout(location = 0) out vec3 fragColor;
+
+layout( push_constant ) uniform constants{
+    mat4 mvp;
+};
+
+void main()	{
+    vec3 positions[3] = {
+        vec3(-0.5, 0.5, -1),
+        vec3( 0.5, 0.5, -1),
+        vec3(0, -0.5, -1)
+    };
+    
+    vec3 colors[3] = {
+        vec3(1, 0, 0),
+        vec3(0, 1, 0),
+        vec3(0, 0, 1)
+    };
+
+	gl_Position = mvp * vec4(positions[gl_VertexIndex], 1.0);
+	fragColor = colors[gl_VertexIndex];
+}
\ No newline at end of file
diff --git a/first_triangle/src/main.cpp b/first_triangle/src/main.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6ffd0d1173b16f672ea324ffbd611eee76782738
--- /dev/null
+++ b/first_triangle/src/main.cpp
@@ -0,0 +1,93 @@
+#include <vkcv/Core.hpp>
+#include <vkcv/Pass.hpp>
+#include <vkcv/shader/GLSLCompiler.hpp>
+#include <vkcv/camera/CameraManager.hpp>
+
+#include <glm/glm.hpp>
+
+int main(int argc, const char** argv) {
+  const std::string applicationName = "My application";
+  
+  vkcv::Core core = vkcv::Core::create(
+    applicationName,
+    VK_MAKE_VERSION(0, 0, 1),
+    { vk::QueueFlagBits::eGraphics },
+    { VK_KHR_SWAPCHAIN_EXTENSION_NAME }
+  );
+  
+  const int windowWidth = 800;
+  const int windowHeight = 600;
+  const bool isWindowResizable = false;
+  
+  vkcv::WindowHandle windowHandle = core.createWindow(
+    applicationName,
+    windowWidth,
+    windowHeight,
+    isWindowResizable
+  );
+  
+  vkcv::Window& window = core.getWindow(windowHandle);
+  
+  vkcv::PassHandle renderPass = vkcv::passSwapchain(
+    core,
+    window.getSwapchain(),
+    { vk::Format::eUndefined }
+  );
+  
+  vkcv::ShaderProgram shaderProgram;
+  vkcv::shader::GLSLCompiler compiler;
+  
+  compiler.compileProgram(
+    shaderProgram,
+    {
+      { vkcv::ShaderStage::VERTEX, "shaders/shader.vert" },
+      { vkcv::ShaderStage::FRAGMENT, "shaders/shader.frag" }
+    },
+    nullptr
+  );
+  
+  vkcv::GraphicsPipelineHandle gfxPipeline = core.createGraphicsPipeline(
+    vkcv::GraphicsPipelineConfig(
+      shaderProgram,
+      renderPass,
+      {},
+      {}
+    )
+  );
+  
+  vkcv::VertexData vertexData;
+  vertexData.setCount(3);
+  
+  vkcv::InstanceDrawcall drawcall (vertexData);
+  const auto swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle();
+  
+  vkcv::camera::CameraManager cameraManager (window);
+  
+  auto camHandle = cameraManager.addCamera(vkcv::camera::ControllerType::PILOT);
+  cameraManager.getCamera(camHandle).setPosition(glm::vec3(0, 0, 2));
+  
+  core.run([&](const vkcv::WindowHandle &windowHandle,
+               double t,
+               double dt,
+               uint32_t swapchainWidth,
+               uint32_t swapchainHeight
+  ) {
+    cameraManager.update(dt);
+    
+    glm::mat4 mvp = cameraManager.getActiveCamera().getMVP();
+    
+    auto cmdStream = core.createCommandStream(vkcv::QueueType::Graphics);
+    
+    core.recordDrawcallsToCmdStream(
+      cmdStream,
+      gfxPipeline,
+      vkcv::pushConstants<glm::mat4>(mvp),
+      { drawcall },
+      { swapchainInput },
+      windowHandle
+    );
+    
+    core.prepareSwapchainImageForPresent(cmdStream);
+    core.submitCommandStream(cmdStream);
+  });
+}