diff --git a/demo/demo/main.cpp b/demo/demo/main.cpp
index 5c6729b726759538f1a236ede2f5d23e339af2f2..109fd0e87c85582d39eb4db05ee7d27449c3fb91 100644
--- a/demo/demo/main.cpp
+++ b/demo/demo/main.cpp
@@ -39,6 +39,7 @@
 
 #include "fggl/data/assimp/module.hpp"
 #include "fggl/assets/module.hpp"
+#include "fggl/assets/packed/module.hpp"
 #include "fggl/script/lua/module.hpp"
 
 #include "GameScene.h"
@@ -59,7 +60,7 @@ static void setup_menu(fggl::App& app) {
 
 		menu->add(labels.at(i), [&app, sceneName]() {
 			auto* audio = app.service<fggl::audio::AudioService>();
-			audio->play("click.ogg", false);
+			audio->play("ui/click.ogg", false);
 			app.change_state(sceneName);
 		});
 	}
@@ -82,6 +83,7 @@ int main(int argc, const char* argv[]) {
 	moduleManager.use<fggl::gfx::OpenGL4>();
 	moduleManager.use<fggl::display::GLFW>();
 	moduleManager.use<fggl::assets::AssetFolders>();
+	moduleManager.use<fggl::assets::PackedAssets>();
 	moduleManager.use<fggl::entity::ECS>();
 	moduleManager.use<fggl::script::Lua>();
 
@@ -98,11 +100,15 @@ int main(int argc, const char* argv[]) {
 	// create the application
 	fggl::App app( &moduleManager, "fggl-demo" );
 
+	auto* assetFinder = app.service<fggl::assets::CheckinAdapted>();
+	assetFinder->discover("core");
+	assetFinder->discover("viewer");
+
 	// force asset loading
 	{
 		auto* assets = app.service<fggl::assets::AssetManager>();
 		auto* loader = app.service<fggl::assets::Loader>();
-		loader->load("click.ogg", fggl::audio::OGG_VORBIS, assets);
+		loader->load("ui/click.ogg", fggl::audio::OGG_VORBIS, assets);
 	}
 
 	auto* windowing = app.service<fggl::display::WindowService>();
diff --git a/demo/demo/models/viewer.cpp b/demo/demo/models/viewer.cpp
index bf7b3ebababdb36e212537ee2a47e5c0ce56e754..e073c29fce609c378f8b0ed8babb955767399ae6 100644
--- a/demo/demo/models/viewer.cpp
+++ b/demo/demo/models/viewer.cpp
@@ -113,7 +113,7 @@ namespace demo {
 		auto *loader = owner().service<fggl::assets::Loader>();
 		auto *manager = owner().service<fggl::assets::AssetManager>();
 
-		loader->load("backpack/backpack.obj", fggl::data::models::ASSIMP_MODEL, manager);
+		loader->load("backpack/backpack.obj", fggl::data::models::ASSIMP_MODEL, manager, "viewer");
 
 		// create camera
 		setup_camera(world());
diff --git a/fggl/assets/CMakeLists.txt b/fggl/assets/CMakeLists.txt
index d057f9945c730f3879fbdacfca19c020cf456921..d39a51326aa6d384a1155b3d3fb5e2ad4bec1a82 100644
--- a/fggl/assets/CMakeLists.txt
+++ b/fggl/assets/CMakeLists.txt
@@ -1,3 +1,4 @@
 target_sources(fggl PRIVATE
         module.cpp
-        )
\ No newline at end of file
+        packed/module.cpp
+)
\ No newline at end of file
diff --git a/fggl/assets/module.cpp b/fggl/assets/module.cpp
index 5c25dacde21d820fb5bd9a2f9b0f6da1b4fdf1ae..e56972a325f9f392384cc883785fe9a68b36208d 100644
--- a/fggl/assets/module.cpp
+++ b/fggl/assets/module.cpp
@@ -23,7 +23,8 @@ namespace fggl::assets {
 	bool AssetFolders::factory(modules::ModuleService service, modules::Services &services) {
 		if (service == Loader::service) {
 			auto storage = services.get<data::Storage>();
-			services.create<Loader>(storage);
+			auto checkin = services.get<CheckinAdapted>();
+			services.create<Loader>(storage, checkin);
 			return true;
 		}
 		if (service == AssetManager::service) {
diff --git a/fggl/assets/packed/module.cpp b/fggl/assets/packed/module.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3a5646923b4069f10d17ad2f62957651be89ccf0
--- /dev/null
+++ b/fggl/assets/packed/module.cpp
@@ -0,0 +1,37 @@
+/*
+ * This file is part of FGGL.
+ *
+ * FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with FGGL.
+ * If not, see <https://www.gnu.org/licenses/>.
+ */
+
+//
+// Created by webpigeon on 20/08/22.
+//
+
+#include "fggl/assets/packed/module.hpp"
+
+namespace fggl::assets {
+
+	bool PackedAssets::factory(modules::ModuleService service, modules::Services &services) {
+		if (service == RawCheckin::service) {
+			services.create<RawCheckin>();
+			return true;
+		}
+		if (service == CheckinAdapted::service) {
+			auto* storage = services.get<data::Storage>();
+			auto* rawCheckin = services.get<RawCheckin>();
+			services.create<CheckinAdapted>(storage, rawCheckin);
+			return true;
+		}
+		return false;
+	}
+
+} // namespace fggl::assets
\ No newline at end of file
diff --git a/fggl/assets/pipeline/CMakeLists.txt b/fggl/assets/pipeline/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/fggl/assets/pipeline/loader.cpp b/fggl/assets/pipeline/loader.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bd1c1d0ba7ca678defbe42e2a8143724820eb003
--- /dev/null
+++ b/fggl/assets/pipeline/loader.cpp
@@ -0,0 +1,215 @@
+/*
+ * This file is part of FGGL.
+ *
+ * FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with FGGL.
+ * If not, see <https://www.gnu.org/licenses/>.
+ */
+
+//
+// Created by webpigeon on 19/11/22.
+//
+
+#include <stack>
+#include <vector>
+#include <memory>
+#include <set>
+#include <map>
+#include <concepts>
+
+#include "fggl/util/guid.hpp"
+
+namespace fggl::assets {
+
+	using AssetName = util::OpaqueName<uint64_t, struct AssetRefStruct>;
+
+	/**
+	 * The base class representing an asset.
+	 *
+	 * This can be combined with the templated version.
+	 */
+	class Asset {
+		public:
+			Asset(AssetName name) : m_name(name) {}
+			virtual ~Asset() = default;
+
+			inline void release() {
+				releaseImpl();
+			}
+
+			bool operator==(const Asset& asset) const {
+				return m_name == asset.m_name;
+			}
+
+			bool operator!=(const Asset& asset) const {
+				return m_name != asset.m_name;
+			}
+
+		private:
+			AssetName m_name;
+			virtual void releaseImpl() = 0;
+	};
+
+	/**
+	 * Wrapper for types that cannot extend Asset themselves.
+	 *
+	 * @tparam T the asset to wrap
+	 */
+	template<typename T>
+	class AssetBox : public Asset {
+		public:
+			AssetBox(T* ptr) : m_ptr(ptr) {}
+
+			~AssetBox() override {
+				release();
+			}
+
+			T* ptr() {
+				return m_ptr;
+			}
+
+		private:
+			T* m_ptr;
+
+			void releaseImpl() override {
+				delete m_ptr;
+				m_ptr = nullptr;
+			}
+
+	};
+
+	/**
+	 * Asset Library.
+	 *
+	 * The currently usable set of assets loaded into the engine.
+	 */
+	class AssetLibrary {
+		public:
+			void load(AssetName name);
+			void unload(AssetName name);
+
+			template<typename T>
+			requires std::derived_from<T, Asset>
+			void store(AssetName name, T* ptr) {
+				m_assets[name] = std::make_unique<T>(ptr);
+			}
+
+			template<typename T>
+			requires std::derived_from<T, Asset>
+			void get(AssetName name) const {
+				Asset* asset = m_assets.at(name).get();
+				return dynamic_cast<T>(asset);
+			}
+
+			inline Asset* get(AssetName name) const {
+				return m_assets.at( name ).get();
+			}
+
+		private:
+			std::map<AssetName, std::unique_ptr<Asset>> m_assets;
+
+	};
+
+	struct AssetRecord {
+		AssetName id;
+		std::vector<AssetName> dependencies;
+
+		bool hasDepends(AssetName name) const;
+		void addDepend(AssetName name);
+	};
+
+	class AssetGraph {
+		public:
+			AssetGraph(AssetLibrary* loader);
+
+			/**
+			 *
+			 *
+			 * @param name
+			 */
+			void require(AssetName& name) {
+				if ( m_loaded.find(name) != m_loaded.end() ) {
+					return;
+				}
+				m_required.push(name);
+			}
+
+			/**
+			 *
+			 *
+			 * @return
+			 */
+			 [[nodiscard]]
+			inline bool isLoadComplete() const {
+				return m_required.empty();
+			}
+
+			/**
+			 *
+			 *
+			 * @param name
+			 * @return
+			 */
+			 [[nodiscard]]
+			inline bool isLoaded(AssetName name) const {
+				return m_loaded.find(name) != m_loaded.end();
+			}
+
+			/**
+			 *
+			 * @param name
+			 * @param description
+			 */
+			void addDependency(AssetName& name, AssetName& description) {
+				auto& assets = m_assets.at(name);
+				assets.addDepend(description);
+			}
+
+			/**
+			 *
+			 * @param name
+			 * @param dependency
+			 * @return
+			 */
+			[[nodiscard]]
+			bool hasDependency(AssetName& name , AssetName& dependency) const {
+				try {
+					auto &assets = m_assets.at(name);
+					return assets.hasDepends(dependency);
+				} catch ( std::out_of_range& ) {
+					return false;
+				}
+			}
+
+			/**
+			 *
+			 */
+			void process() {
+				auto asset = m_required.top();
+				m_loader->load( asset );
+				m_required.pop();
+			}
+
+			/**
+			 *
+			 */
+			void finishLoading() {
+				while ( !m_loaded.empty() ) {
+					process();
+				}
+			}
+
+		private:
+			std::stack<AssetName> m_required;
+			std::set<AssetName> m_loaded;
+			std::map<AssetName, AssetRecord> m_assets;
+			AssetLibrary* m_loader;
+	};
+
+} // namespace fggl::assets
\ No newline at end of file
diff --git a/fggl/audio/openal/audio.cpp b/fggl/audio/openal/audio.cpp
index 1cfb4b7a123a0a6424a3e2907a2af381ca96a552..d763a6f5e37a889d573b54e9a63ebe215acc27cf 100644
--- a/fggl/audio/openal/audio.cpp
+++ b/fggl/audio/openal/audio.cpp
@@ -52,6 +52,35 @@ namespace fggl::audio::openal {
 		return nullptr;
 	}
 
+	bool load_vorbis_short(std::filesystem::path path, assets::MemoryBlock& block) {
+		// vorbis
+		auto* clip = new AudioClipShort();
+		clip->sampleCount = stb_vorbis_decode_filename( path.c_str(), &clip->channels, &clip->sampleRate, &clip->data);
+		debug::info("clip loaded: channels={}, sampleRate={}, sampleCount={}", clip->channels, clip->sampleRate, clip->sampleCount);
+
+		if ( clip->sampleCount == -1 ) {
+			return false;
+		}
+
+		return false;
+	}
+
+	assets::AssetTypeID check_vorbis(std::filesystem::path path) {
+		if ( path.extension() != ".ogg" ) {
+			return assets::INVALID_ASSET_TYPE;
+		}
+
+		auto* clip = new AudioClipShort();
+		clip->sampleCount = stb_vorbis_decode_filename( path.c_str(), &clip->channels, &clip->sampleRate, &clip->data);
+
+		if ( clip->sampleCount == -1 ) {
+			return assets::INVALID_ASSET_TYPE;
+		}
+
+		delete clip;
+		return ASSET_CLIP_SHORT;
+	}
+
 	void AudioSource::play(const AudioClipShort &clip, bool looping) {
 		check_error("pre play");
 
diff --git a/fggl/audio/openal/module.cpp b/fggl/audio/openal/module.cpp
index 056abd3a214a1a7a70e58a4dbf45ffb25a1e30cd..89aeb857d93558665556c24e8fbebd9ab1c8cd2f 100644
--- a/fggl/audio/openal/module.cpp
+++ b/fggl/audio/openal/module.cpp
@@ -29,6 +29,11 @@ namespace fggl::audio {
 				assetLoader->setFactory(OGG_VORBIS, openal::load_vorbis, assets::LoadType::PATH);
 			}
 
+			{
+				auto *checkin = services.get<assets::CheckinAdapted>();
+				checkin->setLoader( RES_OGG_VORBIS, openal::load_vorbis_short, openal::check_vorbis );
+			}
+
 			services.bind<audio::AudioService, openal::AudioServiceOAL>(assets);
 			return true;
 		}
diff --git a/fggl/data/assimp/module.cpp b/fggl/data/assimp/module.cpp
index 8ba764885f0c0cf1e698ebfe78565723a9d23153..4ae1bb6956dec034152891544789a635af8311ef 100644
--- a/fggl/data/assimp/module.cpp
+++ b/fggl/data/assimp/module.cpp
@@ -195,11 +195,63 @@ namespace fggl::data::models {
 		return nullptr;
 	}
 
+	static bool load_tex_stb(std::filesystem::path filePath, assets::MemoryBlock& block) {
+		stbi_set_flip_vertically_on_load(true);
+
+		//load the texture data into memory
+		data::Texture2D* image = new data::Texture2D();
+		image->data = stbi_load(filePath.c_str(), &image->size.x, &image->size.y, &image->channels, 3);
+
+		if ( image->data == nullptr ) {
+			debug::warning("error reading texture: {}", stbi_failure_reason());
+			delete image;
+			return false;
+		} else {
+			//manager->set(guid, image);
+			// TODO pass metadata to loader in a sensible way
+			block.size = image->channels * image->size.x * image->size.y;
+			block.data = (std::byte*)image->data;
+			delete image;
+			return true;
+		}
+	}
+
+	static assets::AssetTypeID is_tex_stb(std::filesystem::path filePath) {
+		// detect jpgs
+		if ( filePath.extension() == ".jpg" || filePath.extension() == ".jpeg" ) {
+			return TEXTURE_RGBA;
+		}
+
+		// detect png
+		if ( filePath.extension() == ".png" ) {
+			return TEXTURE_RGBA;
+		}
+
+		return assets::INVALID_ASSET_TYPE;
+	}
+
+	static bool load_model_assimp(std::filesystem::path filePath, assets::MemoryBlock& block) {
+		return false; //TODO
+	}
+
+	static assets::AssetTypeID is_model_assimp(std::filesystem::path filePath) {
+		if ( filePath.extension() == ".obj" ){
+			return MODEL_MULTI3D;
+		}
+
+		return assets::INVALID_ASSET_TYPE;
+	}
+
 	bool AssimpModule::factory(modules::ModuleService service, modules::Services &serviceManager) {
 		if ( service == MODEL_PROVIDER ) {
-			auto assetLoader = serviceManager.get<assets::Loader>();
+			auto* assetLoader = serviceManager.get<assets::Loader>();
 			assetLoader->setFactory( ASSIMP_MODEL, load_assimp_model, assets::LoadType::PATH );
 			assetLoader->setFactory( DATA_TEXTURE2D, load_assimp_texture, assets::LoadType::PATH );
+
+			auto* checkin = serviceManager.get<assets::CheckinAdapted>();
+			checkin->setLoader( MIME_JPG, load_tex_stb, is_tex_stb );
+			checkin->setLoader( MIME_PNG, load_tex_stb, is_tex_stb );
+			checkin->setLoader( MIME_OBJ, load_model_assimp, is_model_assimp );
 		}
 	}
 
diff --git a/include/fggl/assets/loader.hpp b/include/fggl/assets/loader.hpp
index b58f506002576ea725d04913ea5a3ecf3f4f7267..0bc18d9e97ae12e87abf6490343a6c2c36a4b88d 100644
--- a/include/fggl/assets/loader.hpp
+++ b/include/fggl/assets/loader.hpp
@@ -27,6 +27,7 @@
 #include <variant>
 
 #include "fggl/assets/types.hpp"
+#include "fggl/assets/packed/adapter.hpp"
 #include "fggl/data/storage.hpp"
 
 namespace fggl::assets {
@@ -46,7 +47,7 @@ namespace fggl::assets {
 		public:
 			constexpr const static modules::ModuleService service = modules::make_service("fggl::assets::Loader");
 
-			explicit inline Loader(data::Storage *storage) : m_storage(storage) {}
+			explicit inline Loader(data::Storage *storage, CheckinAdapted *checkin) : m_storage(storage), m_checkin(checkin) {}
 
 			explicit Loader(Loader *parent, data::Storage *storage) : m_parent(parent), m_storage(storage) {};
 
@@ -68,8 +69,17 @@ namespace fggl::assets {
 				m_requests.push(ResourceRequest{guid, type});
 			}
 
-			void load(const AssetGUID &guid, const AssetType &type, void* userPtr = nullptr) {
-				auto path = m_storage->resolvePath(data::StorageType::Data, guid);
+			void load(const AssetGUID &guid, const AssetType &type, void* userPtr = nullptr, const std::string& pack = "core") {
+
+				auto assetID = assets::make_asset_id(pack, guid);
+				std::filesystem::path path{};
+
+				// integrate the asset search routine, falling back to path scanning if needed
+				if ( m_checkin->exists(assetID) ) {
+					path = m_checkin->getPath(assetID);
+				} else {
+					path = m_storage->resolvePath(data::StorageType::Data, guid);
+				}
 
 				auto factoryItr = m_factories.find(type);
 				if ( factoryItr == m_factories.end() ) {
@@ -120,6 +130,7 @@ namespace fggl::assets {
 			Loader *m_parent = nullptr;
 			using Config = std::pair<Checkin, LoadType>;
 			data::Storage *m_storage;
+			CheckinAdapted *m_checkin;
 			std::queue<ResourceRequest> m_requests;
 			std::map<AssetType, Config> m_factories;
 	};
diff --git a/include/fggl/assets/module.hpp b/include/fggl/assets/module.hpp
index 1c61f2d7724dd0b7195078b2eb58f1e766951ed1..388268e7bb034b532f59502cc90fa4f9392e3cda 100644
--- a/include/fggl/assets/module.hpp
+++ b/include/fggl/assets/module.hpp
@@ -20,7 +20,10 @@
 #define FGGL_ASSETS_MODULE_HPP
 
 #include "fggl/modules/module.hpp"
+
 #include "fggl/data/module.hpp"
+
+#include "fggl/assets/packed/module.hpp"
 #include "fggl/assets/manager.hpp"
 #include "fggl/assets/loader.hpp"
 
@@ -32,8 +35,9 @@ namespace fggl::assets {
 			Loader::service,
 			AssetManager::service
 		};
-		constexpr static const std::array<modules::ModuleService, 1> depends = {
-			data::Storage::service
+		constexpr static const std::array<modules::ModuleService, 2> depends = {
+			data::Storage::service,
+			CheckinAdapted::service
 		};
 		static bool factory(modules::ModuleService name, modules::Services &serviceManager);
 	};
diff --git a/include/fggl/assets/packed/adapter.hpp b/include/fggl/assets/packed/adapter.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..fd787ba7df0318dee6f4a957ebae1029dc9bc862
--- /dev/null
+++ b/include/fggl/assets/packed/adapter.hpp
@@ -0,0 +1,267 @@
+/*
+ * This file is part of FGGL.
+ *
+ * FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with FGGL.
+ * If not, see <https://www.gnu.org/licenses/>.
+ */
+
+//
+// Created by webpigeon on 19/11/22.
+//
+
+#ifndef FGGL_ASSETS_PACKED_ADAPTER_HPP
+#define FGGL_ASSETS_PACKED_ADAPTER_HPP
+
+#include <stack>
+#include <ranges>
+#include <algorithm>
+
+#include "fggl/assets/packed/direct.hpp"
+#include "fggl/data/storage.hpp"
+
+namespace fggl::assets {
+
+	using ResourceType = util::OpaqueName<uint64_t, struct ResourceTypeStruct>;
+	constexpr ResourceType from_mime(const char* mime) {
+		return ResourceType::make( util::hash_fnv1a_64(mime) );
+	};
+
+	struct ResourceRecord {
+		std::filesystem::path m_path;
+		AssetID assetID;
+		ResourceType m_fileType;
+		AssetTypeID m_assetType;
+	};
+
+	struct ManifestHeader {
+		uint64_t assetID;
+		uint64_t fileType;
+		uint64_t assetType;
+		uint64_t stringSize;
+	};
+
+	[[maybe_unused]]
+	inline bool NEEDS_CHECKIN(std::filesystem::path, MemoryBlock) {
+		debug::error("attempted to load asset which does not have a valid checkin yet");
+		return false;
+	}
+
+	/**
+	 * Adapter for Raw Checkin.
+	 *
+	 * For debugging/development it's a pain to have to pack assets directly. Although its much slower, it can be useful
+	 * to be able to load non-optimised formats at runtime. This adapter allows injecting these non-optimised formats
+	 * into the production checkin system.
+	 */
+	class CheckinAdapted {
+		public:
+			constexpr const static modules::ModuleService service = modules::make_service("fggl::assets::checkin::debug");
+			using FilePredicate = std::function<AssetTypeID(std::filesystem::path)>;
+			using FileLoader = std::function<bool(std::filesystem::path, MemoryBlock& block)>;
+
+			CheckinAdapted(data::Storage* storage, RawCheckin* checkSvc) : m_storage(storage), m_checkin(checkSvc) {};
+
+			// asset loading
+			void load(AssetID asset) {
+				auto& assetRef = m_files.at(asset);
+				auto& loader = m_loaders.at(assetRef.m_fileType);
+
+				MemoryBlock block;
+				auto result = loader(assetRef.m_path, block);
+				if ( !result ) {
+					return;
+				}
+
+				m_checkin->check(assetRef.assetID, assetRef.m_assetType, block);
+			}
+
+			inline bool exists(AssetID asset) const {
+				return m_files.find(asset) != m_files.end();
+			}
+
+			inline std::filesystem::path getPath(AssetID asset) const {
+				auto& file = m_files.at(asset);
+				return file.m_path;
+			}
+
+			void discover( const char* packName, bool useCache = false, bool updateCache = true) {
+				std::string packRoot = "packs/";
+				auto packDir = m_storage->resolvePath( data::StorageType::Data, packRoot + packName );
+				discover(packDir, useCache, updateCache);
+			}
+
+			// asset discovery
+			void discover( std::filesystem::path& packDir, bool useCache=true, bool updateCache=false ) {
+				if ( useCache && has_manifest(packDir)) {
+					// check if we've cached the search
+					load_manifest(packDir.filename(), packDir);
+					return;
+				}
+
+				std::vector<AssetID> packFiles;
+				std::stack< std::filesystem::path > paths;
+				paths.push(packDir);
+
+				while ( !paths.empty() ) {
+					auto path = paths.top();
+					paths.pop();
+
+					if ( std::filesystem::is_directory(path) ) {
+						std::ranges::for_each( std::filesystem::directory_iterator{path}, [&paths](auto& path) {
+							paths.push(path);
+						});
+					} else if ( std::filesystem::is_regular_file(path) ) {
+						process_file( path, packDir, packFiles );
+					}
+				}
+
+				// update the cache and remember what pack maps to what asset
+				if ( updateCache ) {
+					save_manifest(packDir.filename(), packDir, packFiles);
+				}
+				m_packs[ packDir.filename() ] = packFiles;
+			}
+
+			inline void setLoader(ResourceType type, FileLoader loader, FilePredicate predicate = nullptr) {
+				assert( loader != nullptr );
+				m_loaders[type] = loader;
+
+				if ( predicate != nullptr ) {
+					m_predicates[type] = predicate;
+				}
+			}
+
+		private:
+			data::Storage* m_storage;
+			RawCheckin* m_checkin;
+			std::map<AssetID, ResourceRecord> m_files;
+
+			std::map<ResourceType, FilePredicate> m_predicates;
+			std::map<ResourceType, FileLoader> m_loaders;
+			std::map<std::string, std::vector<AssetID>> m_packs;
+
+			void process_file(std::filesystem::path path, std::filesystem::path packDir, std::vector<AssetID> packFiles) {
+				for( auto& [rType, pred] : m_predicates ) {
+					// check the predicate, is this valid?
+					auto aType = pred(path);
+					if ( aType != INVALID_ASSET_TYPE ) {
+						// it was, so we can finish processing
+						auto packName = packDir.filename();
+						auto relPath = std::filesystem::relative(path, packDir);
+						ResourceRecord rr{
+							.m_path = path,
+							.assetID = make_asset_id(packName, relPath.generic_string()),
+							.m_fileType = rType,
+							.m_assetType = aType,
+						};
+						m_files[rr.assetID] = rr;
+						packFiles.push_back( rr.assetID );
+						debug::trace("discovered {} ({}) from pack '{}'", rr.assetID.get(), relPath.c_str(), packName.c_str() );
+						break;
+					}
+				}
+			}
+
+			inline bool has_manifest(const std::string& packName) {
+				auto packManifest = m_storage->resolvePath( data::StorageType::Cache, packName + "_manifest.bin" );
+				return std::filesystem::exists(packManifest);
+			}
+
+			void load_manifest_entry(FILE* file, const std::filesystem::path& packRoot) {
+				// read our entry ( id, ftype, atype, pathLen )
+				ManifestHeader header{};
+				std::fread(&header, sizeof(ManifestHeader), 1, file);
+
+				// read the relative asset path
+				char* relPath = new char[header.stringSize + 1];
+				std::fread( relPath, sizeof(char), header.stringSize, file );
+				relPath[ header.stringSize + 1 ] = '\0';
+
+				// calculate and verify path
+				std::filesystem::path fullPath = packRoot / relPath;
+				delete[] relPath;
+
+				if ( !std::filesystem::exists(fullPath) ) {
+					debug::warning("pack manifest for {} contained invalid path {}", packRoot.filename().c_str(), fullPath.c_str());
+					return;
+				}
+
+				// entry seems valid, load it
+				ResourceRecord rr {
+					.m_path = fullPath,
+					.assetID = AssetID::make(header.assetID),
+					.m_fileType = ResourceType::make(header.fileType),
+					.m_assetType = AssetTypeID::make(header.assetType)
+				};
+				m_files[ rr.assetID ] = rr;
+				m_packs[ packRoot.filename() ].push_back( rr.assetID );
+				debug::trace("discovered {} ({}) from pack {}", rr.assetID.get(), fullPath.c_str(), packRoot.filename().c_str() );
+			}
+
+			void load_manifest(const std::string& packName, const std::filesystem::path& packRoot) {
+				auto packManifest = m_storage->resolvePath( data::StorageType::Cache, packName + "_manifest.bin" );
+				if ( !std::filesystem::exists(packManifest) ) {
+					return;
+				}
+
+				// open the manifest file and start extracting entries
+				FILE* file = std::fopen(packManifest.c_str(), "r");
+				if ( file == nullptr ) {
+					debug::warning("error opening manifest: {}", packManifest.c_str());
+					return;
+				}
+
+				// read the number of entries
+				uint64_t entries{0};
+				std::fread(&entries, sizeof(uint64_t), 1, file);
+				for ( uint64_t i = 0; i < entries; ++i) {
+					load_manifest_entry(file, packRoot);
+				}
+
+				std::fclose( file );
+			}
+
+			void save_manifest(const std::string& packName, const std::filesystem::path& packRoot, const std::vector<AssetID>& assets) {
+				auto packManifest = m_storage->resolvePath( data::StorageType::Cache, packName + "_manifest.bin", true);
+
+				FILE* file = std::fopen(packManifest.c_str(), "w");
+				if ( file == nullptr) {
+					debug::warning("error saving manifest {}, missing dir?", packManifest.c_str());
+					return;
+				}
+
+				const uint64_t entries{ assets.size() };
+				std::fwrite( &entries, sizeof(uint64_t), 1, file);
+
+				// write the entries
+				for ( uint64_t i = 0; i < entries; ++i ) {
+					auto& assetID = assets[i];
+
+					auto& assetRecord = m_files.at(assetID);
+					auto relPath = std::filesystem::relative(assetRecord.m_path, packRoot);
+					auto relPathStr = relPath.generic_string();
+
+					ManifestHeader mh {
+						.assetID = assetRecord.assetID.get(),
+						.fileType = assetRecord.m_fileType.get(),
+						.assetType = assetRecord.m_assetType.get(),
+						.stringSize = relPathStr.size()
+					};
+					std::fwrite( &mh, sizeof(ManifestHeader), 1, file );
+					std::fwrite( relPathStr.c_str(), sizeof(char), relPathStr.size(), file );
+				}
+
+				std::fclose(file);
+			}
+	};
+
+}
+
+#endif //FGGL_ASSETS_PACKED_ADAPTER_HPP
diff --git a/include/fggl/assets/packed/direct.hpp b/include/fggl/assets/packed/direct.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..faa01aedcd1ca28bc5c9abfec8ea7be3e69c8e37
--- /dev/null
+++ b/include/fggl/assets/packed/direct.hpp
@@ -0,0 +1,76 @@
+/*
+ * This file is part of FGGL.
+ *
+ * FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with FGGL.
+ * If not, see <https://www.gnu.org/licenses/>.
+ */
+
+//
+// Created by webpigeon on 19/11/22.
+//
+
+#ifndef FGGL_ASSETS_PACKED_DIRECT_HPP
+#define FGGL_ASSETS_PACKED_DIRECT_HPP
+
+#include <functional>
+#include <map>
+
+#include "fggl/assets/types.hpp"
+#include "fggl/util/safety.hpp"
+#include "fggl/util/guid.hpp"
+#include "fggl/modules/module.hpp"
+
+/**
+ * Raw Checkin.
+ *
+ * This is a version of the checkin system where the check-in functions are shown a raw block of memory and its their
+ * job to parse and load something meaningful from that.
+ */
+namespace fggl::assets {
+
+	using AssetID = util::OpaqueName<uint64_t, struct AssetIDTag>;
+
+	constexpr AssetID make_asset_id(const std::string& pack, const std::string& path, const std::string& view = "") {
+		auto ref = pack + ":" + path;
+		if ( !view.empty() ) {
+			ref += "[" + view + "]";
+		}
+		return AssetID::make( util::hash_fnv1a_64(ref.c_str()) );
+	}
+
+	using AssetTypeID = util::OpaqueName<uint64_t, struct AssetTypeTag>;
+	constexpr auto INVALID_ASSET_TYPE = AssetTypeID::make(0);
+
+	constexpr AssetTypeID make_asset_type(const char* type) {
+		return AssetTypeID::make( util::hash_fnv1a_64(type) );
+	}
+
+	class RawCheckin {
+		public:
+			constexpr const static modules::ModuleService service = modules::make_service("fggl::assets::checkin");
+			using DecodeAndCheckFunc = std::function<void(AssetGUID, MemoryBlock& block)>;
+
+			void check(AssetID, AssetTypeID, MemoryBlock& block) const;
+
+			inline void check(int64_t id, uint64_t type, MemoryBlock& block ) const {
+				check( AssetID::make(id), AssetTypeID::make(type), block );
+			}
+
+			inline void setCheckin(AssetTypeID type, DecodeAndCheckFunc func) {
+				m_check[type] = func;
+			}
+
+		private:
+			std::map<AssetTypeID, DecodeAndCheckFunc> m_check;
+	};
+
+}
+
+#endif //FGGL_ASSETS_PACKED_DIRECT_HPP
diff --git a/include/fggl/assets/packed/module.hpp b/include/fggl/assets/packed/module.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..8ecc4b2583d2a5f20c2af511b4804b07073026af
--- /dev/null
+++ b/include/fggl/assets/packed/module.hpp
@@ -0,0 +1,45 @@
+/*
+ * This file is part of FGGL.
+ *
+ * FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with FGGL.
+ * If not, see <https://www.gnu.org/licenses/>.
+ */
+
+//
+// Created by webpigeon on 27/06/22.
+//
+
+#ifndef FGGL_ASSETS_PACKED_MODULE_HPP
+#define FGGL_ASSETS_PACKED_MODULE_HPP
+
+#include "fggl/modules/module.hpp"
+#include "fggl/data/module.hpp"
+#include "fggl/assets/loader.hpp"
+
+#include "fggl/assets/packed/adapter.hpp"
+#include "fggl/assets/packed/direct.hpp"
+
+namespace fggl::assets {
+
+	struct PackedAssets {
+		constexpr static const char *name = "fggl::assets::packed";
+		constexpr static const std::array<modules::ModuleService, 2> provides = {
+			RawCheckin::service,
+			CheckinAdapted::service
+		};
+		constexpr static const std::array<modules::ModuleService, 1> depends = {
+			data::Storage::service
+		};
+		static bool factory(modules::ModuleService name, modules::Services &serviceManager);
+	};
+
+} // namespace fggl::assets
+
+#endif //FGGL_ASSETS_PACKED_MODULE_HPP
diff --git a/include/fggl/assets/packed/packed.hpp b/include/fggl/assets/packed/packed.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..4a6c0912dd907bfb56a7e7eace8ae873ef4dc8dd
--- /dev/null
+++ b/include/fggl/assets/packed/packed.hpp
@@ -0,0 +1,80 @@
+/*
+ * This file is part of FGGL.
+ *
+ * FGGL is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * FGGL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with FGGL.
+ * If not, see <https://www.gnu.org/licenses/>.
+ */
+
+//
+// Created by webpigeon on 19/11/22.
+//
+
+#ifndef FGGL_ASSETS_PACKED_PACKED_HPP
+#define FGGL_ASSETS_PACKED_PACKED_HPP
+
+#include <cstdint>
+#include <cstdio>
+#include <memory>
+
+#include "fggl/assets/types.hpp"
+#include "fggl/assets/packed/direct.hpp"
+
+/**
+ * Packed file reader.
+ *
+ * Read assets stored as sequential [header,data] blocks. This reader does not care about dependencies, it assumes this
+ * was handled before storage (ie, asset dependencies are assumed to be stored before the asset that relies on them).
+ * The caller is also responsible for ensuring that assets in other archives are already loaded by the time the system
+ * assembles the composite assets into something usable.
+ *
+ * If either of these constraints are violated, the results are undefined.
+ */
+namespace fggl::assets {
+
+	struct Header {
+		uint64_t name;
+		uint64_t type;
+		std::size_t size;
+	};
+
+	bool read_header(std::FILE* stream, Header* header) {
+		constexpr auto headerSize = sizeof(Header);
+		auto readBytes = std::fread(header, headerSize, 1, stream);
+		return readBytes == headerSize;
+	}
+
+	bool read_data(std::FILE* stream, void* block, std::size_t size) {
+		auto readBytes = std::fread(block, size, 1, stream);
+		return readBytes == size;
+	}
+
+	void read_archive(RawCheckin* checkin, std::FILE* stream) {
+		while ( !std::feof(stream) ) {
+			Header header;
+			bool headRead = read_header(stream, &header);
+			if ( headRead && header.size != 0 ) {
+				// header has data
+				void* memBlock = std::malloc( header.size );
+				bool valid = read_data( stream, memBlock, header.size );
+
+				// read the data, check it in
+				if (valid) {
+					MemoryBlock block{
+						.data = (std::byte*)memBlock,
+						.size = header.size
+					};
+					checkin->check(header.name, header.type, block);
+				}
+			}
+		}
+	}
+}
+
+#endif //FGGL_ASSETS_PACKED_PACKED_HPP
diff --git a/include/fggl/assets/types.hpp b/include/fggl/assets/types.hpp
index 4b93825aee0042a3cbf81d599c93f2f2cef0ac0b..4abcdc702c521985a3f39361ac252e5833bf6f47 100644
--- a/include/fggl/assets/types.hpp
+++ b/include/fggl/assets/types.hpp
@@ -30,22 +30,19 @@ namespace fggl::assets {
 	using AssetGUID = std::string;
 	using AssetPath = std::filesystem::path;
 
-	struct Asset {
-		AssetType m_type;
-		virtual void release() = 0;
-		virtual bool active() = 0;
-	};
-
 	struct MemoryBlock {
-		void *data;
+		std::byte *data;
 		std::size_t size;
+
+		template<typename T>
+		T* viewAs(std::size_t offset = 0) {
+			static_assert( std::is_standard_layout<T>::value );
+			return (T*)( data[offset] );
+		}
 	};
 
 	using AssetRefRaw = std::shared_ptr<void>;
 
-	template<typename T>
-	using AssetRef = std::shared_ptr<T>;
-
 	class Loader;
 	using AssetData = std::variant<MemoryBlock, AssetPath *, FILE *>;
 	using Checkin = std::function<AssetRefRaw(Loader* loader, const AssetGUID &, const AssetData &, void* userPtr)>;
diff --git a/include/fggl/audio/audio.hpp b/include/fggl/audio/audio.hpp
index 1d9c91234b26f031b859247bcad7259cb873e2a5..67c8889b8fd80d889500e1b351da07d46f595d21 100644
--- a/include/fggl/audio/audio.hpp
+++ b/include/fggl/audio/audio.hpp
@@ -20,6 +20,7 @@
 #include "fggl/data/storage.hpp"
 #include "fggl/modules/module.hpp"
 #include "fggl/assets/module.hpp"
+#include "fggl/assets/packed/module.hpp"
 
 //! backend independent audio interface
 namespace fggl::audio {
@@ -45,6 +46,9 @@ namespace fggl::audio {
 	 using AudioClipShort = AudioClip<short>;
 	 using AudioClipByte = AudioClip<char>;
 
+	 constexpr auto ASSET_CLIP_SHORT = assets::make_asset_type("Audio:Clip:Short");
+	 constexpr auto ASSET_CLIP_BYTE = assets::make_asset_type("Audio:Clip:Byte");
+
 	constexpr modules::ModuleService SERVICE_AUDIO_PLAYBACK = modules::make_service("fggl::audio::AudioService");
 
 	/**
diff --git a/include/fggl/audio/openal/audio.hpp b/include/fggl/audio/openal/audio.hpp
index b1d4bcfa759ba985701d2e01454a90b066ba8862..cf59cab2ce31253226ccd93edf45f8038856e43b 100644
--- a/include/fggl/audio/openal/audio.hpp
+++ b/include/fggl/audio/openal/audio.hpp
@@ -38,6 +38,9 @@ namespace fggl::audio::openal {
 
 	assets::AssetRefRaw load_vorbis(assets::Loader* loader, const assets::AssetGUID &, const assets::AssetData &, void* userPtr);
 
+	bool load_vorbis_short(std::filesystem::path path, assets::MemoryBlock& block);
+	assets::AssetTypeID check_vorbis(std::filesystem::path path);
+
 	enum class AudioType {
 		MONO_8 = AL_FORMAT_MONO8,
 		MONO_16 = AL_FORMAT_MONO16,
diff --git a/include/fggl/audio/openal/module.hpp b/include/fggl/audio/openal/module.hpp
index 260ef675c7d244a8a659754ba63ea376fdc092c9..4ca559d7a17da573aeea85e388ed008aa26f812f 100644
--- a/include/fggl/audio/openal/module.hpp
+++ b/include/fggl/audio/openal/module.hpp
@@ -23,6 +23,7 @@
 #include <string>
 
 #include "fggl/assets/module.hpp"
+#include "fggl/assets/packed/module.hpp"
 
 #include "fggl/audio/audio.hpp"
 #include "fggl/audio/openal/audio.hpp"
@@ -30,14 +31,16 @@
 namespace fggl::audio {
 
 	constexpr auto OGG_VORBIS = assets::AssetType::make("audio/vorbis");
+	constexpr auto RES_OGG_VORBIS = assets::from_mime("audio/vorbis");
 
 	struct OpenAL {
 		constexpr static const char *name = "fggl::audio::OpenAL";
 		constexpr static const std::array<modules::ModuleService, 1> provides = {
 			SERVICE_AUDIO_PLAYBACK
 		};
-		constexpr static const std::array<modules::ModuleService, 1> depends = {
-			assets::AssetManager::service
+		constexpr static const std::array<modules::ModuleService, 2> depends = {
+			assets::AssetManager::service,
+			assets::CheckinAdapted::service
 		};
 		static bool factory(modules::ModuleService name, modules::Services &serviceManager);
 	};
diff --git a/include/fggl/data/assimp/module.hpp b/include/fggl/data/assimp/module.hpp
index 5743dc6052c66f5c6dc87954c2587d639a3ee7fb..d5c40dbf56fdc0c77cee9bf7842ddc8766f3c9c7 100644
--- a/include/fggl/data/assimp/module.hpp
+++ b/include/fggl/data/assimp/module.hpp
@@ -21,6 +21,7 @@
 
 #include "fggl/modules/module.hpp"
 #include "fggl/assets/loader.hpp"
+#include "fggl/assets/packed/module.hpp"
 #include "fggl/data/texture.hpp"
 
 namespace fggl::data::models {
@@ -28,13 +29,21 @@ namespace fggl::data::models {
 	constexpr auto MODEL_PROVIDER = modules::make_service("fggl::data::Model");
 	constexpr auto ASSIMP_MODEL = assets::AssetType::make("model::assimp");
 
+	constexpr auto MIME_JPG = assets::from_mime("image/jpeg");
+	constexpr auto MIME_PNG = assets::from_mime("image/png");
+	constexpr auto MIME_OBJ = assets::from_mime("model/obj");
+
+	constexpr auto MODEL_MULTI3D = assets::make_asset_type("model/multi3D");
+	constexpr auto TEXTURE_RGBA = assets::make_asset_type("texture/rgba");
+
 	struct AssimpModule {
 		constexpr static const char *name = "fggl::data::Assimp";
 		constexpr static const std::array<modules::ModuleService, 1> provides = {
 			MODEL_PROVIDER
 		};
-		constexpr static const std::array<modules::ModuleService, 1> depends = {
-			assets::Loader::service
+		constexpr static const std::array<modules::ModuleService, 2> depends = {
+			assets::Loader::service,
+			assets::CheckinAdapted::service
 		};
 		static bool factory(modules::ModuleService service, modules::Services &serviceManager);
 	};
diff --git a/include/fggl/gfx/ogl4/module.hpp b/include/fggl/gfx/ogl4/module.hpp
index 9de8e7903a67d16c18e6ae05fbc051717c5140c0..abde2d309df64630823c95ec1fe306c7fa299771 100644
--- a/include/fggl/gfx/ogl4/module.hpp
+++ b/include/fggl/gfx/ogl4/module.hpp
@@ -24,6 +24,8 @@
 #include "fggl/modules/module.hpp"
 
 #include "fggl/assets/manager.hpp"
+#include "fggl/assets/packed/module.hpp"
+
 #include "fggl/entity/loader/loader.hpp"
 
 #include "fggl/gfx/interfaces.hpp"
@@ -39,9 +41,10 @@ namespace fggl::gfx {
 		constexpr static const std::array<modules::ModuleService, 1> provides = {
 			WindowGraphics::service
 		};
-		constexpr static const std::array<modules::ModuleService, 4> depends = {
+		constexpr static const std::array<modules::ModuleService, 5> depends = {
 			data::Storage::service,
 			assets::AssetManager::service,
+			assets::CheckinAdapted::service,
 			gui::FontLibrary::service,
 			entity::EntityFactory::service
 		};
diff --git a/include/fggl/gui/module.hpp b/include/fggl/gui/module.hpp
index e2abbd15f81dde1c8fd52118c02ef5ac4b8a8b7c..3e54d06f6210f001cb8b361257904f93f1f9d6c6 100644
--- a/include/fggl/gui/module.hpp
+++ b/include/fggl/gui/module.hpp
@@ -21,16 +21,28 @@
 
 #include "fggl/gui/fonts.hpp"
 #include "fggl/data/module.hpp"
+#include "fggl/assets/packed/module.hpp"
 
 namespace fggl::gui {
 
+	constexpr auto MIME_TTF = assets::from_mime("font/ttf");
+	constexpr auto ASSET_FONT_TTF = assets::make_asset_type("font/ttf");
+
+	static assets::AssetTypeID is_font(std::filesystem::path path) {
+		if ( path.extension() == ".ttf" ){
+			return ASSET_FONT_TTF;
+		}
+		return assets::INVALID_ASSET_TYPE;
+	}
+
 	struct FreeType {
 		constexpr static const char *name = "fggl::gui::FreeType";
 		constexpr static const std::array<modules::ModuleService, 1> provides = {
 			FontLibrary::service
 		};
-		constexpr static const std::array<modules::ModuleService, 1> depends = {
-			data::Storage::service
+		constexpr static const std::array<modules::ModuleService, 2> depends = {
+			data::Storage::service,
+			assets::CheckinAdapted::service
 		};
 		static bool factory(modules::ModuleService name, modules::Services &serviceManager);
 	};
@@ -39,6 +51,10 @@ namespace fggl::gui {
 		if (service == FontLibrary::service) {
 			auto storage = services.get<data::Storage>();
 			services.create<FontLibrary>(storage);
+
+			auto* checkin = services.get<assets::CheckinAdapted>();
+			checkin->setLoader( MIME_TTF, assets::NEEDS_CHECKIN, is_font );
+
 			return true;
 		}
 		return false;
diff --git a/tools/pack/src/binary.hpp b/tools/pack/src/binary.hpp
index 8c52fdcf8ad0ec80b33c123bc784526b19b8e2f5..04f56a36450f6207bad3c123fc28a3bb92d77d06 100644
--- a/tools/pack/src/binary.hpp
+++ b/tools/pack/src/binary.hpp
@@ -30,8 +30,8 @@
 // Created by webpigeon on 11/09/22.
 //
 
-#ifndef FGGL_TOOLS_PACK_INCLUDES_BINARY_HPP
-#define FGGL_TOOLS_PACK_INCLUDES_BINARY_HPP
+#ifndef FGGL_TOOLS_PACK_SRC_BINARY_HPP
+#define FGGL_TOOLS_PACK_SRC_BINARY_HPP
 
 #include <cstdint>
 #include <iostream>
@@ -132,4 +132,4 @@ namespace fggl::data {
 
 }
 
-#endif //FGGL_TOOLS_PACK_INCLUDES_BINARY_HPP
+#endif //FGGL_TOOLS_PACK_SRC_BINARY_HPP