diff --git a/demo/main.cpp b/demo/main.cpp
index 381e4b3cd8a538884a43d6b6ce04a29164ea18a2..f58a6351a3fcf66ac05e68ec6afd9c947cb8f87f 100644
--- a/demo/main.cpp
+++ b/demo/main.cpp
@@ -206,7 +206,10 @@ void process_edgescroll(fggl::ecs3::World& ecs, InputManager input, fggl::ecs::e
 }
 
 
-void process_camera(fggl::gfx::Window& window, fggl::ecs3::World& ecs, InputManager input, fggl::ecs::entity_t cam) {
+void process_camera(fggl::gfx::Window& window, fggl::ecs3::World& ecs, InputManager input) {
+    auto cameras = ecs.findMatching<fggl::gfx::Camera>();
+    fggl::ecs3::entity_t cam = cameras[0];
+
 	auto camTransform = ecs.get<fggl::math::Transform>(cam);
 	auto camComp = ecs.get<fggl::gfx::Camera>(cam);
 
@@ -251,7 +254,7 @@ int main(int argc, char* argv[]) {
     auto glModule = modules.load<fggl::gfx::ecsOpenGLModule>(win, storage);
 
 	fggl::gfx::loadPipeline(glModule, "unlit", false);
-	fggl::gfx::loadPipeline(glModule, "lighting/phong", false);
+	fggl::gfx::loadPipeline(glModule, "phong", false);
 	fggl::gfx::loadPipeline(glModule, "normals", false);
 
 	// debug layer
@@ -261,56 +264,63 @@ int main(int argc, char* argv[]) {
 	// create ECS
     types.make<fggl::math::Transform>();
 
-	// make camera
-	auto camEnt = ecs.create();
-	{
-		auto cameraTf = ecs.add<fggl::math::Transform>(camEnt);
-		cameraTf->origin( glm::vec3(0.0f, 3.0f, 3.0f) );
-
-		ecs.add<fggl::gfx::Camera>(camEnt);
-	}
-
-	auto floorEnt = ecs.create();
+    // create camera using strings
+    {
+        auto prototype = ecs.create(false);
+        ecs.add(prototype, types.find(fggl::math::Transform::name));
+        ecs.add(prototype, types.find(fggl::gfx::Camera::name));
+
+        auto camTf = ecs.get<fggl::math::Transform>(prototype);
+        camTf->origin( glm::vec3(0.0f, 3.0f, 3.0f) );
+    }
+
+    // create building prototype
+    fggl::ecs3::entity_t bunker;
+    {
+        bunker = ecs.create(true);
+        ecs.add(bunker, types.find(fggl::math::Transform::name));
+
+        // mesh
+        int nSections = 2;
+        constexpr float HALF_PI = M_PI / 2.0f;
+        constexpr char shader[] = "phong";
+
+        fggl::data::Mesh mesh;
+        for (int j=-(nSections/2); j<=nSections/2; j++) {
+            const auto shapeOffset = glm::vec3( 0.0f, 0.0f, j * 1.0f );
+
+            const auto cubeMat = glm::translate( fggl::math::mat4( 1.0f ) , shapeOffset );
+            const auto leftSlope = fggl::math::modelMatrix(
+                    glm::vec3(-1.0f, 0.0f, 0.0f) + shapeOffset,
+                    glm::vec3( 0.0f, -HALF_PI, 0.0f) );
+            const auto rightSlope = fggl::math::modelMatrix(
+                    glm::vec3( 1.0f, 0.0f, 0.0f) + shapeOffset,
+                    glm::vec3( 0.0f, HALF_PI, 0.0f) );
+
+            fggl::data::make_cube( mesh, cubeMat );
+            fggl::data::make_slope( mesh, leftSlope );
+            fggl::data::make_slope( mesh, rightSlope );
+        }
+        mesh.removeDups();
+
+        fggl::gfx::StaticMesh staticMesh{mesh, shader};
+        ecs.set<fggl::gfx::StaticMesh>(bunker, &staticMesh);
+    }
+
+	auto floorEnt = ecs.create(false);
 	{
 		ecs.add<fggl::math::Transform>( floorEnt );
 		fggl::data::Mesh mesh = fggl::data::make_quad_xz();
 
-        fggl::gfx::StaticMesh sMesh{mesh, "lighting/phong"};
+        fggl::gfx::StaticMesh sMesh{mesh, "phong"};
 		ecs.set<fggl::gfx::StaticMesh>(floorEnt, &sMesh);
 	}
 
-	int nCubes = 3;
-	int nSections = 2;
-
-	constexpr float HALF_PI = M_PI / 2.0f;
-
+    int nCubes = 3;
 	for ( int i=0; i<nCubes; i++ ) {
-		auto entity = ecs.create();
-
-		// set the position
-		auto result = ecs.add<fggl::math::Transform>(entity);
+        auto bunkerClone = ecs.copy(bunker);
+        auto result = ecs.get<fggl::math::Transform>(bunkerClone);
 		result->origin( glm::vec3( i * 5.0f, 0.0f, 0.0f) );
-
-		fggl::data::Mesh mesh;
-		for (int j=-(nSections/2); j<=nSections/2; j++) {
-			const auto shapeOffset = glm::vec3( 0.0f, 0.0f, j * 1.0f );
-
-			const auto cubeMat = glm::translate( fggl::math::mat4( 1.0f ) , shapeOffset );
-			const auto leftSlope = fggl::math::modelMatrix( 
-					glm::vec3(-1.0f, 0.0f, 0.0f) + shapeOffset,
-					glm::vec3( 0.0f, -HALF_PI, 0.0f) );
-			const auto rightSlope = fggl::math::modelMatrix( 
-					glm::vec3( 1.0f, 0.0f, 0.0f) + shapeOffset,
-					glm::vec3( 0.0f, HALF_PI, 0.0f) );
-
-			fggl::data::make_cube( mesh, cubeMat );
-			fggl::data::make_slope( mesh, leftSlope );
-			fggl::data::make_slope( mesh, rightSlope );
-		}
-		mesh.removeDups();
-
-        fggl::gfx::StaticMesh staticMesh{mesh, "lighting/phong"};
-		ecs.set<fggl::gfx::StaticMesh>(entity, &staticMesh);
 	}
 
 	bool gamepadWindow = true;
@@ -333,51 +343,68 @@ int main(int argc, char* argv[]) {
 		//
 		// update step
 		// 
-		process_camera(win, ecs, inputs, camEnt);
+		process_camera(win, ecs, inputs);
+
+        // ECS3 inspector
+        ImGui::Begin("Entities");
+        auto entityItr = ecs.all();
+        for (auto& entity : entityItr) {
+            std::string label = "entity-" + std::to_string(entity);
+            if ( ImGui::TreeNode(label.c_str()) ){
+                auto entComp = ecs.getComponents(entity);
+                for ( auto comp : entComp ){
+                    auto meta = types.meta(comp);
+                    ImGui::Text("%s (%d) - %lu bytes", meta->name(), comp, meta->size());
+                }
+                ImGui::TreePop();
+            }
+        }
+        ImGui::End();
 
 		// imgui gamepad debug
-		auto& gamepads = inputs->gamepads;
-		ImGui::Begin("GamePad", &gamepadWindow);
-		for ( int i=0; i<16; i++ ) {
-			std::string title = gamepads.name(i);
-
-			bool present = gamepads.present(i);
-			if ( ImGui::TreeNode(title.c_str()) ) {
-				ImGui::Text("present: %s", present ? "yes" : "no" );
-
-				if ( present ) {
-
-					if ( ImGui::TreeNode("buttons##2") ) {
-						for ( auto& btn : fggl::input::GamepadButtonsMicrosoft ) {
-							ImGui::Text( "%s: %i %i %i", btn.name,
-									gamepads.button(i, btn.id),
-									gamepads.buttonPressed(i, btn.id),
-									gamepads.buttonReleased(i, btn.id)
-									);
-						}
-						ImGui::TreePop();
-					}
-
-					if ( ImGui::TreeNode("axes##2") ) {
-						for ( auto& axis : fggl::input::GamepadAxes ) {
-							ImGui::Text("%s: %f %f", axis.name,
-									gamepads.axis(i, axis.id),
-									gamepads.axisDelta(i, axis.id)
-								   );
-
-						}
-						ImGui::TreePop();
-					}
-
-				}
-
-				ImGui::TreePop();
-				ImGui::Separator();
-			}
-
-		}
-		ImGui::End();
-		debug.showDemo();
+        if ( gamepadWindow ) {
+            auto &gamepads = inputs->gamepads;
+            ImGui::Begin("GamePad", &gamepadWindow);
+            for (int i = 0; i < 16; i++) {
+                std::string title = gamepads.name(i);
+
+                bool present = gamepads.present(i);
+                if (ImGui::TreeNode(title.c_str())) {
+                    ImGui::Text("present: %s", present ? "yes" : "no");
+
+                    if (present) {
+
+                        if (ImGui::TreeNode("buttons##2")) {
+                            for (auto &btn: fggl::input::GamepadButtonsMicrosoft) {
+                                ImGui::Text("%s: %i %i %i", btn.name,
+                                            gamepads.button(i, btn.id),
+                                            gamepads.buttonPressed(i, btn.id),
+                                            gamepads.buttonReleased(i, btn.id)
+                                );
+                            }
+                            ImGui::TreePop();
+                        }
+
+                        if (ImGui::TreeNode("axes##2")) {
+                            for (auto &axis: fggl::input::GamepadAxes) {
+                                ImGui::Text("%s: %f %f", axis.name,
+                                            gamepads.axis(i, axis.id),
+                                            gamepads.axisDelta(i, axis.id)
+                                );
+
+                            }
+                            ImGui::TreePop();
+                        }
+
+                    }
+
+                    ImGui::TreePop();
+                    ImGui::Separator();
+                }
+
+            }
+            ImGui::End();
+        }
 
 		//
 		// render step
diff --git a/fggl/data/storage.hpp b/fggl/data/storage.hpp
index a9636423418c0fd3e2d166c335878231a4bc3043..9e2ba223128143086546dc552e91e9cfc04d08e9 100644
--- a/fggl/data/storage.hpp
+++ b/fggl/data/storage.hpp
@@ -21,10 +21,9 @@ namespace fggl::data {
 			bool load(StorageType pool, const std::string& name, T* out) {
 				auto path = resolvePath(pool, name);
 				if ( !std::filesystem::exists(path) ) {
-					std::cerr << "path does not exist! " << path << std::endl;
+					std::cerr << "path " << path << " does not exist! " << std::endl;
 					return false;
 				}
-
 				return fggl_deserialize<T>(path, out);
 			}
 
@@ -39,7 +38,7 @@ namespace fggl::data {
 
 				switch ( pool ) {
 					case Data:
-						path = std::filesystem::current_path() / "res";
+						path = std::filesystem::current_path() / "data";
 						break;
 					case User:
 						path = "./user-data/";
diff --git a/fggl/debug/debug.cpp b/fggl/debug/debug.cpp
index a9117e0f322735a0d89a29a8febb1f32d86d9add..399fa2410ab879ebff89b24bf21d8af0573812c9 100644
--- a/fggl/debug/debug.cpp
+++ b/fggl/debug/debug.cpp
@@ -11,7 +11,10 @@ DebugUI::DebugUI(Window& win) : m_visible(false) {
 	IMGUI_CHECKVERSION();
 	ImGui::CreateContext();
 
-    	ImGui_ImplGlfw_InitForOpenGL(win.handle(), true);
+    ImGuiIO& io = ImGui::GetIO();
+    io.IniFilename = NULL;
+
+    ImGui_ImplGlfw_InitForOpenGL(win.handle(), true);
 	ImGui_ImplOpenGL3_Init("#version 130");
 }
 
diff --git a/fggl/ecs/component.hpp b/fggl/ecs/component.hpp
index 36e5a5f39809fe198535d3aa0b57d3c7f06d4b70..51edda314707ebb6c85ea6a8eccc110c35f5579e 100644
--- a/fggl/ecs/component.hpp
+++ b/fggl/ecs/component.hpp
@@ -5,6 +5,7 @@
 
 #include <cassert>
 #include <cstring>
+#include <string>
 #include <new>
 #include <utility>
 
@@ -18,11 +19,19 @@ namespace fggl::ecs {
 			using data_t = unsigned char;
 			virtual ~ComponentBase() {};
 
+            // in place
 			virtual void destroy(data_t* data) const = 0;
 			virtual void move(data_t* src, data_t* dest) const = 0;
 			virtual void bulkMove(data_t* src, data_t* dest, std::size_t count) = 0; 
 			virtual void construct(data_t* data) const = 0;
 
+            // virtual
+            virtual void* construct() const = 0;
+            virtual void* copyConstruct(const void* src) = 0;
+
+            virtual const char* name() const = 0;
+            virtual const component_type_t id() const = 0;
+
 			virtual std::size_t size() const = 0;
 	};
 
@@ -34,10 +43,27 @@ namespace fggl::ecs {
 				location->~C();
 			}
 
+            virtual const char* name() const override {
+                return C::name;
+            }
+
+            virtual const component_type_t id() const {
+                return Component<C>::typeID();
+            }
+
 			virtual void construct(unsigned char* data) const override {
 				new (data) C();
 			}
 
+            void* copyConstruct(const void* src) override {
+                const C* srcPtr = (C*)src;
+                return new C(*srcPtr);
+            }
+
+            void* construct() const override {
+                return new C();
+            }
+
 			virtual void move(data_t* src, data_t* dest) const override {
 				assert(src != nullptr);
 				assert(dest != nullptr);
diff --git a/fggl/ecs3/prototype/world.h b/fggl/ecs3/prototype/world.h
index 52000ee3ce550a737e315a5b33c0001b90c6a6af..74b59b2463ef0e53912f4c25b5d7062b05b06946 100644
--- a/fggl/ecs3/prototype/world.h
+++ b/fggl/ecs3/prototype/world.h
@@ -18,7 +18,12 @@ namespace fggl::ecs3::prototype {
 
     class Entity {
         public:
-            Entity(entity_t id) : m_id() {};
+            bool m_abstract;
+
+            explicit Entity(entity_t id) : m_id(id), m_abstract(false) {};
+            Entity(const Entity& entity) : m_id(entity.m_id), m_components(entity.m_components) {
+                std::cerr << "someone be doing one of them copy things: " << m_id << std::endl;
+            }
             ~Entity() = default;
 
             template<typename C>
@@ -28,6 +33,12 @@ namespace fggl::ecs3::prototype {
                 return ptr;
             }
 
+            void* add(std::shared_ptr<ComponentBase> t) {
+                void* ptr = t->construct();
+                m_components[t->id()] = ptr;
+                return ptr;
+            }
+
             template<typename C>
             C* set(const C* ptr) {
                 C* newPtr = new C(*ptr);
@@ -35,12 +46,30 @@ namespace fggl::ecs3::prototype {
                 return newPtr;
             }
 
+            void* set(const std::shared_ptr<ComponentBase>& t, const void* ptr) {
+                void* newPtr = t->copyConstruct(ptr);
+                m_components[t->id()] = newPtr;
+                return newPtr;
+            }
+
             template<typename C>
             C* get() {
                 void* ptr = m_components.at(Component<C>::typeID());
                 return (C*)ptr;
             }
 
+            inline void* get(component_type_t t){
+                return m_components.at(t);
+            }
+
+            std::vector<component_type_t> getComponentIDs() {
+                std::vector<component_type_t> comps{};
+                for (auto& [k,_] : m_components) {
+                    comps.push_back(k);
+                }
+                return comps;
+            }
+
             bool hasComponents(std::vector<component_type_t>& Cs) {
                 for (auto c : Cs) {
                     if ( m_components.find(c) == m_components.end() ) {
@@ -58,20 +87,59 @@ namespace fggl::ecs3::prototype {
 
     class World {
         public:
-            World(TypeRegistry& reg) : m_types(reg), m_next(0), m_entities() {};
+            explicit World(TypeRegistry& reg) : m_types(reg), m_next(1), m_entities() {};
             ~World() = default;
 
-            entity_t create() {
+            entity_t create(bool abstract) {
                 auto nextID = m_next++;
                 m_entities.emplace(nextID, nextID);
+
+                auto& entity = m_entities.at(nextID);
+                entity.m_abstract = abstract;
+
+                // meta data
+                auto* meta = entity.add<ecs3::EntityMeta>();
+                meta->id = nextID;
+                meta->abstract = abstract;
+
                 return nextID;
             }
 
+            entity_t copy(entity_t prototype) {
+                auto clone = create(false);
+
+                auto components = getComponents(prototype);
+                for (auto component : components) {
+                    auto protoComp = get(prototype, component);
+                    set(clone, component, protoComp);
+                }
+
+                return clone;
+            }
+
             void destroy(entity_t entity) {
                 // TOOD resolve and clean components
                 m_entities.erase(entity);
             }
 
+            std::vector<entity_t> all() {
+                std::vector<entity_t> entities{};
+                for( auto& [eid, entity] : m_entities) {
+                    entities.push_back(eid);
+                }
+                return entities;
+            }
+
+            std::vector<component_type_t> getComponents(entity_t entityID){
+                std::vector<component_type_t> components{};
+                auto& entity = m_entities.at(entityID);
+                auto comps = entity.getComponentIDs();
+                for (auto id : comps) {
+                    components.push_back(id);
+                }
+                return components;
+            }
+
             template<typename... Cs>
             std::vector<entity_t> findMatching() {
                 // construct the key
@@ -81,7 +149,7 @@ namespace fggl::ecs3::prototype {
                 // entities
                 std::vector<entity_t> entities{};
                 for( auto& [eid, entity] : m_entities) {
-                    if ( entity.hasComponents(key) ) {
+                    if ( entity.hasComponents(key) && !entity.m_abstract ) {
                         entities.push_back(eid);
                     }
                 }
@@ -91,19 +159,39 @@ namespace fggl::ecs3::prototype {
 
             template<typename C>
             C* add(entity_t entity_id) {
+                std::cerr << "[>>] adding comp " << C::name << " to " << entity_id << std::endl;
                 auto& entity = m_entities.at(entity_id);
                 auto comp = entity.template add<C>();
 
-                m_types.fireAdd(*this, entity_id, Component<C>::typeID());
+                m_types.fireAdd(this, entity_id, Component<C>::typeID());
                 return comp;
             }
 
+            void* add(entity_t entity_id, component_type_t component_id) {
+                auto meta = m_types.meta(component_id);
+                auto& entity = m_entities.at(entity_id);
+
+                void* ptr = entity.add(meta);
+                m_types.fireAdd(this, entity_id, meta->id());
+                return ptr;
+            }
+
             template<typename C>
             C* set(entity_t entity_id, const C* ptr) {
+                std::cerr << "[>>] setting comp " << C::name << " to " << entity_id << std::endl;
                 auto& entity = m_entities.at(entity_id);
                 auto comp = entity.set<C>(ptr);
 
-                m_types.fireAdd(*this, entity_id, Component<C>::typeID());
+                m_types.fireAdd(this, entity_id, Component<C>::typeID());
+                return comp;
+            }
+
+            void* set(entity_t entity_id, component_type_t cid, const void* ptr){
+                auto& entity = m_entities.at(entity_id);
+                auto cMeta = m_types.meta(cid);
+
+                auto comp = entity.set(cMeta, ptr);
+                m_types.fireAdd(this, entity_id, cid);
                 return comp;
             }
 
@@ -113,6 +201,11 @@ namespace fggl::ecs3::prototype {
                 return entity.get<C>();
             }
 
+            void* get(entity_t entity_id, component_type_t t){
+                auto& entity = m_entities.at(entity_id);
+                return entity.get(t);
+            }
+
         private:
             TypeRegistry& m_types;
             entity_t m_next;
diff --git a/fggl/ecs3/types.hpp b/fggl/ecs3/types.hpp
index 14aff893540ae694db026b72f96677e0c3169702..fb0fe4f2cc8f076ea00cb4325f29771d48f51a83 100644
--- a/fggl/ecs3/types.hpp
+++ b/fggl/ecs3/types.hpp
@@ -26,14 +26,16 @@ namespace fggl::ecs3 {
     using fggl::ecs::component_type_t;
     class ModuleManager;
 
-    using callback_t = std::function<void(prototype::World&, ecs3::entity_t)>;
+    using callback_t = std::function<void(prototype::World*, ecs3::entity_t)>;
     struct TypeCallbacks {
         std::vector<callback_t> add;
     };
 
     // core component types
     struct EntityMeta {
+        constexpr static const char name[] = "meta";
         entity_t id;
+        bool abstract;
     };
 
     struct RecordIdentifier {
@@ -175,6 +177,15 @@ namespace fggl::ecs3 {
 				return m_types.at( type_id );
 			}
 
+            inline component_type_t find(const char* name) const {
+                for (auto& [type, meta] : m_types) {
+                    if ( std::strcmp(name, meta->name()) == 0) {
+                        return type;
+                    }
+                }
+                return 0;
+            }
+
 			inline void make_virtual(std::shared_ptr<ComponentBase> vtype) {
 				auto type_id = m_last_virtual++;
 				m_types[type_id] = std::move(vtype);
@@ -184,10 +195,14 @@ namespace fggl::ecs3 {
                 m_callbacks[component].add.push_back(callback);
             }
 
-            void fireAdd(prototype::World& world, entity_t entity, component_type_t type) {
-                auto& callbacks = m_callbacks[type].add;
-                for ( auto& callback : callbacks) {
-                    callback(world, entity);
+            void fireAdd(prototype::World* world, entity_t entity, component_type_t type) {
+                try {
+                    auto& callbacks = m_callbacks.at(type).add;
+                    for ( auto& callback : callbacks) {
+                        callback(world, entity);
+                    }
+                } catch ( std::out_of_range& e) {
+                    std::cerr << "no callbacks for: " << m_types[type]->name() << std::endl;
                 }
             }
 
diff --git a/fggl/gfx/camera.hpp b/fggl/gfx/camera.hpp
index 0e0a48e27de0513e6a38865ba0faa4071474fe92..c1eaa43bb7d7aeca073be30b320ed0294fd8cd12 100644
--- a/fggl/gfx/camera.hpp
+++ b/fggl/gfx/camera.hpp
@@ -6,6 +6,7 @@
 namespace fggl::gfx {
 
 	struct Camera {
+        constexpr const static char name[] = "Camera";
 		math::vec3 target = math::vec3(0.0f, 0.0f, 0.0f);
 		float aspectRatio = 1280.0f / 720.0f;
 		float fov = glm::radians(45.0f);
diff --git a/fggl/gfx/common.hpp b/fggl/gfx/common.hpp
index c8376f3477814d66968fd01eb0159437262906ce..71101f5c5c5702cae023cfd6b954977864f31816 100644
--- a/fggl/gfx/common.hpp
+++ b/fggl/gfx/common.hpp
@@ -14,6 +14,7 @@
 namespace fggl::gfx {
 
 	struct StaticMesh {
+        constexpr static const char name[] = "StaticMesh";
 		data::Mesh mesh;
 		std::string pipeline;
 
diff --git a/fggl/gfx/ogl/compat.hpp b/fggl/gfx/ogl/compat.hpp
index d84a05ee209fae9e635002119d6adfd43c0eae4b..fd761c62bf38044fc31ab4b82c22ca4780694405 100644
--- a/fggl/gfx/ogl/compat.hpp
+++ b/fggl/gfx/ogl/compat.hpp
@@ -36,15 +36,14 @@ namespace fggl::gfx {
             return "gfx::opengl";
         }
 
-        void uploadMesh(ecs3::World& world, ecs::entity_t entity) {
-            std::cerr << "[!!] I be firein me shaders!" << std::endl;
-            auto meshData = world.get<gfx::StaticMesh>(entity);
+        void uploadMesh(ecs3::World* world, ecs::entity_t entity) {
+            auto meshData = world->get<gfx::StaticMesh>(entity);
 
             auto pipeline = cache.get(meshData->pipeline);
             auto glMesh = renderer.upload(meshData->mesh);
 
             glMesh.pipeline = pipeline;
-            world.set<fggl::gfx::GlRenderToken>(entity, &glMesh);
+            world->set<fggl::gfx::GlRenderToken>(entity, &glMesh);
         }
 
         void onLoad(ecs3::ModuleManager& manager, ecs3::TypeRegistry& types) override {
@@ -84,7 +83,8 @@ namespace fggl::gfx {
 	//
 	// fake module/callbacks - our ECS doesn't have module/callback support yet.
 	// 
-	inline void onStaticMeshAdded(ecs3::World& ecs, ecs::entity_t entity, OglModule& mod) {
+	void onStaticMeshAdded(ecs3::World& ecs, ecs::entity_t entity, OglModule& mod) {
+        std::cerr << "[CALLBACK] static mesh added, renderable?" << std::endl;
         /*
 		auto meshData = ecs.get<gfx::StaticMesh>(entity);
 		auto pipeline = mod->cache.get(meshData->pipeline);
@@ -106,6 +106,7 @@ namespace fggl::gfx {
 
 		// get the models
 		auto renderables = ecs.findMatching<fggl::gfx::GlRenderToken>();
+
 		for ( auto renderable : renderables ) {
 			mod->renderer.render(ecs, camera, dt);
 		}
diff --git a/fggl/gfx/ogl/renderer.cpp b/fggl/gfx/ogl/renderer.cpp
index 0e8e9833250ed5b3dccd2f0d609c85a4d6520b64..eff7e8e9cdf06b7a1712c54a0d9d6f2dd2175003 100644
--- a/fggl/gfx/ogl/renderer.cpp
+++ b/fggl/gfx/ogl/renderer.cpp
@@ -48,7 +48,7 @@ static GLuint createIndexBuffer(std::vector<uint32_t>& indexData) {
 }
 
 GlRenderToken MeshRenderer::upload(fggl::data::Mesh& mesh) {
-	GlRenderToken token;
+	GlRenderToken token{};
 	glGenVertexArrays(1, &token.vao);
 	glBindVertexArray(token.vao);
 
@@ -67,10 +67,16 @@ GlRenderToken MeshRenderer::upload(fggl::data::Mesh& mesh) {
 }
 
 void MeshRenderer::render(fggl::ecs3::World& ecs, ecs3::entity_t camera, float dt) {
-    if ( camera == ecs::NULL_ENTITY ) return;
+    if ( camera == ecs::NULL_ENTITY ){
+        std::cerr << "no camera" << std::endl;
+        return;
+    }
 
     auto entities = ecs.findMatching<GlRenderToken>();
-    if ( entities.size() == 0 ) return;
+    if ( entities.empty() ) {
+        std::cerr << "no entities with render tokens" << std::endl;
+        return;
+    }
 
     total += dt;
 
diff --git a/fggl/gfx/ogl/renderer.hpp b/fggl/gfx/ogl/renderer.hpp
index 59320689b906025f2dc67565a3639b140d1081bc..b13647f27a844bc007f27776d809f322843b137f 100644
--- a/fggl/gfx/ogl/renderer.hpp
+++ b/fggl/gfx/ogl/renderer.hpp
@@ -10,6 +10,7 @@
 namespace fggl::gfx {
 
 	struct GlRenderToken {
+        constexpr static const char name[] = "RenderToken";
 		GLuint vao;
 		GLuint buffs[2];
 		GLuint idxOffset;
diff --git a/fggl/gfx/ogl/shader.cpp b/fggl/gfx/ogl/shader.cpp
index 3d91705128c03b2e41c8d2fe19e5a5049dc6ccf3..c3558de127c555dd03b1a231b3cb83d6abcc65cb 100644
--- a/fggl/gfx/ogl/shader.cpp
+++ b/fggl/gfx/ogl/shader.cpp
@@ -10,9 +10,12 @@ bool ShaderCache::compileShader(const std::string& fname, GLuint sid) {
 	std::string source;
 	bool result = m_storage.load(fggl::data::Data, fname, &source);
 	if ( !result ) {
+        std::cerr << ">> Error loading file: " << fname << std::endl;
 		return false;
 	}
 
+    std::cerr << "source for " << fname << " is " << source << std::endl;
+
 	// upload and compile shader
 	const auto *src_cstr = (const GLchar *)source.c_str();
 	glShaderSource(sid, 1, &src_cstr, 0);
@@ -85,6 +88,8 @@ GLuint ShaderCache::get(const std::string& name) {
 
 GLuint ShaderCache::load(const ShaderConfig& config) {
 
+    std::cerr << "Starting program generation: " << config.name << std::endl;
+
 	GLuint pid = glCreateProgram();
 
 	if ( m_binary ) {
@@ -95,7 +100,7 @@ GLuint ShaderCache::load(const ShaderConfig& config) {
 			return pid;
 		}
 
-		std::cerr << "could not load cached shader, taking the long route" << std::endl;
+		std::cerr << ">> could not load cached shader, taking the long route" << std::endl;
 	}
 
 	// TODO actual shader loading
diff --git a/fggl/math/types.hpp b/fggl/math/types.hpp
index e4b3c4612651aef354fd78c2446cc701cdbf2a15..0f75cf67aaf163e0d9a0cc4dac6539175abea92b 100644
--- a/fggl/math/types.hpp
+++ b/fggl/math/types.hpp
@@ -32,6 +32,7 @@ namespace fggl::math {
 	}
 
 	struct Transform {
+        constexpr static const char name[] = "Transform";
 
 		Transform() : m_local(1.0f), m_origin(0.0f), m_model(1.0f), m_rotation() {
 		}
diff --git a/tests/testfggl/ecs/ecs.cpp b/tests/testfggl/ecs/ecs.cpp
index ed8ab1b5423b8577b083dba3449e133cfb9fa0a5..86c4e3ef118945bef203833300dba2064edbc7bf 100644
--- a/tests/testfggl/ecs/ecs.cpp
+++ b/tests/testfggl/ecs/ecs.cpp
@@ -7,15 +7,19 @@ using fggl::ecs::Component;
 
 namespace {
 
-	class DummyComp1 : public Component<DummyComp1> {
+	class DummyComp1 {
+		public:
+			constexpr static const char* name = "DummyComp1";
 	};
 
-	class DummyComp2 : public Component<DummyComp2> {
+	class DummyComp2 {
 		public:
+			constexpr static const char* name = "DummyComp2";
 			int x;
 			DummyComp2() : x(0) {}
 			DummyComp2(int tmp) : x(tmp) {
 			}
+			DummyComp2( const DummyComp2& other) : x(other.x) {}
 			DummyComp2( DummyComp2&& other ) : x(other.x) {}
 	};
 
diff --git a/tests/testfggl/ecs3/ecs.cpp b/tests/testfggl/ecs3/ecs.cpp
index 74d5cab30598ec2a5b020cddf062b6d6fdb762db..e5689c1077b61efc880a8a6eff92975b00905f2d 100644
--- a/tests/testfggl/ecs3/ecs.cpp
+++ b/tests/testfggl/ecs3/ecs.cpp
@@ -8,17 +8,21 @@ using fggl::ecs::Component;
 namespace {
 
 	class DummyComp4 {
-        bool a;
-        bool b;
-        bool c;
+		public:
+			constexpr static const char* name = "DummyComp2";
+			bool a;
+			bool b;
+			bool c;
 	};
 
 	class DummyComp3 {
 		public:
+			constexpr static const char* name = "DummyComp2";
 			int x;
 			DummyComp3() = default;
 			DummyComp3(int tmp) : x(tmp) {
 			}
+			DummyComp3( const DummyComp3& other ) : x(other.x) {}
 			DummyComp3( DummyComp3&& other ) : x(other.x) {}
 	};