diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a2a8066
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+build/
+.cache/
+CMakeUserPresets.json
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..88e55dc
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 3.22.0)
+
+set(PROJECT_NAME dinkyecs_sandbox)
+
+project(${PROJECT_NAME})
+set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
+
+file(GLOB PROJECT_SRC *.cpp *.hpp *.h)
+
+find_package(nlohmann_json)
+find_package(fmt)
+
+add_executable(${PROJECT_NAME} ${PROJECT_SRC})
+target_link_libraries(${PROJECT_NAME} nlohmann_json::nlohmann_json fmt::fmt)
diff --git a/clang_profile b/clang_profile
new file mode 100644
index 0000000..ef6d2d2
--- /dev/null
+++ b/clang_profile
@@ -0,0 +1,18 @@
+[settings]
+os=Windows
+arch=x86_64
+build_type=Debug
+compiler=clang
+compiler.version=19
+compiler.cppstd=gnu20
+compiler.runtime=static
+compiler.runtime_type=Debug
+compiler.runtime_version=v143
+
+[buildenv]
+CC=clang
+CXX=clang
+RC=clang
+
+[conf]
+tools.cmake.cmaketoolchain:generator=Ninja
diff --git a/conanfile.txt b/conanfile.txt
new file mode 100644
index 0000000..1249efb
--- /dev/null
+++ b/conanfile.txt
@@ -0,0 +1,10 @@
+[requires]
+nlohmann_json/3.11.3
+fmt/11.1.3
+
+[generators]
+CMakeDeps
+CMakeToolchain
+
+[layout]
+cmake_layout
diff --git a/main.cpp b/main.cpp
new file mode 100644
index 0000000..d0fda46
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,146 @@
+#include "dinkyecs.hpp"
+#include "point.hpp"
+#include <cassert>
+
+#define REQUIRE(X) assert(X);
+
+using DinkyECS::Entity;
+
+using namespace fmt;
+using DinkyECS::Entity;
+using std::string;
+
+struct Player {
+  string name;
+  Entity eid;
+};
+
+struct Position {
+  Point location;
+};
+
+// DINKY_HAS_COMPONENT(Point, x, y);
+// DINKY_HAS_COMPONENT(Position, location);
+
+struct Motion {
+  int dx;
+  int dy;
+  bool random=false;
+};
+
+// DINKY_HAS_COMPONENT(Motion, dx, dy, random);
+
+struct Velocity {
+  double x, y;
+};
+
+// DINKY_HAS_COMPONENT(Velocity, x, y);
+
+struct Gravity {
+  double level;
+};
+
+// DINKY_HAS_COMPONENT(Gravity, level);
+
+struct DaGUI {
+  int event;
+};
+
+void configure(DinkyECS::World &world, Entity &test) {
+  println("---Configuring the base system.");
+  Entity test2 = world.entity();
+
+  world.set<Position>(test, {10,20});
+  world.set<Velocity>(test, {1,2});
+
+  world.set<Position>(test2, {1,1});
+  world.set<Velocity>(test2, {9,19});
+
+  println("---- Setting up the player as a fact in the system.");
+
+  auto player_eid = world.entity();
+  Player player_info{"Zed", player_eid};
+  // just set some player info as a fact with the entity id
+  world.set_the<Player>(player_info);
+
+  world.set<Velocity>(player_eid, {0,0});
+  world.set<Position>(player_eid, {0,0});
+
+  auto enemy = world.entity();
+  world.set<Velocity>(enemy, {0,0});
+  world.set<Position>(enemy, {0,0});
+
+  println("--- Creating facts (singletons)");
+  world.set_the<Gravity>({0.9});
+}
+
+int main() {
+  DinkyECS::World world;
+  Entity test = world.entity();
+
+  configure(world, test);
+
+  Position &pos = world.get<Position>(test);
+  REQUIRE(pos.location.x == 10);
+  REQUIRE(pos.location.y == 20);
+
+  Velocity &vel = world.get<Velocity>(test);
+  REQUIRE(vel.x == 1);
+  REQUIRE(vel.y == 2);
+
+  world.query<Position>([](const auto &ent, auto &pos) {
+    REQUIRE(ent > 0);
+    REQUIRE(pos.location.x >= 0);
+    REQUIRE(pos.location.y >= 0);
+  });
+
+  world.query<Velocity>([](const auto &ent, auto &vel) {
+    REQUIRE(ent > 0);
+    REQUIRE(vel.x >= 0);
+    REQUIRE(vel.y >= 0);
+  });
+
+  println("--- Manually get the velocity in position system:");
+  world.query<Position>([&](const auto &ent, auto &pos) {
+    Velocity &vel = world.get<Velocity>(ent);
+
+    REQUIRE(ent > 0);
+    REQUIRE(pos.location.x >= 0);
+    REQUIRE(pos.location.y >= 0);
+    REQUIRE(ent > 0);
+    REQUIRE(vel.x >= 0);
+    REQUIRE(vel.y >= 0);
+  });
+
+  println("--- Query only entities with Position and Velocity:");
+  world.query<Position, Velocity>([&](const auto &ent, auto &pos, auto &vel) {
+    Gravity &grav = world.get_the<Gravity>();
+    REQUIRE(grav.level <= 1.0f);
+    REQUIRE(grav.level > 0.5f);
+    REQUIRE(ent > 0);
+    REQUIRE(pos.location.x >= 0);
+    REQUIRE(pos.location.y >= 0);
+    REQUIRE(ent > 0);
+    REQUIRE(vel.x >= 0);
+    REQUIRE(vel.y >= 0);
+  });
+
+  // now remove Velocity
+  REQUIRE(world.has<Velocity>(test));
+  world.remove<Velocity>(test);
+  //REQUIRE_THROWS(world.get<Velocity>(test));
+  REQUIRE(!world.has<Velocity>(test));
+
+  println("--- After remove test, should only result in test2:");
+  world.query<Position, Velocity>([&](const auto &ent, auto &pos, auto &vel) {
+    auto &in_position = world.get<Position>(ent);
+    auto &in_velocity = world.get<Velocity>(ent);
+    REQUIRE(pos.location.x >= 0);
+    REQUIRE(pos.location.y >= 0);
+    REQUIRE(in_position.location.x == pos.location.x);
+    REQUIRE(in_position.location.y == pos.location.y);
+    REQUIRE(in_velocity.x == vel.x);
+    REQUIRE(in_velocity.y == vel.y);
+  });
+  return 0;
+}
diff --git a/point.hpp b/point.hpp
new file mode 100644
index 0000000..db754c0
--- /dev/null
+++ b/point.hpp
@@ -0,0 +1,21 @@
+
+#pragma once
+#include <vector>
+
+struct Point {
+  size_t x = 0;
+  size_t y = 0;
+
+  bool operator==(const Point& other) const {
+    return other.x == x && other.y == y;
+  }
+};
+
+typedef std::vector<Point> PointList;
+
+template<> struct std::hash<Point> {
+  size_t operator()(const Point& p) const {
+    auto hasher = std::hash<int>();
+    return hasher(p.x) ^ hasher(p.y);
+  }
+};