diff --git a/lib/node.cpp b/lib/node.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..bada1929fdd79025b1e0c404ca3ef53be60dc137
--- /dev/null
+++ b/lib/node.cpp
@@ -0,0 +1,36 @@
+#include "node.hpp"
+
+/* 
+Node::Node() {
+    root_ = nullptr;
+    parent_ = nullptr;
+    particles_ = nullptr;
+    nParticles_ = 0;
+    depth_ = 0;
+    size_ = 0;
+    for (unsigned i=0; i<3; ++i) center_[i] = 0;
+    localParticles_ = nullptr;
+    nLocalParticles_ = 0;
+    for (unsigned i=0; i<8; ++i) children_[i] = nullptr;
+}
+ */
+
+Node::Node(Node* parent, double* particles, unsigned nParticles, unsigned depth, double size, double center[3], unsigned* localParticles, unsigned nLocalParticles) {
+    parent_ = parent;
+    particles_ = particles;
+    nParticles_ = nParticles;
+    depth_ = depth;
+    size_ = size;
+    for (unsigned i=0; i<3; ++i) center_[i] = center[i];
+    localParticles_ = localParticles;
+    nLocalParticles_ = nLocalParticles;
+    // allocate children
+    // TODO
+}
+
+Node::~Node() {
+    for (unsigned i=0; i<8; ++i) {
+        delete children_[i];
+    }
+    delete[] localParticles_;
+}
\ No newline at end of file
diff --git a/lib/node.hpp b/lib/node.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..9d078fd48000d7e758733d5880a01414e6820ed1
--- /dev/null
+++ b/lib/node.hpp
@@ -0,0 +1,25 @@
+#ifndef NODE_HPP
+#define NODE_HPP
+
+class Node {
+public:
+    // default constructor creates a leaf node
+    Node() = default;
+    // whoever creates the node is responsible for deciding which particles are in which octant and for allocating the localParticles array 
+    // node will write to localParticles array
+    Node(Node* parent, double* particles, unsigned nParticles, unsigned depth, double size, double center[3], unsigned* localParticles, unsigned nLocalParticles);
+    ~Node();
+private:
+    Node* root_;
+    Node* parent_;
+    Node* children_[8];
+    double* particles_;
+    unsigned nParticles_;
+    unsigned depth_;
+    double size_;
+    double center_[3];
+    unsigned* localParticles_;
+    unsigned nLocalParticles_;
+};
+
+#endif /* NODE_HPP */
\ No newline at end of file
diff --git a/lib/tree.cpp b/lib/tree.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..fe348c93ef470ad4a108e8997d7f0fd260396c6e
--- /dev/null
+++ b/lib/tree.cpp
@@ -0,0 +1,24 @@
+#include "tree.hpp"
+#include "node.hpp"
+
+Tree::Tree(double* particles, unsigned nParticles, double size, double* center) {
+    particles_ = particles;
+    nParticles_ = nParticles;
+    size_ = size;
+
+    for (unsigned i=0; i < 3; ++i) center_[i] = center[i];
+
+    unsigned* localParticles_ = new unsigned[nParticles_];
+    for (unsigned i=0; i < nParticles_; ++i) localParticles_[i] = i;
+    
+    root_ = new Node();
+    *root_ = Node(root_, particles_, nParticles_, 0, size_, center_, localParticles_, nParticles_);
+}
+
+Tree::~Tree() {
+    delete root_;
+}
+
+void Tree::update() {
+    // TODO
+}
\ No newline at end of file
diff --git a/lib/tree.hpp b/lib/tree.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..1da26c6905364150a3861a413799ab682023c005
--- /dev/null
+++ b/lib/tree.hpp
@@ -0,0 +1,23 @@
+#ifndef TREE_HPP
+#define TREE_HPP
+
+#include "node.hpp"
+
+class Tree {
+public:
+    // constructor
+    Tree() = delete;
+    Tree(double* particles, unsigned nParticles, double size, double* center);
+    // destructor
+    ~Tree();
+    // update tree: visit each node, check if it needs to be split or merged (for example if a particle has left the region)
+    void update();
+private:
+    Node* root_;
+    double* particles_;
+    unsigned nParticles_;
+    double size_;
+    double center_[3];
+};
+
+#endif /* TREE_HPP */
\ No newline at end of file