diff --git a/CMakeLists.txt b/CMakeLists.txt
index 74b2891989e31118f543b03ccc3de7b5f3a13e05..225d1b47efcb6fe78e31ccd77ea9c6964986d981 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -341,8 +341,8 @@ add_library(lava.app STATIC
         ${LIBLAVA_DIR}/app/def.hpp
         ${LIBLAVA_DIR}/app/forward_shading.cpp
         ${LIBLAVA_DIR}/app/forward_shading.hpp
-        ${LIBLAVA_DIR}/app/gui.cpp
-        ${LIBLAVA_DIR}/app/gui.hpp
+        ${LIBLAVA_DIR}/app/imgui.cpp
+        ${LIBLAVA_DIR}/app/imgui.hpp
         ${LIBLAVA_EXT_DIR}/imgui/imgui.cpp
         ${LIBLAVA_EXT_DIR}/imgui/imgui_draw.cpp
         ${LIBLAVA_EXT_DIR}/imgui/imgui_tables.cpp
diff --git a/DOCS.md b/DOCS.md
index 0cbdd609370692c7f98b029b5627079e08b6fdc7..2f7a6e8bd1bebd746cee590013b7c47cbf1e5d6e 100644
--- a/DOCS.md
+++ b/DOCS.md
@@ -358,7 +358,8 @@ int main(int argc, char* argv[]) {
     if (!app.setup())
         return error::not_ready;
 
-    app.gui.on_draw = []() {
+    app.imgui.on_draw = []() {
+
         ImGui::ShowDemoWindow();
     };
 
@@ -386,7 +387,7 @@ int main(int argc, char* argv[]) {
 
 #### lava [app](https://github.com/liblava/liblava/tree/master/liblava/app)
 
-[![app](https://img.shields.io/badge/lava-app-brightgreen.svg)](https://github.com/liblava/liblava/tree/master/liblava/app/app.hpp) [![camera](https://img.shields.io/badge/lava-camera-brightgreen.svg)](https://github.com/liblava/liblava/tree/master/liblava/app/camera.hpp) [![config](https://img.shields.io/badge/lava-config-brightgreen.svg)](https://github.com/liblava/liblava/tree/master/liblava/app/config.hpp) [![forward_shading](https://img.shields.io/badge/lava-forward_shading-brightgreen.svg)](https://github.com/liblava/liblava/tree/master/liblava/app/forward_shading.hpp) [![gui](https://img.shields.io/badge/lava-gui-brightgreen.svg)](https://github.com/liblava/liblava/tree/master/liblava/app/gui.hpp)
+[![app](https://img.shields.io/badge/lava-app-brightgreen.svg)](https://github.com/liblava/liblava/tree/master/liblava/app/app.hpp) [![camera](https://img.shields.io/badge/lava-camera-brightgreen.svg)](https://github.com/liblava/liblava/tree/master/liblava/app/camera.hpp) [![config](https://img.shields.io/badge/lava-config-brightgreen.svg)](https://github.com/liblava/liblava/tree/master/liblava/app/config.hpp) [![forward_shading](https://img.shields.io/badge/lava-forward_shading-brightgreen.svg)](https://github.com/liblava/liblava/tree/master/liblava/app/forward_shading.hpp) [![imgui](https://img.shields.io/badge/lava-imgui-brightgreen.svg)](https://github.com/liblava/liblava/tree/master/liblava/app/imgui.hpp)
 
 #### lava [block](https://github.com/liblava/liblava/tree/master/liblava/block)
 
diff --git a/README.md b/README.md
index ea89b3347746a8aadf6002e7dfa68dd4758e38d8..8552924f39aa448da38a54a4e0470408a49bfd03 100644
--- a/README.md
+++ b/README.md
@@ -18,7 +18,7 @@
 * **[run loop](DOCS.md/#run-loop)** **abstraction** for **[window](DOCS.md/#window)** and **[input](DOCS.md/#input) handling**
 * **plain** **[renderer](DOCS.md/#renderer)** and **[command buffer model](DOCS.md/#command-buffer-model)**
 * **[texture](DOCS.md/#texture)** and **[mesh](DOCS.md/#mesh)** **loading** from **virtual [file system](DOCS.md/#file-system)**
-* **[camera](DOCS.md/#camera)** + **[gui](DOCS.md/#gui)** + **[logging](DOCS.md/#logging)** + **test driver** and much more
+* **[GUI](DOCS.md/#gui)** + **[camera](DOCS.md/#camera)** + **[logging](DOCS.md/#logging)** + **utils** and much more
 
 <br />
 
diff --git a/liblava/app.hpp b/liblava/app.hpp
index 07f3b87e5d5bee258de2bb400fe24e2e842665c6..7a218126c7948676ab26b6187c8be04d1d21a1a7 100644
--- a/liblava/app.hpp
+++ b/liblava/app.hpp
@@ -8,4 +8,4 @@
 #include <liblava/app/camera.hpp>
 #include <liblava/app/config.hpp>
 #include <liblava/app/forward_shading.hpp>
-#include <liblava/app/gui.hpp>
+#include <liblava/app/imgui.hpp>
diff --git a/liblava/app/app.cpp b/liblava/app/app.cpp
index 3d395c7eecfa99f378efb0253f5e4d1e7ac24472..989386a99a27e30306d40b12376b5ce30d240fc3 100644
--- a/liblava/app/app.cpp
+++ b/liblava/app/app.cpp
@@ -31,8 +31,8 @@ namespace lava {
             if (j.count(_delta_))
                 run_time.fix_delta = ms(j[_delta_]);
 
-            if (j.count(_gui_))
-                gui.set_active(j[_gui_]);
+            if (j.count(_imgui_))
+                imgui.set_active(j[_imgui_]);
 
             if (j.count(_v_sync_))
                 config.v_sync = j[_v_sync_];
@@ -46,7 +46,7 @@ namespace lava {
             j[_speed_] = run_time.speed;
             j[_fixed_delta_] = run_time.use_fix_delta;
             j[_delta_] = run_time.fix_delta.count();
-            j[_gui_] = gui.activated();
+            j[_imgui_] = imgui.activated();
             j[_v_sync_] = config.v_sync;
             j[_physical_device_] = config.physical_device;
         };
@@ -116,7 +116,7 @@ namespace lava {
         camera.aspect_ratio = window.get_aspect_ratio();
         camera.update_projection();
 
-        if (!create_gui())
+        if (!create_imgui())
             return false;
 
         if (!create_block())
@@ -131,7 +131,7 @@ namespace lava {
         add_run_end([&]() {
             camera.destroy();
 
-            destroy_gui();
+            destroy_imgui();
 
             block.destroy();
 
@@ -157,35 +157,35 @@ namespace lava {
         return true;
     }
 
-    bool app::create_gui() {
-        if (config.font.file.empty()) {
-            auto font_files = file_system::enumerate_files(_gui_font_path_);
+    bool app::create_imgui() {
+        if (config.imgui_font.file.empty()) {
+            auto font_files = file_system::enumerate_files(_imgui_font_path_);
             if (!font_files.empty())
-                config.font.file = fmt::format("{}{}", _gui_font_path_, str(font_files.front()));
+                config.imgui_font.file = fmt::format("{}{}", _imgui_font_path_, str(font_files.front()));
         }
 
-        setup_font(gui_config, config.font);
+        setup_imgui_font(imgui_config, config.imgui_font);
 
-        gui_config.ini_file_dir = file_system::get_pref_dir();
+        imgui_config.ini_file_dir = file_system::get_pref_dir();
 
-        gui.setup(window.get(), gui_config);
-        if (!gui.create(device, target->get_frame_count(), shading.get_vk_pass()))
+        imgui.setup(window.get(), imgui_config);
+        if (!imgui.create(device, target->get_frame_count(), shading.get_vk_pass()))
             return false;
 
-        shading.get_pass()->add(gui.get_pipeline());
+        shading.get_pass()->add(imgui.get_pipeline());
 
-        fonts = make_texture();
-        if (!gui.upload_fonts(fonts))
+        imgui_fonts = make_texture();
+        if (!imgui.upload_fonts(imgui_fonts))
             return false;
 
-        staging.add(fonts);
+        staging.add(imgui_fonts);
 
         return true;
     }
 
-    void app::destroy_gui() {
-        gui.destroy();
-        fonts->destroy();
+    void app::destroy_imgui() {
+        imgui.destroy();
+        imgui_fonts->destroy();
     }
 
     bool app::create_target() {
@@ -215,17 +215,17 @@ namespace lava {
     }
 
     void app::handle_input() {
-        input.add(&gui);
+        input.add(&imgui);
 
         input.key.listeners.add([&](key_event::ref event) {
-            if (gui.capture_keyboard()) {
+            if (imgui.capture_keyboard()) {
                 camera.stop();
                 return false;
             }
 
             if (config.handle_key_events) {
                 if (event.pressed(key::tab))
-                    gui.toggle();
+                    imgui.toggle();
 
                 if (event.pressed(key::escape))
                     return shut_down();
@@ -251,7 +251,7 @@ namespace lava {
         });
 
         input.mouse_button.listeners.add([&](mouse_button_event::ref event) {
-            if (gui.capture_mouse())
+            if (imgui.capture_mouse())
                 return false;
 
             if (camera.activated())
@@ -261,7 +261,7 @@ namespace lava {
         });
 
         input.scroll.listeners.add([&](scroll_event::ref event) {
-            if (gui.capture_mouse())
+            if (imgui.capture_mouse())
                 return false;
 
             if (camera.activated())
@@ -278,7 +278,7 @@ namespace lava {
         });
 
         add_run_end([&]() {
-            input.remove(&gui);
+            input.remove(&imgui);
         });
     }
 
@@ -291,7 +291,7 @@ namespace lava {
                 device->wait_for_idle();
 
                 destroy_target();
-                destroy_gui();
+                destroy_imgui();
 
                 if (window.switch_mode_request()) {
                     if (config.save_window)
@@ -315,7 +315,7 @@ namespace lava {
                 if (!create_target())
                     return false;
 
-                return create_gui();
+                return create_imgui();
             }
 
             if (window.resize_request()) {
diff --git a/liblava/app/app.hpp b/liblava/app/app.hpp
index 567aa0d4355bf508fb167e5e79e91a47f18ef4b7..b4a0f66498a660c95da5a9b6ebd370fe349099fd 100644
--- a/liblava/app/app.hpp
+++ b/liblava/app/app.hpp
@@ -21,8 +21,8 @@ namespace lava {
         lava::window window;
         lava::input input;
 
-        lava::gui gui;
-        gui::config gui_config;
+        lava::imgui imgui;
+        imgui::config imgui_config;
 
         device_ptr device = nullptr;
         lava::camera camera;
@@ -72,15 +72,15 @@ namespace lava {
         void update();
         void render();
 
-        bool create_gui();
-        void destroy_gui();
+        bool create_imgui();
+        void destroy_imgui();
 
         bool create_target();
         void destroy_target();
 
         bool create_block();
 
-        texture::ptr fonts;
+        texture::ptr imgui_fonts;
 
         bool toggle_v_sync = false;
         ui32 frame_counter = 0;
diff --git a/liblava/app/config.hpp b/liblava/app/config.hpp
index 8654a86fa34f7a0304e2cf892c0d77b48b8f2679..2d54a77b0c7585328e9d7682088bebfcbe06fb82 100644
--- a/liblava/app/config.hpp
+++ b/liblava/app/config.hpp
@@ -4,7 +4,7 @@
 
 #pragma once
 
-#include <liblava/app/gui.hpp>
+#include <liblava/app/imgui.hpp>
 #include <liblava/frame/window.hpp>
 
 namespace lava {
@@ -16,7 +16,7 @@ namespace lava {
         bool v_sync = false;
         index physical_device = 0;
 
-        lava::font font;
+        imgui::font imgui_font;
     };
 
     window::state::optional load_window_state(name save_name);
diff --git a/liblava/app/def.hpp b/liblava/app/def.hpp
index bcea534f986376ead8fbaa86926fb01d954c4aac..b4a0228c5c036c324219b01bb929c6c42404f102 100644
--- a/liblava/app/def.hpp
+++ b/liblava/app/def.hpp
@@ -16,7 +16,7 @@ namespace lava {
     constexpr name _auto_load_ = "auto load";
     constexpr name _fixed_delta_ = "fixed delta";
     constexpr name _delta_ = "delta";
-    constexpr name _gui_ = "gui";
+    constexpr name _imgui_ = "imgui";
     constexpr name _v_sync_ = "v-sync";
     constexpr name _physical_device_ = "physical device";
 
@@ -25,4 +25,7 @@ namespace lava {
     constexpr name _lava_gui_ = "lava gui";
     constexpr name _lava_texture_staging_ = "lava texture staging";
 
+    // res folder
+    constexpr name _font_icon_path_ = "font/icon/";
+
 } // namespace lava
diff --git a/liblava/app/gui.cpp b/liblava/app/imgui.cpp
similarity index 96%
rename from liblava/app/gui.cpp
rename to liblava/app/imgui.cpp
index cd548395ba910508c03ca91f1882b990f60cfbeb..9303552700059bd24f12d03f73adc71d8aa5ed5c 100644
--- a/liblava/app/gui.cpp
+++ b/liblava/app/imgui.cpp
@@ -1,9 +1,9 @@
-// file      : liblava/app/gui.cpp
+// file      : liblava/app/imgui.cpp
 // copyright : Copyright (c) 2018-present, Lava Block OÜ and contributors
 // license   : MIT; see accompanying LICENSE file
 
 #include <liblava/app/def.hpp>
-#include <liblava/app/gui.hpp>
+#include <liblava/app/imgui.hpp>
 #include <liblava/base/debug_utils.hpp>
 #include <liblava/resource/format.hpp>
 
@@ -29,18 +29,18 @@ namespace lava {
         glfwSetClipboardString(static_cast<GLFWwindow*>(user_data), text);
     }
 
-    void gui::handle_mouse_button_event(i32 button, i32 action, i32 mods) {
+    void imgui::handle_mouse_button_event(i32 button, i32 action, i32 mods) {
         if (action == GLFW_PRESS && button >= 0 && button < IM_ARRAYSIZE(mouse_just_pressed))
             mouse_just_pressed[button] = true;
     }
 
-    void gui::handle_scroll_event(r64 x_offset, r64 y_offset) {
+    void imgui::handle_scroll_event(r64 x_offset, r64 y_offset) {
         auto& io = ImGui::GetIO();
         io.MouseWheelH += static_cast<float>(x_offset);
         io.MouseWheel += static_cast<float>(y_offset);
     }
 
-    void gui::handle_key_event(i32 key, i32 scancode, i32 action, i32 mods) {
+    void imgui::handle_key_event(i32 key, i32 scancode, i32 action, i32 mods) {
         auto& io = ImGui::GetIO();
 
         if (action == GLFW_PRESS)
@@ -55,7 +55,7 @@ namespace lava {
         io.KeySuper = io.KeysDown[GLFW_KEY_LEFT_SUPER] || io.KeysDown[GLFW_KEY_RIGHT_SUPER];
     }
 
-    void gui::update_mouse_pos_and_buttons() {
+    void imgui::update_mouse_pos_and_buttons() {
         auto& io = ImGui::GetIO();
 
         for (i32 i = 0; i < IM_ARRAYSIZE(io.MouseDown); i++) {
@@ -77,7 +77,7 @@ namespace lava {
         }
     }
 
-    void gui::update_mouse_cursor() {
+    void imgui::update_mouse_cursor() {
         auto& io = ImGui::GetIO();
         if ((io.ConfigFlags & ImGuiConfigFlags_NoMouseCursorChange) || glfwGetInputMode(window, GLFW_CURSOR) == GLFW_CURSOR_DISABLED)
             return;
@@ -91,7 +91,7 @@ namespace lava {
         }
     }
 
-    void gui::setup(GLFWwindow* w, config config) {
+    void imgui::setup(GLFWwindow* w, config config) {
         window = w;
         current_time = 0.0;
 
@@ -219,7 +219,7 @@ namespace lava {
             io.NavInputs[NAV_NO] = v; \
     }
 
-    void gui::new_frame() {
+    void imgui::new_frame() {
         auto& io = ImGui::GetIO();
         IM_ASSERT(io.Fonts->IsBuilt());
 
@@ -345,7 +345,7 @@ namespace lava {
         0x00010038
     };
 
-    bool gui::create(graphics_pipeline::ptr p, index mf) {
+    bool imgui::create(graphics_pipeline::ptr p, index mf) {
         pipeline = std::move(p);
 
         device = pipeline->get_device();
@@ -411,7 +411,7 @@ namespace lava {
         return true;
     }
 
-    void gui::destroy() {
+    void imgui::destroy() {
         if (!initialized)
             return;
 
@@ -426,23 +426,23 @@ namespace lava {
         initialized = false;
     }
 
-    bool gui::capture_mouse() const {
+    bool imgui::capture_mouse() const {
         return ImGui::GetIO().WantCaptureMouse;
     }
 
-    bool gui::capture_keyboard() const {
+    bool imgui::capture_keyboard() const {
         return ImGui::GetIO().WantCaptureKeyboard;
     }
 
-    void gui::set_ini_file(fs::path dir) {
-        dir.append(_gui_file_);
+    void imgui::set_ini_file(fs::path dir) {
+        dir.append(_imgui_file_);
 
         ini_file = dir.string();
 
         ImGui::GetIO().IniFilename = str(ini_file);
     }
 
-    void gui::invalidate_device_objects() {
+    void imgui::invalidate_device_objects() {
         vertex_buffers.clear();
         index_buffers.clear();
 
@@ -459,7 +459,7 @@ namespace lava {
         layout = nullptr;
     }
 
-    void gui::render(VkCommandBuffer cmd_buf) {
+    void imgui::render(VkCommandBuffer cmd_buf) {
         ImGui::Render();
 
         render_draw_lists(cmd_buf);
@@ -467,7 +467,7 @@ namespace lava {
         frame = (frame + 1) % max_frames;
     }
 
-    void gui::prepare_draw_lists(ImDrawData* draw_data) {
+    void imgui::prepare_draw_lists(ImDrawData* draw_data) {
         auto vertex_size = draw_data->TotalVtxCount * sizeof(ImDrawVert);
         if (!vertex_buffers[frame]->valid() || vertex_buffers[frame]->get_size() < vertex_size) {
             if (vertex_buffers[frame]->valid())
@@ -519,7 +519,7 @@ namespace lava {
         check(device->call().vkFlushMappedMemoryRanges(device->get(), to_ui32(ranges.size()), ranges.data()));
     }
 
-    void gui::render_draw_lists(VkCommandBuffer cmd_buf) {
+    void imgui::render_draw_lists(VkCommandBuffer cmd_buf) {
         auto draw_data = ImGui::GetDrawData();
         if (draw_data->TotalVtxCount == 0)
             return;
@@ -587,7 +587,7 @@ namespace lava {
         }
     }
 
-    bool gui::upload_fonts(texture::ptr texture) {
+    bool imgui::upload_fonts(texture::ptr texture) {
         uchar* pixels = nullptr;
 
         auto width = 0;
@@ -618,7 +618,7 @@ namespace lava {
 
 } // namespace lava
 
-void lava::setup_font(gui::config& config, font::ref font) {
+void lava::setup_imgui_font(imgui::config& config, imgui::font::ref font) {
     if (load_file_data(str(font.file), config.font_data)) {
         config.font_size = font.size;
 
diff --git a/liblava/app/gui.hpp b/liblava/app/imgui.hpp
similarity index 81%
rename from liblava/app/gui.hpp
rename to liblava/app/imgui.hpp
index 51a2ac01ba45814349e6c98ecb2f780b26246dc2..7e9c11a518a844e3ecba1a04e2f8faa7f433c69a 100644
--- a/liblava/app/gui.hpp
+++ b/liblava/app/imgui.hpp
@@ -1,4 +1,4 @@
-// file      : liblava/app/gui.hpp
+// file      : liblava/app/imgui.hpp
 // copyright : Copyright (c) 2018-present, Lava Block OÜ and contributors
 // license   : MIT; see accompanying LICENSE file
 
@@ -16,15 +16,15 @@ struct ImDrawData;
 
 namespace lava {
 
-    constexpr const r32 default_font_size = 18.f;
-    constexpr name _gui_file_ = "gui.ini";
+    constexpr const r32 default_imgui_font_size = 18.f;
+    constexpr name _imgui_file_ = "imgui.ini";
 
-    struct gui : input_callback {
-        explicit gui() = default;
-        explicit gui(GLFWwindow* window) {
+    struct imgui : input_callback {
+        explicit imgui() = default;
+        explicit imgui(GLFWwindow* window) {
             setup(window);
         }
-        ~gui() {
+        ~imgui() {
             destroy();
         }
 
@@ -34,12 +34,25 @@ namespace lava {
             ui16 range_begin = 0;
             ui16 range_end = 0;
 
-            r32 size = default_font_size;
+            r32 size = default_imgui_font_size;
+        };
+
+        struct font {
+            using ref = font const&;
+
+            string file;
+            r32 size = 21.f;
+
+            string icon_file;
+            r32 icon_size = 21.f;
+
+            ui16 icon_range_begin = 0;
+            ui16 icon_range_end = 0;
         };
 
         struct config {
             data font_data;
-            r32 font_size = default_font_size;
+            r32 font_size = default_imgui_font_size;
 
             icon_font icon;
 
@@ -139,22 +152,8 @@ namespace lava {
         bool active = true;
     };
 
-    constexpr name _gui_font_path_ = "font/gui/";
-    constexpr name _gui_font_icon_path_ = "font/icon/";
-
-    struct font {
-        using ref = font const&;
-
-        string file;
-        r32 size = 21.f;
-
-        string icon_file;
-        r32 icon_size = 21.f;
-
-        ui16 icon_range_begin = 0;
-        ui16 icon_range_end = 0;
-    };
+    constexpr name _imgui_font_path_ = "font/imgui/";
 
-    void setup_font(gui::config& config, font::ref font);
+    void setup_imgui_font(imgui::config& config, imgui::font::ref font);
 
 } // namespace lava
diff --git a/liblava/core/types.hpp b/liblava/core/types.hpp
index 4bf5ba3c4d10939afe7c530cf920e1b493c36249..fbb866d0b934cf9b1e0293115efe3ba4856ae88f 100644
--- a/liblava/core/types.hpp
+++ b/liblava/core/types.hpp
@@ -135,6 +135,11 @@ namespace lava {
         return static_cast<index>(value);
     }
 
+    template<typename T>
+    inline char const* icon(T value) {
+        return (char const*) value;
+    }
+
     struct no_copy_no_move {
         no_copy_no_move() = default;
         no_copy_no_move(no_copy_no_move const&) = delete;
diff --git a/liblava/fwd.hpp b/liblava/fwd.hpp
index ebd41d5782b046b247ed0cf7ff6a906b8f1df398..5db8b4151c08637a4d7f40fed457c18df5b1cd6a 100644
--- a/liblava/fwd.hpp
+++ b/liblava/fwd.hpp
@@ -10,7 +10,7 @@ namespace lava {
     struct app;
     struct camera;
     struct forward_shading;
-    struct gui;
+    struct imgui;
 
     // liblava/asset.hpp
     struct scope_image;
diff --git a/liblava/util/log.hpp b/liblava/util/log.hpp
index ada30ead0a2f67e654036286f6cf6b5323125997..3872e0e5134ad2d91b73e2fb051cb2291e6146e6 100644
--- a/liblava/util/log.hpp
+++ b/liblava/util/log.hpp
@@ -75,4 +75,9 @@ namespace lava {
         }
     }
 
+    template<typename T>
+    inline string icon_text(T value) {
+        return fmt::format("{}", icon(value));
+    }
+
 } // namespace lava
diff --git a/tests/tests.cpp b/tests/tests.cpp
index d5038f867a9d69dc5f4ca265fc3d600162d840ba..6b08d0444b90a1e8c09b411ea245045c52b31479 100644
--- a/tests/tests.cpp
+++ b/tests/tests.cpp
@@ -399,7 +399,7 @@ LAVA_TEST(8, "imgui demo") {
     if (!app.setup())
         return error::not_ready;
 
-    app.gui.on_draw = []() {
+    app.imgui.on_draw = []() {
         ImGui::ShowDemoWindow();
     };