diff --git a/Cargo.lock b/Cargo.lock
index 883d2ab8b80f374050c8c6298cda0f4be28dc2f9..75780af4db63c8076b956c6be3704f0fcca6f968 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -206,6 +206,56 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "anstream"
+version = "0.6.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is_terminal_polyfill",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
+dependencies = [
+ "windows-sys 0.59.0",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e"
+dependencies = [
+ "anstyle",
+ "once_cell",
+ "windows-sys 0.59.0",
+]
+
 [[package]]
 name = "anyhow"
 version = "1.0.95"
@@ -889,12 +939,39 @@ dependencies = [
  "unicode-width",
 ]
 
+[[package]]
+name = "colog"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c426b7af8d5e0ad79de6713996632ce31f0d68ba84068fb0d654b396e519df0"
+dependencies = [
+ "colored",
+ "env_logger",
+ "log",
+]
+
 [[package]]
 name = "color_quant"
 version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
 
+[[package]]
+name = "colorchoice"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
+
+[[package]]
+name = "colored"
+version = "2.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c"
+dependencies = [
+ "lazy_static",
+ "windows-sys 0.59.0",
+]
+
 [[package]]
 name = "combine"
 version = "4.6.7"
@@ -1293,6 +1370,18 @@ dependencies = [
  "winit",
 ]
 
+[[package]]
+name = "egui_logger"
+version = "0.6.2"
+source = "git+https://github.com/rnd-ash/egui_logger?branch=main#f274d8da2322b3d1bd02a7ff8f8ef025c33f24a9"
+dependencies = [
+ "chrono",
+ "egui",
+ "hashbrown 0.15.2",
+ "log",
+ "regex",
+]
+
 [[package]]
 name = "egui_tiles"
 version = "0.12.0"
@@ -1404,6 +1493,29 @@ dependencies = [
  "syn 2.0.95",
 ]
 
+[[package]]
+name = "env_filter"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0"
+dependencies = [
+ "log",
+ "regex",
+]
+
+[[package]]
+name = "env_logger"
+version = "0.11.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "env_filter",
+ "humantime",
+ "log",
+]
+
 [[package]]
 name = "epaint"
 version = "0.31.0"
@@ -2097,6 +2209,12 @@ version = "1.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
 
+[[package]]
+name = "humantime"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
+
 [[package]]
 name = "hyper"
 version = "0.14.32"
@@ -2394,6 +2512,12 @@ version = "2.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
 
+[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
+
 [[package]]
 name = "itertools"
 version = "0.10.5"
@@ -2674,9 +2798,9 @@ dependencies = [
 
 [[package]]
 name = "log"
-version = "0.4.22"
+version = "0.4.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
+checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f"
 
 [[package]]
 name = "longitude"
@@ -3014,16 +3138,6 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8"
 
-[[package]]
-name = "nu-ansi-term"
-version = "0.46.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
-dependencies = [
- "overload",
- "winapi",
-]
-
 [[package]]
 name = "num-bigint"
 version = "0.4.6"
@@ -3386,12 +3500,6 @@ dependencies = [
  "pin-project-lite",
 ]
 
-[[package]]
-name = "overload"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
-
 [[package]]
 name = "owned_ttf_parser"
 version = "0.25.0"
@@ -4366,15 +4474,6 @@ dependencies = [
  "digest",
 ]
 
-[[package]]
-name = "sharded-slab"
-version = "0.1.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
-dependencies = [
- "lazy_static",
-]
-
 [[package]]
 name = "shlex"
 version = "1.3.0"
@@ -4741,16 +4840,6 @@ dependencies = [
  "syn 2.0.95",
 ]
 
-[[package]]
-name = "thread_local"
-version = "1.1.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
-dependencies = [
- "cfg-if",
- "once_cell",
-]
-
 [[package]]
 name = "tiff"
 version = "0.9.1"
@@ -4976,32 +5065,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c"
 dependencies = [
  "once_cell",
- "valuable",
-]
-
-[[package]]
-name = "tracing-log"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
-dependencies = [
- "log",
- "once_cell",
- "tracing-core",
-]
-
-[[package]]
-name = "tracing-subscriber"
-version = "0.3.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008"
-dependencies = [
- "nu-ansi-term",
- "sharded-slab",
- "smallvec",
- "thread_local",
- "tracing-core",
- "tracing-log",
 ]
 
 [[package]]
@@ -5180,6 +5243,12 @@ version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
 
+[[package]]
+name = "utf8parse"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
+
 [[package]]
 name = "uuid"
 version = "1.11.0"
@@ -5197,12 +5266,6 @@ dependencies = [
  "wasm-bindgen",
 ]
 
-[[package]]
-name = "valuable"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
-
 [[package]]
 name = "vcpkg"
 version = "0.2.15"
@@ -6297,9 +6360,11 @@ dependencies = [
  "built",
  "chrono",
  "chrono-humanize",
+ "colog",
  "eframe",
  "egui",
  "egui_extras",
+ "egui_logger",
  "egui_tiles",
  "fern",
  "figment",
@@ -6313,8 +6378,6 @@ dependencies = [
  "rusqlite_migration",
  "serde",
  "tokio",
- "tracing",
- "tracing-subscriber",
  "walkers",
 ]
 
diff --git a/Cargo.toml b/Cargo.toml
index 6e3c3676f0bd1fe431ffceadad5d72edf3497fdf..9a0d36061cd968a5a691b676b8e944ec9ce74d7c 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,11 +7,9 @@ build = "build.rs"
 
 [dependencies]
 fern = "0.7.1"
-log = "0.4.22"
+log = "0.4.25"
 meshtastic = "0.1.6"
 tokio = "1.42.0"
-tracing = "0.1.41"
-tracing-subscriber = "0.3.19"
 rusqlite = { version = "0.32.1", features = ["bundled"] }
 rusqlite_migration = "1.3.1"
 lazy_static = "1.5.0"
@@ -23,13 +21,15 @@ chrono-humanize = "0.2.3"
 # gui
 eframe = { version = "0.31.0", features = ["wgpu"] }
 egui = "0.31.0"
-walkers = "0.34.0"
 egui_extras = { version = "0.31.0", features = ["all_loaders"] }
+egui_tiles = "0.12.0"
+egui_logger = { git = "https://github.com/rnd-ash/egui_logger", branch = "main" }
+walkers = "0.34.0"
 image = { version = "0.25", features = ["jpeg", "png", "webp"] }
 chrono = "0.4.39"
 longitude = "0.2.1"
-egui_tiles = "0.12.0"
+colog = "1.3.0"
 
 [build-dependencies]
 built = { version = "0.7.6", features = ["git2", "chrono"] }
-git2 = "0.20.0"
\ No newline at end of file
+git2 = "0.20.0"
diff --git a/docs/gui.md b/docs/gui.md
index a114ee8ab03978c6bedf4eecb793ae7a4002e7de..59aa0080364db6e37153b615688656c39a8e24d5 100644
--- a/docs/gui.md
+++ b/docs/gui.md
@@ -11,4 +11,6 @@
 - 'Tiling' UI, make it piss easy to change the UI to each user's liking.
     - Pop out windows to new ones? Can we also tile them??
     - List of Presets, with naming?
-    - One single context/alt/top bar for file, edit, whatever.
\ No newline at end of file
+    - One single context/alt/top bar for file, edit, whatever.
+- Logging view
+    - https://github.com/RegenJacob/egui_logger
\ No newline at end of file
diff --git a/src/config.rs b/src/config.rs
index 1ec16916530e651dca3a66119aae1288234f6f31..7deb82fc96bf3a525d48f5d0ee5e275c7abf989c 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -1,4 +1,3 @@
-use longitude::DistanceUnit;
 use serde::Deserialize;
 
 /// Holds the individual config segments.
diff --git a/src/db.rs b/src/db.rs
index 0acdbed01a6f8a07f544c551d9842eb47e757531..35fab6ac9f21dcfa9ff55884993c6be87be0ee8e 100644
--- a/src/db.rs
+++ b/src/db.rs
@@ -1,15 +1,14 @@
-use std::path::{Path, PathBuf};
+use std::path::PathBuf;
 use std::fs::File;
-use std::io;
 
-use meshtastic::protobufs::config::{BluetoothConfig, DeviceConfig, DisplayConfig, LoRaConfig, NetworkConfig, PayloadVariant, PositionConfig, PowerConfig};
+use meshtastic::protobufs::config::{BluetoothConfig, DeviceConfig, DisplayConfig, LoRaConfig, NetworkConfig, PositionConfig, PowerConfig};
 use meshtastic::protobufs::module_config::{AmbientLightingConfig, AudioConfig, CannedMessageConfig, DetectionSensorConfig, ExternalNotificationConfig, MqttConfig, NeighborInfoConfig, PaxcounterConfig, RangeTestConfig, RemoteHardwareConfig, SerialConfig, StoreForwardConfig, TelemetryConfig};
 use rusqlite::{Connection, Result};
 use rusqlite_migration::{Migrations, M};
 use serde::{Deserialize, Serialize};
-use tracing::{debug, error, info};
+use log::{error, warn, info, debug, trace};
 use lazy_static::lazy_static;
-use meshtastic::protobufs::{Channel, Data, DeviceMetrics, MeshPacket, MyNodeInfo, NodeInfo, Position, User};
+use meshtastic::protobufs::{Channel, DeviceMetrics, MeshPacket, MyNodeInfo, NodeInfo, Position, User};
 
 use crate::CONFIG;
 
@@ -25,7 +24,7 @@ lazy_static! {
     ]);
 }
 
-fn u32_vec_to_u8_vec(vec: &Vec<u32>) -> Vec<u8> {
+fn u32_vec_to_u8_vec(vec: &[u32]) -> Vec<u8> {
     vec.iter()
         .flat_map(|x| x.to_be_bytes().to_vec())
         .collect()
diff --git a/src/gui/context_menu.rs b/src/gui/menus.rs
similarity index 100%
rename from src/gui/context_menu.rs
rename to src/gui/menus.rs
diff --git a/src/gui/mod.rs b/src/gui/mod.rs
index abc0769f328873a3bd40c3843ab0852016cc4be0..f77847c1d7655d1bc53b4b89d071010ad46f95c7 100644
--- a/src/gui/mod.rs
+++ b/src/gui/mod.rs
@@ -1,13 +1,16 @@
 pub mod widgets;
 use crate::gui::widgets::WidgetType::About;
-use egui::{menu, Color32, FontDefinitions};
-use egui_tiles::{SimplificationOptions, Tile, TileId, Tiles};
-use tracing::debug;
+use egui::{Ui, menu, Color32, FontDefinitions};
+use egui_tiles::{Container, SimplificationOptions, Tile, TileId, Tiles};
+use log::{error, warn, info, debug, trace};
+use widgets::about;
 
 /// Runs the actual GUI.
 /// We contruct the empty tree, headers and basic window stuff here.
 /// Widgets are all opened via this, or loaded from a saved state.
 pub(crate) async fn run_gui() -> Result<(), eframe::Error> {
+    // Start Logging
+    egui_logger::builder().init().expect("Error initialising egui_logger");
     debug!("Running in GUI Mode!");
     // run actual ui
     let options = eframe::NativeOptions {
@@ -34,13 +37,29 @@ pub(crate) async fn run_gui() -> Result<(), eframe::Error> {
 /// This allows us to add new widgets into the UI.
 impl YamsApp {
     // Add a new pane to the tree, depending on the widget_type.
-    fn add_about(&mut self, widget_type: widgets::WidgetType,) {
-        // Find the next free id. (maybe?)
+    fn add_widget(&mut self, widget_type: widgets::WidgetType,) {
+        // Find the next view number we can use
         let next_view_num = self.tree.tiles.next_free_id().0 as usize;
+
         // Create a new pane with said view number.
-        let pane = Pane::with_nr(next_view_num, widget_type);
-        // Insert it!
-        let _ = self.tree.tiles.insert_pane(pane);
+        let pane = Pane::with_nr(next_view_num, widget_type.clone());
+        
+        // Insert it into the tree
+        let pane_id = self.tree.tiles.insert_pane(pane);
+        // debug!("Inserted pane: {:#?}", pane);
+
+
+        // Add the new pane to the root tab tile if possible.
+        if let Some(root_id) = self.tree.root() {
+            // Modify the tile if it's a container and supports children.
+            if let Some(root_tile) = self.tree.tiles.get_mut(root_id) {
+                if let Tile::Container(container) = root_tile {
+                    if let Container::Tabs(tabs) = container {
+                        tabs.children.push(pane_id);
+                    }
+                }
+            }
+        }
     }
 }
 
@@ -51,13 +70,16 @@ impl Default for YamsApp {
     fn default() -> Self {
         // Initialize a variable to keep track of the next view number
         let mut next_view_nr = 0;
-        // Define a closure that will create a new Pane with a unique view number
-        // and increment the next_view_nr variable for the next time it's called
-        let mut gen_view = || {
-            let view = Pane::with_nr(next_view_nr, widgets::WidgetType::NodeList);
-            next_view_nr += 1;
-            view
-        };
+        
+        // Closure (fancy function?) to create new Panes
+        // let mut gen_view = || {
+        //     let view = Pane::with_nr(next_view_nr, widgets::WidgetType::About);
+        //     next_view_nr += 1;
+        //     view
+        // };
+        // Create new panes for default
+        // let about_view = Pane::with_nr(next_view_nr+1, widgets::WidgetType::About);
+        let nodelist_view = Pane::with_nr(next_view_nr+1, widgets::WidgetType::NodeList);
 
         // Create an empty tiles structure to store a tile (which can contain more tiles)
         let mut tiles = egui_tiles::Tiles::default();
@@ -65,33 +87,9 @@ impl Default for YamsApp {
         // Vector to hold the ids of our tabs
         let mut tabs = vec![];
 
-        // Insert a tab tile with 7 children into our tiles and push its id onto the tabs vector
-        let tab_tile = {
-            let children = (0..7).map(|_| tiles.insert_pane(gen_view())).collect();
-            tiles.insert_tab_tile(children)
-        };
-        tabs.push(tab_tile);
-
-        // Insert a horizontal tile with 7 children into our tiles and push its id onto the tabs vector
-        tabs.push({
-            let children = (0..7).map(|_| tiles.insert_pane(gen_view())).collect();
-            tiles.insert_horizontal_tile(children)
-        });
-
-        // Insert a vertical tile with 7 children into our tiles and push its id onto the tabs vector
-        tabs.push({
-            let children = (0..7).map(|_| tiles.insert_pane(gen_view())).collect();
-            tiles.insert_vertical_tile(children)
-        });
-
-        // Insert a grid tile with 11 cells into our tiles and push its id onto the tabs vector
-        tabs.push({
-            let cells = (0..11).map(|_| tiles.insert_pane(gen_view())).collect();
-            tiles.insert_grid_tile(cells)
-        });
-
         // Insert a single pane tile into our tiles and push its id onto the tabs vector
-        tabs.push(tiles.insert_pane(gen_view()));
+        // tabs.push(tiles.insert_pane(about_view));
+        tabs.push(tiles.insert_pane(nodelist_view));
 
         // Insert a tab tile with all of our tabs as children into our tiles
         let root = tiles.insert_tab_tile(tabs);
@@ -100,10 +98,12 @@ impl Default for YamsApp {
         let tree = egui_tiles::Tree::new("my_tree", root, tiles);
 
         // Return a new YamsApp instance with our tree and default behavior
-        Self {
+        let self_state = Self {
             tree,
             behavior: Default::default(),
-        }
+        };
+        debug!("Full YamsApp default state: {:#?}", &self_state);
+        self_state
     }
 }
 
@@ -144,6 +144,7 @@ impl Pane {
 }
 
 // The storage for the Tree Behaviour config options
+#[derive(Debug)]
 struct TreeBehavior {
     simplification_options: egui_tiles::SimplificationOptions,
     tab_bar_height: f32,
@@ -290,16 +291,16 @@ impl egui_tiles::Behavior<Pane> for TreeBehavior {
                 Tile::Pane(pane) => {
                     // Single pane removal
                     let tab_title = self.tab_title_for_pane(pane);
-                    log::debug!("Closing tab: {}, tile ID: {tile_id:?}", tab_title.text());
+                    debug!("Closing tab: {}, tile ID: {tile_id:?}", tab_title.text());
                 }
                 Tile::Container(container) => {
                     // Container removal
-                    log::debug!("Closing container: {:?}", container.kind());
+                    debug!("Closing container: {:?}", container.kind());
                     let children_ids = container.children();
                     for child_id in children_ids {
                         if let Some(Tile::Pane(pane)) = tiles.get(*child_id) {
                             let tab_title = self.tab_title_for_pane(pane);
-                            log::debug!("Closing tab: {}, tile ID: {tile_id:?}", tab_title.text());
+                            debug!("Closing tab: {}, tile ID: {tile_id:?}", tab_title.text());
                         }
                     }
                 }
@@ -311,7 +312,7 @@ impl egui_tiles::Behavior<Pane> for TreeBehavior {
     }
 }
 
-#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
+#[derive(Debug)]
 struct YamsApp {
     tree: egui_tiles::Tree<Pane>,
 
@@ -336,8 +337,30 @@ impl eframe::App for YamsApp {
 
                 // List of widgets here, we can add new widgets into the panel from here!
                 ui.menu_button("Widgets", |ui| {
-                    // Nested menus here
-                    // Add Widget -> Widget Selector
+                    // make a add widget button for every single widget type
+                    ui.menu_button("Add Widget", |ui| {
+                        if ui.button("About YAMS").clicked() {
+                            self.add_widget(widgets::WidgetType::About);
+                        }
+                        if ui.button("Node List").clicked() {
+                            self.add_widget(widgets::WidgetType::NodeList);
+                        }
+                        if ui.button("Node Info").clicked() {
+                            self.add_widget(widgets::WidgetType::NodeInfo);
+                        }
+                        if ui.button("Logs").clicked() {
+                            self.add_widget(widgets::WidgetType::Log);
+                        }
+                        if ui.button("Map View").clicked() {
+                            self.add_widget(widgets::WidgetType::MapView);
+                        }
+                        if ui.button("Settings").clicked() {
+                            self.add_widget(widgets::WidgetType::Settings);
+                        }
+                        if ui.button("Signal Strength").clicked() {
+                            self.add_widget(widgets::WidgetType::SignalStrengthHistorical);
+                        }
+                    })
                 });
 
                 // UI Tools (reset, split? layouts?)
@@ -353,8 +376,7 @@ impl eframe::App for YamsApp {
                     }
                     if ui.button("About").clicked() {
                         // Create a new about widget (don't show it in the widgets menu?)
-                        // TODO: THIS DOES NOT WORK!
-                        self.add_about(widgets::WidgetType::About);
+                        self.add_widget(widgets::WidgetType::About);
                         
                     }
                 });
@@ -403,7 +425,7 @@ fn tree_ui(
 
     // Temporarily remove the tile to circumvent the borrowchecker
     let Some(mut tile) = tiles.remove(tile_id) else {
-        log::debug!("Missing tile {tile_id:?}");
+        debug!("Missing tile {tile_id:?}");
         return;
     };
 
@@ -443,4 +465,4 @@ fn tree_ui(
 
     // Put the tile back
     tiles.insert(tile_id, tile);
-}
+}
\ No newline at end of file
diff --git a/src/gui/widgets/about.rs b/src/gui/widgets/about.rs
index 3d34b741f8427e63cb8c25a7a69ae22bfa613c1d..3ee4b8ee9487fc2a8b6180640efd6b9261b5e631 100644
--- a/src/gui/widgets/about.rs
+++ b/src/gui/widgets/about.rs
@@ -9,7 +9,6 @@ use crate::built_info;
 /// - link to repo
 /// - contributors
 /// - random shit
-
 pub fn about_ui(ui: &mut egui::Ui) {
     // Show cool ascii logo
     // TODO: make this not wrap or truncate with ...
diff --git a/src/gui/widgets/log.rs b/src/gui/widgets/log.rs
deleted file mode 100644
index 67d043278fc397c5c6e0c6986cb7a40c2936d996..0000000000000000000000000000000000000000
--- a/src/gui/widgets/log.rs
+++ /dev/null
@@ -1,3 +0,0 @@
-/// This widget shows all log output from the program.
-/// You should be able to open multiple of these, so we can have "Serial Log" and "YAMS Log" as two separate instances of this widget.
-/// Filtering by log level?
\ No newline at end of file
diff --git a/src/gui/widgets/logging.rs b/src/gui/widgets/logging.rs
new file mode 100644
index 0000000000000000000000000000000000000000..b9ed7482eb03ec34ec6f73a359e82a72ea6414d0
--- /dev/null
+++ b/src/gui/widgets/logging.rs
@@ -0,0 +1,10 @@
+// This widget shows all log output from the program.
+// You should be able to open multiple of these, so we can have "Serial Log" and "YAMS Log" as two separate instances of this widget.
+// Filtering by log level?
+
+use egui;
+
+pub fn log_ui(ui: &mut egui::Ui) {
+    // Ensure that `egui_logger::logger_ui()` returns an object compatible with `&mut egui::Ui`
+    egui_logger::logger_ui().enable_ctx_menu(true).show(ui);
+}
\ No newline at end of file
diff --git a/src/gui/widgets/mod.rs b/src/gui/widgets/mod.rs
index e1d6d30c2c2ddaf0f62b828cafc451c2edf79564..f048c5894a291642f4bdbc0d15ca323caa1215eb 100644
--- a/src/gui/widgets/mod.rs
+++ b/src/gui/widgets/mod.rs
@@ -3,6 +3,8 @@
 use std::fmt;
 pub mod about;
 pub mod node_list;
+pub mod node_info;
+pub mod logging;
 
 #[derive(Clone)]
 pub(crate) enum WidgetType {
@@ -39,7 +41,9 @@ pub fn render_widget(widget_type: &WidgetType, ui: &mut egui::Ui) {
             node_list::nodelist_ui(ui);
         },
         WidgetType::NodeInfo => todo!(),
-        WidgetType::Log => todo!(),
+        WidgetType::Log => {
+            logging::log_ui(ui);
+        },
         WidgetType::MapView => todo!(),
         WidgetType::Settings => todo!(),
         WidgetType::SignalStrengthHistorical => todo!(),
diff --git a/src/gui/widgets/node_info.rs b/src/gui/widgets/node_info.rs
new file mode 100644
index 0000000000000000000000000000000000000000..b8d10d3e2248f47313a3481d6bf33e83e5b91d20
--- /dev/null
+++ b/src/gui/widgets/node_info.rs
@@ -0,0 +1,143 @@
+use chrono::DateTime;
+use chrono_humanize::HumanTime;
+use egui_extras::{Column, TableBuilder};
+use longitude::{DistanceUnit, Location};
+use meshtastic::protobufs::{channel::Role, HardwareModel, Position};
+
+use crate::{db::Database, CONFIG};
+
+use super::node_list;
+
+// This handles viewing information about a specific node.
+// Shows:
+// - All the normal info from a node
+// - Location History on a map?
+// - Recent Messages?
+// - Neighbours?
+// - Battery Graph
+// - Environmental Graph
+// - First Seen / Last Heard
+// - Distance
+
+/// UI Elements for the Node List
+pub fn nodeinfo_ui(ui: &mut egui::Ui) {
+    // Get nodes from DB
+    let mut nodes = Database::read_node_list().expect("Failed to read nodes");
+    
+    // Sort nodes by `last_heard` in descending order
+    nodes.sort_by(|a, b| b.last_heard.cmp(&a.last_heard));
+    
+    TableBuilder::new(ui)
+    // TODO for the table:
+    // - Clickable Table Sorting
+    // - Add more info
+    // - Auto hide/show scrollbar on smaller devices
+    // - Add to a panel that we can move around / shitty windowing.
+        .column(Column::remainder())            // node id
+        .column(Column::remainder().clip(true)) // node name
+        .column(Column::remainder())            // snr
+        .column(Column::remainder())            // dist
+        .column(Column::remainder())            // hops
+        .column(Column::remainder().clip(true))            // hw model
+        .column(Column::remainder())            // role
+        .column(Column::remainder())            // battery
+        .column(Column::remainder().clip(true))            // last heard
+        .striped(true)
+        .header(15.0, |mut header| {
+            header.col(|ui| {
+                ui.heading("Node ID");
+            });
+            header.col(|ui| {
+                ui.heading("Name");
+            });
+            header.col(|ui| {
+                ui.heading("SNR");
+            });
+            header.col(|ui| {
+            
+                // Get distance units
+                let unit = match CONFIG.gui.units.as_ref() {
+                    "Centimeters" => "cm",
+                    "Meters" => "m",
+                    "Kilometers" => "km",
+                    "Inches" => "in",
+                    "Feet" => "ft",
+                    "Yards" => "yd",
+                    "Miles" => "mi",
+                    _ => "km", // Default to km if no match found.
+                };
+            
+                ui.heading(format!("Distance ({})", unit));
+            });
+            header.col(|ui| {
+                ui.heading("Hops Away");
+            });
+            header.col(|ui| {
+                ui.heading("HW Model");
+            });
+            header.col(|ui| {
+                ui.heading("Role");
+            });
+            header.col(|ui| {
+                ui.heading("Battery");
+            });
+            header.col(|ui| {
+                ui.heading("Last Heard");
+            });
+        })
+        .body(|mut body| {
+            for node in nodes {
+                let user = node.user.unwrap();
+                let device = node.device_metrics.unwrap();
+                // Convert the last heard to a time, then make it nice to read.
+                let now = chrono::Local::now().to_utc();
+                let humanised = if node.last_heard == 0 {
+                    String::from("Unknown")
+                } else {
+                    let last_heard = DateTime::from_timestamp(node.last_heard.into(), 0).unwrap();
+                    let duration = last_heard - now;
+                    HumanTime::from(duration).to_string()
+                };
+            
+                body.row(15.0, |mut row| {
+                    row.col(|ui| {
+                        ui.label(user.id);
+                    });
+                    row.col(|ui| {
+                        ui.label(format!("{} ({})", user.long_name, user.short_name));
+                    });
+                    row.col(|ui| {
+                        ui.label(node.snr.to_string());
+                    });
+                    row.col(|ui| {
+                        if let Some(distance) = node_list::calc_distance_to_node(node.position.unwrap()) {
+                            if distance.is_nan() {
+                                ui.label("-");
+                            } else {
+                                ui.label(format!("{:.2}", distance));
+                            }
+                        } else {
+                            ui.label("-");
+                        }
+                    });
+                    row.col(|ui| {
+                        ui.label(node.hops_away.to_string());
+                    });
+                    row.col(|ui| {
+                        // Convert the i32 to a HardwareModel object, then convert to string
+                        ui.label(HardwareModel::from_i32(user.hw_model).unwrap_or_default().as_str_name());
+                    });
+                    row.col(|ui| {
+                        // Convert the i32 to a Role object, convert to string.
+                        ui.label(Role::from_i32(user.role).unwrap_or_default().as_str_name());
+                    });
+                    row.col(|ui| {
+                        ui.label(device.battery_level.to_string());
+                    });
+                    row.col(|ui| {
+                        ui.label(humanised);
+                    });
+                });
+            }
+        });
+}
\ No newline at end of file
diff --git a/src/gui/widgets/node_list.rs b/src/gui/widgets/node_list.rs
index 0206c341d7b7e109c82583cdd2e368c095f74a18..ef020318253f4f866e724d54ccf5be2b2db9be97 100644
--- a/src/gui/widgets/node_list.rs
+++ b/src/gui/widgets/node_list.rs
@@ -17,7 +17,7 @@ use crate::{db::Database, CONFIG};
 // - Location (has/doesn't have gps location)
 
 /// Calculates the distance betwen 2 coordinate points.
-fn calc_distance_to_node(away: Position) -> Option<f64> {
+pub(crate) fn calc_distance_to_node(away: Position) -> Option<f64> {
     let home_pos = Database::read_home_node().expect("Failed to find Home Node").position.unwrap();
 
     let distance = Location {
diff --git a/src/main.rs b/src/main.rs
index 5d6934eed3621cdec8ecb6a0e1bb84bf99604250..bc12fa3a0b55c772ebf33e3af2b0d7ba6e986c13 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -3,14 +3,11 @@ use std::{env, process};
 use figment::{Figment, providers::{Format, Toml, Env}};
 
 use lazy_static::lazy_static;
-use meshtastic::api::{StreamApi, StreamHandle};
+use meshtastic::api::StreamApi;
 use meshtastic::utils;
-use meshtastic::protobufs::*;
 
 use packets::parse;
-use tokio::{net::TcpStream, sync::mpsc::UnboundedReceiver};
-use tracing::{debug, error, info, Level};
-use tracing_subscriber::FmtSubscriber;
+use log::{error, warn, info, debug, trace};
 
 mod nodes;
 mod packets;
@@ -30,19 +27,20 @@ lazy_static! {
             .merge(Env::prefixed("yamm_"))
             .extract()
             .unwrap_or_default();
-        tracing::info!("Loaded Config!");
-        tracing::debug!("full config: {:?}", config);
+        info!("Loaded Config!");
+        debug!("full config: {:?}", config);
         config
     };
 }
 
 async fn run_server() {
+    // Start Logging
+    colog::init();
+
     // set up new connection
     let stream_api = StreamApi::new();
 
     // Different connection types have different setups.
-    let mut tcp_stream: StreamHandle<TcpStream>;
-    //let mut serial_stream: StreamHandle<SerialStream>; // SerialStream isn't a valid type???
     match &CONFIG.meshconfig.connection_type {
         config::ConnectionType::Tcp => {
             // Build the tcp stream object from config.
@@ -83,25 +81,13 @@ async fn run_server() {
 
 #[tokio::main]
 async fn main() -> Result<(), Box<dyn std::error::Error>> {
-    // Initialise Logging - this isn't final.
-    let subscriber = FmtSubscriber::builder()
-        // all events higher than debug are shown
-        .with_max_level(Level::DEBUG)
-        .finish();
-    tracing::subscriber::set_global_default(subscriber)
-        .expect("setting default subscriber failed");
-
-    // Hello World!
-    info!("Y(et) A(nother) M(eshtastic) S(erver) - v0.1.0");
-
-
     // Do we run a server or gui?
     let args: Vec<String> = env::args().collect();
 
     // display help on no args, exit.
     if args.len() < 2 {
-        info!("Usage: yams <mode>");
-        info!("Modes: 'server', 'gui'");
+        println!("Usage: yams <mode>");
+        println!("Modes: 'server', 'gui'");
         process::exit(1);
     }
 
@@ -110,9 +96,9 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
         "server" => run_server().await,
         "gui" => gui::run_gui().await.expect("uh oh"),
         _ => {
-            error!("Unknown mode: {}", args[1]);
-            info!("Usage: yams <mode>");
-            info!("Modes: 'server', 'gui'");
+            eprintln!("Unknown mode: {}", args[1]);
+            println!("Usage: yams <mode>");
+            println!("Modes: 'server', 'gui'");
             process::exit(1);
         }
     }
diff --git a/src/packets.rs b/src/packets.rs
index d5fd3a0c1f3b51ed9530ea6b56a5e209b1bc18ed..9d5aad7174cc466bb4e6b09fb6bc90076e5b0668 100644
--- a/src/packets.rs
+++ b/src/packets.rs
@@ -1,10 +1,6 @@
-use std::path::Path;
-
-use config::device_config;
 use from_radio::PayloadVariant;
-use log::info;
-use meshtastic::protobufs::{config::device_config::Role, *};
-use tracing::{debug, error};
+use meshtastic::protobufs::*;
+use log::{error, warn, info, debug, trace};
 
 use crate::db::Database;