diff --git a/demo/demo/hexboard/board.cpp b/demo/demo/hexboard/board.cpp
index 40bf199540fddd761861b3d18917f788a542b5a1..4c8c1c5eb7e98ca0a337d7a2ac8ec1c0c96162af 100644
--- a/demo/demo/hexboard/board.cpp
+++ b/demo/demo/hexboard/board.cpp
@@ -40,15 +40,53 @@ namespace demo::hexboard {
 		}
 	}
 
+	// see https://www.redblobgames.com/grids/hexagons/#hex-to-pixel
+	const fggl::math::mat2 HEX_BASIS{
+		std::sqrt(3.0F), std::sqrt(3.0F) / 2.0F,
+		0.0F, 3.0F / 2.0F
+	};
+
+	static inline fggl::math::vec2 hexToScreen(fggl::grid::IntHex hexPos, float size, fggl::math::vec2 offset = {0,0}) {
+		return size * fggl::math::vec2{hexPos.q(), hexPos.r()} * HEX_BASIS + offset;
+	}
+
 	void Scene::render(fggl::gfx::Graphics &gfx) {
 		// if the board is not set, abort
-		if ( m_board == nullptr ){
+		/*if ( m_board == nullptr ){
 			return;
-		}
+		}*/
 
 		// draw the grid
+		// FIXME don't hard-code the screen size
+		const float hexRadius = 64.0F;
+		const auto gridWidth = (int)( (1920 - hexRadius) / (hexRadius * std::sqrt(3.0F)) );
+		const auto gridHeight = (int)( (1080 - hexRadius) / (hexRadius * (3.0F / 2.0F) ));
+
+		const fggl::math::vec2 offset{
+			( 1920 - ( (float)gridWidth * hexRadius * std::sqrt(3.0F))) - (hexRadius / 2.0F),
+			( (1080 - hexRadius / 2.0F) - ( (float)gridHeight * hexRadius * (3.0F / 2.0F) )),
+		};
+
 		fggl::gfx::Paint paint;
+		fggl::grid::IntHex hexPos{0, 0};
+		auto rowBasis = hexPos;
+		for(auto i=0; i<gridHeight; ++i) {
+			for (auto j=0; j<gridWidth; ++j) {
+				auto pos = hexToScreen(hexPos, hexRadius, offset);
+
+				auto hex = fggl::gfx::make_shape(pos, hexRadius, 6);
+				paint.stroke(hex);
+				pos.x += hexRadius;
+				hexPos = hexPos.neighbour( fggl::grid::HexDirPointy::RIGHT );
+			}
+
+			rowBasis = i % 2 == 0 ? rowBasis.neighbour(fggl::grid::HexDirPointy::BOTTOM_RIGHT) : rowBasis.neighbour(fggl::grid::HexDirPointy::BOTTOM_LEFT);
+			hexPos = rowBasis;
+		}
+
 		gfx.draw2D(paint);
 	}
 
+
+
 } // namespace demo::hexboard
\ No newline at end of file
diff --git a/include/fggl/grid/hexagon.hpp b/include/fggl/grid/hexagon.hpp
index 3d63a38fb25c7fc2bc6165df2666dda9531252ef..b5bb3b14f84359644f9244bf47e1dbd57ed04f7b 100644
--- a/include/fggl/grid/hexagon.hpp
+++ b/include/fggl/grid/hexagon.hpp
@@ -72,11 +72,13 @@ namespace fggl::grid {
 		}
 
 		inline HexPointT neighbour(HexDirPointy dir) {
-			return this + HexPointT<T>(HEX_DIRECTIONS.at((int)dir));
+			auto& offset = HEX_DIRECTIONS.at( (int)dir );
+			return { m_pos[0] + offset[0], m_pos[1] + offset[1] };
 		}
 
 		inline HexPointT neighbour(HexDirFlat dir) {
-			return this + HexPointT<T>(HEX_DIAGONALS.at((int)dir));
+			auto& offset = HEX_DIAGONALS.at( (int)dir );
+			return { m_pos[0] + offset[0], m_pos[1] + offset[1] };
 		}
 
 		HexPointT operator+(const HexPointT<T>& other) const {