diff --git a/source/main.cpp b/source/main.cpp
index 4d22cc05a393616df0bf2bc6f8e2c57368cd5dba..e9cfcd008182c3ef255c3825b838d96cb61b66bd 100644
--- a/source/main.cpp
+++ b/source/main.cpp
@@ -12,8 +12,8 @@
 #include "digit_display.h"
 #include "timer.h"
 
-const std::chrono::steady_clock::duration max_duration = 99h + 59min + 59s;
-const std::chrono::steady_clock::duration min_duration{};
+// const std::chrono::steady_clock::duration max_duration = 99h + 59min + 59s;
+// const std::chrono::steady_clock::duration min_duration{};
 
 struct nothing {};
 using movement = motion::movement<std::chrono::steady_clock::duration, nothing, nothing>;
@@ -98,12 +98,12 @@ int main(int argc, const char** argv) try
 	auto current_timer = motion::symphony{support::make_range(timers)};
 	bool paused = true;
 
-	ui_shop ui{ ui_factory<i_ui_object, i_graphic, i_interactive>{} };
+	entities ui{ components<object_interface<i_ui_object, i_graphic, i_interactive>>{} };
 
 	rect button_rect{win.size()/8 + int2{5,5}};
 	auto make_control_button = [&]() -> auto&
 	{
-		auto& button = ui.make<plain_button>(fg_color, button_rect);
+		auto& button = ui.emplace<plain_button>(fg_color, button_rect);
 		return button;
 	};
 	auto& stop_button = make_control_button();
@@ -135,14 +135,14 @@ int main(int argc, const char** argv) try
 	auto make_timer_ui = [&ui, &fg_color, &focus_handler]()
 	{
 		auto [hours_display, minutes_display, seconds_display] =
-			ui.make_order([&](auto& factory)
+			ui.make([&](auto& components)
 		{
 			int2 digit_size{40,100};
 			auto digit_spacing = int2::i(5);
 			auto make_time_display = [&]() -> auto&
 			{
 				// oof, template -_-
-				auto& display = factory.template make<digit_display<>>(digit_size, digit_spacing, fg_color);
+				auto& display = components.template emplace<digit_display<>>(digit_size, digit_spacing, fg_color);
 				return display;
 			};
 			return std::tie
@@ -151,7 +151,7 @@ int main(int argc, const char** argv) try
 				make_time_display(),
 				make_time_display()
 			);
-		}).goods;
+		}).components;
 
 		hours_display.on_press.push_back(focus_handler);
 		minutes_display.on_press.push_back(focus_handler);
@@ -161,9 +161,9 @@ int main(int argc, const char** argv) try
 		bounds_layout timer_layout(
 			{
 				&hours_display,
-				&ui.make<digit_bitmap>(digit[10], fg_color, separator_rect),
+				&ui.emplace<digit_bitmap>(digit[10], fg_color, separator_rect),
 				&minutes_display,
-				&ui.make<digit_bitmap>(digit[10], fg_color, separator_rect),
+				&ui.emplace<digit_bitmap>(digit[10], fg_color, separator_rect),
 				&seconds_display
 			},
 			int2::i(5)
@@ -274,14 +274,14 @@ int main(int argc, const char** argv) try
 						main_layout.elements.push_back(&layout);
 						main_layout.update();
 
-						h.on_input.push_back([&timer, &h](auto&&, int old_value, int new_value)
+						h.on_input.push_back([&timer](auto&&, int old_value, int new_value)
 						{
 							using namespace std::chrono;
 							auto offset = hours(new_value) - hours(old_value);
 							timer.reset();
 							timer.total = timer.total - timer.elapsed + offset;
 						});
-						m.on_input.push_back([&timer, &m](auto&&, int old_value, int new_value)
+						m.on_input.push_back([&timer](auto&&, int old_value, int new_value)
 						{
 							using namespace std::chrono;
 							auto new_minutes = minutes(new_value);
@@ -291,7 +291,7 @@ int main(int argc, const char** argv) try
 							timer.reset();
 							timer.total = timer.total - timer.elapsed + offset;
 						});
-						s.on_input.push_back([&timer, &s](auto&&, int old_value, int new_value)
+						s.on_input.push_back([&timer](auto&&, int old_value, int new_value)
 						{
 							using namespace std::chrono;
 							auto new_seconds = seconds(new_value);
@@ -307,7 +307,7 @@ int main(int argc, const char** argv) try
 				[](auto) { }
 			}, *event);
 
-			for(auto&& interactive : ui.get<i_interactive>())
+			for(auto&& interactive : ui.get<i_interactive*>())
 				interactive->update(*event);
 		}
 
@@ -331,7 +331,7 @@ int main(int argc, const char** argv) try
 
 		fill(win.surface(), bg_color);
 
-		for(auto&& graphic : ui.get<i_graphic>())
+		for(auto&& graphic : ui.get<i_graphic*>())
 			graphic->draw(win.surface());
 		win.update();
 
diff --git a/source/ui_factory.hpp b/source/ui_factory.hpp
index 95aea9b4aa4e94312bebfde86f11dbb1790da41b..a74cf063f6c4e13b9ef3d3450bc3876cf24302bf 100644
--- a/source/ui_factory.hpp
+++ b/source/ui_factory.hpp
@@ -6,180 +6,281 @@
 
 #include "simple/support/tuple_utils.hpp"
 
-//TODO; nothing UI here anymore... also not really a factory and not really a shop... rename all the things!
 
 template <typename... Interfaces>
-class ui_shop;
+class entities;
+
+using simple::support::flatten_t;
+using simple::support::flatten_meta_operator;
+
+template <typename T, T Offset, T... Is>
+constexpr auto offset_sequence(std::integer_sequence<T,Is...>)
+{
+	return std::integer_sequence<T, (Is + Offset)...>{};
+}
+
+template <typename T, T begin, T size>
+constexpr auto make_integer_segment()
+{
+	return offset_sequence<T, begin>(std::make_integer_sequence<T, size>{});
+}
 
 template <typename Base, typename... Interfaces>
-class pointer_interface;
-
-// TODO: is lists of components, so call components
-// specify types of components
-// component type is either a value type or pointer_interface
-// value type just created and stored in appropriate vector
-// pointer_interface handled like below
-template <typename Type, typename... Interfaces>
-class ui_factory
+// TODO: enable if is_abstract<Base> && has_virtual_destructor<Base>
+// and maybe is_abstract<Interfaces>, but not sure
+struct object_interface
+{
+	static constexpr size_t type_count = 1 + sizeof...(Interfaces);
+};
+
+// TODO: parameterise std::unique_ptr and std::vector templates?? do I need that within a project or between projects, cause in a latter case can get away with using declaration in a configuration header
+template <typename... Types>
+class components
 {
 	public:
 
-	using type = Type;
+	using types = std::tuple<Types...>;
 
 	template <typename Element, typename ...Args>
-	Element& make(Args&&... args)
+	Element& emplace(Args&&... args)
 	{
-		using namespace simple::support;
-		auto& elements = tuple_car(interfaces);
-		auto element = std::make_unique<Element>(std::forward<Args>(args)...);
-		Element& raw = *element.get();
+		using simple::support::find_meta_t;
+		using simple::support::bind_meta;
+		using simple::support::tuple_car;
+		using simple::support::tuple_car_t;
+		using simple::support::tuple_tie_cdr;
+		using simple::support::tie_subtuple;
+		using simple::support::is_template_instance_v;
+
+		using found = find_meta_t<bind_meta<is_component, size_constant<0>, Element>, types>;
+		static_assert(found::value != std::tuple_size_v<types>, "Element type not found in known component list.");
+		if constexpr (is_template_instance_v<object_interface, typename found::type>)
+		{
+			auto object_vectors = tie_subtuple(vectors,
+				make_integer_segment<size_t,
+					typename found::functor::binding{},
+					found::type::type_count
+				>()
+			);
+
+			// get the tuple of the pointer interface and do this
+			auto& elements = tuple_car(object_vectors);
 
-		add_interface(raw, tuple_tie_cdr(interfaces));
+			auto element = std::make_unique<Element>(std::forward<Args>(args)...);
+			Element& raw = *element.get();
 
-		elements.push_back(std::move(element)); // assuming raw pointer will not change... that's safe right?
-		return raw;
+			add_interface(raw, tuple_tie_cdr(object_vectors));
+
+			elements.emplace_back(std::move(element)); // assuming raw pointer will not change... that's safe right?
+			return raw;
+		}
+		else
+		{
+			return std::get<found::value>().emplace_back(std::forward<Args>(args)...);
+		}
 	}
 
 	// TODO: return a range
-	template <typename Interface>
+	template <typename Component>
 	const auto& get() const noexcept
 	{
-		using ptr_t = std::conditional_t<std::is_same_v<Interface, type>,
-			  std::unique_ptr<type>,
-			  Interface*>;
-		return std::get<std::vector<ptr_t>>(interfaces);
+		using simple::support::find_v;
+		return std::get<find_v<Component, flat_types>>(vectors);
 	}
 
 	private:
 
-	template <typename... T>
-	using container = std::tuple< std::vector<T> ... >;
-	template <typename... T>
-	using container_ref = std::tuple< std::vector<T>& ... >;
+	template <typename T>
+	struct flatten_object_interface : flatten_meta_operator<T> {};
+	template <typename Base, typename... Interfaces>
+	struct flatten_object_interface<object_interface<Base, Interfaces...>>
+	{
+		using type = std::tuple<std::unique_ptr<Base>, Interfaces*...>;
+	};
 
-	container<
-		std::unique_ptr<type>,
-		Interfaces* ...
-	> interfaces;
+	template <size_t i> using size_constant = std::integral_constant<size_t, i>;
 
+	template <typename flat_index, typename T, typename Component>
+	struct is_component : std::is_same<T,Component>
+	{
+		using binding = size_constant<flat_index{} + !is_component::value>;
+	};
+
+	template <typename flat_index, typename T, typename Base, typename... Interfaces>
+	struct is_component<flat_index, T, object_interface<Base,Interfaces...>>
+	{
+		static constexpr bool value = std::is_base_of_v<Base, T>;
+		static constexpr size_t increment =
+			[](bool value)
+			{
+				return value
+					? 0
+					: object_interface<Base,Interfaces...>::type_count
+				;
+			}
+			(is_component::value);
+		using binding = size_constant<flat_index{} + increment>;
+	};
+
+	using flat_types = flatten_t<types,flatten_object_interface>;
+
+	template <typename Tuple, bool ref = false>
+	struct container { };
+
+	template <typename... Ts>
+	struct container<std::tuple<Ts...>, false>
+	{
+		using type = std::tuple<std::vector<Ts>...>;
+	};
+
+	template <typename... Ts>
+	struct container<std::tuple<Ts...>, true>
+	{
+		using type = std::tuple<std::vector<Ts>&...>;
+	};
+
+	template <typename Tuple>
+	using container_t = typename container<Tuple>::type;
+
+	template <typename... Ts>
+	using container_ref_t = typename container<std::tuple<Ts...>, true>::type;
 
 	template <typename El>
 	void add_interface(El&, std::tuple<>){}
 
 	template <typename El, typename In, typename... Rest>
-	void add_interface(El& element, container_ref<In*, Rest...> interfaces)
+	// NOTE: the shorthand can't deduce the In :/
+	// void add_interface(El& element, container_ref_t<In*, Rest...> interfaces)
+	void add_interface(El& element, std::tuple<std::vector<In*>&, std::vector<Rest>&...> interfaces)
 	{
-		using namespace simple::support;
+		using simple::support::tuple_car;
+		using simple::support::tuple_tie_cdr;
 		if constexpr (std::is_base_of_v<In, El>)
 			tuple_car(interfaces).push_back(&element);
 		add_interface(element,tuple_tie_cdr(interfaces));
 	}
 
-	friend class ui_shop<Type, Interfaces...>;
-};
+	container_t<flat_types> vectors;
 
+	friend class entities<Types...>;
+};
 
-// TODO: groups components into entities, so call entities
-template <typename... Interfaces>
-class ui_shop
+template <typename... Components>
+class entities
 {
 	public:
 
-	// TODO: rename reciept to entity
-	using receipt_id_t = unsigned;
+	using entity_id_t = unsigned;
 
-	ui_shop(ui_factory<Interfaces...> supplier) :
-		supplier(std::move(supplier))
+	entities(components<Components...> components) :
+		_components(std::move(components))
 	{
 	}
 
-	// TODO: rename order to entity, rename goods to components
-	template <typename Goods>
-	struct order
+	template <typename T>
+	struct entity
 	{
 		public:
-		Goods goods;
-		const receipt_id_t receipt_id;
+		T components;
+		const entity_id_t entity_id;
 
 		private:
-		order(Goods&& goods, const receipt_id_t& receipt_id) :
-			goods(std::forward<Goods>(goods)),
-			receipt_id(receipt_id)
+		entity(T&& components, const entity_id_t& entity_id) :
+			components(std::forward<T>(components)),
+			entity_id(entity_id)
 		{}
-		friend class ui_shop;
+		friend class entities;
 	};
 
 	// TODO: getter of components based on entity ids
 
+	// TODO; eplace specific components to replace the make function below,
+	// component type1, args1
+	// component_type2, args2
+	// ...
+	// component_typeN, argsN
+	//
+	// maybe use a component helper template, so it looks like this:
+	// entities.emplace
+	// (
+	//   component<Type1>(args1...),
+	//   component<Type2>(args2...),
+	//   component<Type3>(args3...),
+	//   component<Type4>(args4...),
+	// );
+	// can also sfinae on this helper template.
+	//
+	// return a predictable entity object with references to all components and the id
+
 	template <typename Function>
-	order<std::invoke_result_t<
-		Function, ui_factory<Interfaces...>&>>
-	make_order(Function&& function)
+	entity<std::invoke_result_t<
+		Function, components<Components...>&>>
+	make(Function&& function)
 	{
 		using simple::support::transform;
 		auto size = transform([](const auto& x) {return x.size(); },
-			supplier.interfaces);
+			_components.vectors);
 
-		auto&& goods = std::invoke(
+		auto&& product = std::invoke(
 			std::forward<Function>(function),
-			supplier);
+			_components);
 
-		receipt_ids.push_back(get_id());
+		entity_ids.push_back(get_id());
 
-		transform([](auto& receipt_size, auto size, const auto& interface)
+		transform([](auto& entity_size, auto size, const auto& interface)
 		{
-			receipt_size.push_back(interface.size() - size);
-		}, receipt_sizes, size, supplier.interfaces);
+			entity_size.push_back(interface.size() - size);
+		}, entity_sizes, size, _components.vectors);
 
 		return
 		{
-			std::forward<decltype(goods)>(goods),
-			receipt_ids.back()
+			std::forward<decltype(product)>(product),
+			entity_ids.back()
 		};
 	};
 
 	template <typename Element, typename ...Args>
-	Element& make(Args&&... args)
+	Element& emplace(Args&&... args)
 	{
-		return make_order([&](auto& factory) -> auto&
+		return make([&](auto& components) -> auto&
 		{
 			return
-				factory.template make<Element>
+				components.template emplace<Element>
 					(std::forward<Args>(args)...);
-		}).goods;
+		}).components;
 	}
 
-	bool recycle(receipt_id_t id)
+	bool erase(entity_id_t id)
 	{
 		auto found = lower_bound
 		(
-			begin(receipt_ids),
-			end(receipt_ids),
+			begin(entity_ids),
+			end(entity_ids),
 			id
 		);
 
-		if(found != end(receipt_ids))
+		if(found != end(entity_ids))
 		{
 			using simple::support::transform;
-			transform([&](auto& interfaces, auto& sizes)
+			transform([&](auto& components, auto& sizes)
 			{
-				auto size_begin = begin(receipt_sizes);
+				auto size_begin = begin(entity_sizes);
 				auto found_size = size_begin +
-					(found - begin(receipt_ids));
+					(found - begin(entity_ids));
 
-				auto goods_begin = begin(interfaces) +
+				auto components_begin = begin(components) +
 					accumulate(size_begin, found_size, 0);
-				interfaces.erase
+				components.erase
 				(
-					goods_begin,
-					goods_begin + *found_size
+					components_begin,
+					components_begin + *found_size
 				);
 
 
 				sizes.erase(found_size);
-			}, supplier.interfaces, receipt_sizes);
+			}, _components.components, entity_sizes);
 
-			receipt_ids.erase(found);
+			entity_ids.erase(found);
 			return true;
 		}
 
@@ -188,28 +289,29 @@ class ui_shop
 
 	template <typename Interface>
 	decltype(auto) get() const noexcept
-	{ return supplier.template get<Interface>(); }
+	{ return _components.template get<Interface>(); }
 
 	private:
 
-	using receipt_size_t = unsigned short;
+	using entity_size_t = unsigned short;
 
-	receipt_id_t get_id()
+	entity_id_t get_id()
 	{
-		if(empty(receipt_ids))
+		if(empty(entity_ids))
 			return 0;
-		return receipt_ids.back() + 1; //TODO: what if we run out?
+		return entity_ids.back() + 1; //TODO: what if we run out?
 		// but it'll take like two hundred bajillion years D':
 		// yes, what will this program do after two hundred bajillion years of runtime?
 		// reuse ids? do I smell std::rotate? =)
 	}
 
-	ui_factory<Interfaces...> supplier;
-	std::vector<receipt_id_t> receipt_ids;
+	using components_t = components<Components...>;
+	components_t _components;
+	std::vector<entity_id_t> entity_ids;
 	std::array<
-		std::vector<receipt_size_t>,
-		sizeof...(Interfaces) + 1
-	> receipt_sizes;
+		std::vector<entity_size_t>,
+		std::tuple_size_v<typename components_t::flat_types>
+	> entity_sizes;
 };