diff --git a/assets/icons/ellipsis.svg b/assets/icons/ellipsis.svg
new file mode 100644
index 00000000..f3113af9
--- /dev/null
+++ b/assets/icons/ellipsis.svg
@@ -0,0 +1,4 @@
+
diff --git a/assets/icons/panel-left.svg b/assets/icons/panel-left.svg
new file mode 100644
index 00000000..def688f3
--- /dev/null
+++ b/assets/icons/panel-left.svg
@@ -0,0 +1,3 @@
+
diff --git a/crates/common/src/lib.rs b/crates/common/src/lib.rs
index 56b5b4af..829c4676 100644
--- a/crates/common/src/lib.rs
+++ b/crates/common/src/lib.rs
@@ -1,5 +1,7 @@
pub use constants::*;
pub use paths::*;
+pub use utils::*;
mod constants;
mod paths;
+mod utils;
diff --git a/crates/common/src/utils.rs b/crates/common/src/utils.rs
new file mode 100644
index 00000000..b15a4582
--- /dev/null
+++ b/crates/common/src/utils.rs
@@ -0,0 +1,11 @@
+use nostr_sdk::prelude::*;
+
+pub fn shorten_pubkey(public_key: PublicKey, len: usize) -> String {
+ let Ok(pubkey) = public_key.to_bech32();
+
+ format!(
+ "{}:{}",
+ &pubkey[0..(len + 1)],
+ &pubkey[pubkey.len() - len..]
+ )
+}
diff --git a/crates/lume/src/panels/feed.rs b/crates/lume/src/panels/feed.rs
new file mode 100644
index 00000000..0d91aa27
--- /dev/null
+++ b/crates/lume/src/panels/feed.rs
@@ -0,0 +1,180 @@
+use std::time::Duration;
+
+use anyhow::Error;
+use gpui::prelude::FluentBuilder;
+use gpui::{
+ div, img, App, AppContext, Context, Entity, EventEmitter, FocusHandle, Focusable, IntoElement,
+ ParentElement, Render, SharedString, Styled, Task, Window,
+};
+use gpui_component::dock::{Panel, PanelEvent};
+use gpui_component::{h_flex, v_flex, ActiveTheme};
+use nostr_sdk::prelude::*;
+use person::PersonRegistry;
+use smallvec::{smallvec, SmallVec};
+use state::client;
+
+/// Feed
+pub struct Feed {
+ focus_handle: FocusHandle,
+
+ /// All notes that match the query
+ notes: Entity