diff --git a/src/database/entities/channel.rs b/src/database/entities/channel.rs
index 704d743c67cca3b59f10ad342a080cdd516078de..3919dc18750fd333b352772291e9362ca9f7af0e 100644
--- a/src/database/entities/channel.rs
+++ b/src/database/entities/channel.rs
@@ -50,6 +50,18 @@ pub enum Channel {
         #[serde(skip_serializing_if = "Option::is_none")]
         last_message: Option<LastMessage>,
     },
+    TextChannel {
+        #[serde(rename = "_id")]
+        id: String,
+        server: String,
+        #[serde(skip_serializing_if = "Option::is_none")]
+        nonce: Option<String>,
+
+        name: String,
+        description: Option<String>,
+        #[serde(skip_serializing_if = "Option::is_none")]
+        icon: Option<File>,
+    }
 }
 
 impl Channel {
@@ -57,7 +69,8 @@ impl Channel {
         match self {
             Channel::SavedMessages { id, .. }
             | Channel::DirectMessage { id, .. }
-            | Channel::Group { id, .. } => id,
+            | Channel::Group { id, .. }
+            | Channel::TextChannel { id, .. } => id,
         }
     }
 
diff --git a/src/database/entities/server.rs b/src/database/entities/server.rs
index 236bb5d0f7fc80e6ddc0b7377006aea674b719eb..b0fc2a1401167ccae658b2fe6b337e354385ebb3 100644
--- a/src/database/entities/server.rs
+++ b/src/database/entities/server.rs
@@ -43,9 +43,10 @@ pub struct Server {
 
     pub name: String,
     // pub default_permissions: u32,
-    pub channels: Vec<String>,
     // pub invites: Vec<Invite>,
     // pub bans: Vec<Ban>,
+    pub channels: Vec<String>,
+
     #[serde(skip_serializing_if = "Option::is_none")]
     pub icon: Option<File>,
     #[serde(skip_serializing_if = "Option::is_none")]
diff --git a/src/database/permissions/channel.rs b/src/database/permissions/channel.rs
index 2009bb4e4a58eca1f85aa8eb4946115463d9921b..e4f27d57ebcd1b39c91f102d930181e972ccfcaa 100644
--- a/src/database/permissions/channel.rs
+++ b/src/database/permissions/channel.rs
@@ -81,6 +81,9 @@ impl<'a> PermissionCalculator<'a> {
                     Ok(0)
                 }
             }
+            Channel::TextChannel { .. } => {
+                Ok(ChannelPermission::View + ChannelPermission::SendMessage)
+            }
         }
     }
 
diff --git a/src/notifications/events.rs b/src/notifications/events.rs
index 4e401cf9d4046bd76ce70e07d64c4d2e963a6fa3..3a118bee6e96f63eef5f8178a96d32b824b18367 100644
--- a/src/notifications/events.rs
+++ b/src/notifications/events.rs
@@ -143,6 +143,18 @@ impl ClientboundNotification {
                 .ok();
         });
     }
+
+    pub fn publish_to(self, channel: &Channel) {
+        // ! FIXME: update all for channel
+        // ! FIXME: temporary solution for pushing to guilds
+        self.publish(
+            if let Channel::TextChannel { server, .. } = channel {
+                server.clone()
+            } else {
+                channel.id().to_string()
+            }
+        )
+    }
 }
 
 pub fn prehandle_hook(notification: &ClientboundNotification) {
@@ -161,6 +173,7 @@ pub fn prehandle_hook(notification: &ClientboundNotification) {
                         subscribe_if_exists(recipient.clone(), channel_id.to_string()).ok();
                     }
                 }
+                _ => {}
             }
         }
         ClientboundNotification::ServerMemberJoin { id, user } => {
diff --git a/src/routes/channels/delete_channel.rs b/src/routes/channels/delete_channel.rs
index 9575ae61d700d90675607770ab59b105f0e2db92..1885048c95fecf3996ab58dcc0bb77d767c1597d 100644
--- a/src/routes/channels/delete_channel.rs
+++ b/src/routes/channels/delete_channel.rs
@@ -108,5 +108,6 @@ pub async fn req(user: User, target: Ref) -> Result<()> {
 
             Ok(())
         }
+        Channel::TextChannel { .. } => unimplemented!()
     }
 }
diff --git a/src/routes/servers/server_create.rs b/src/routes/servers/server_create.rs
index 96a2f8c058ebc93f2f7c3e0bef3f1cb872097ccd..b299ae4ce9bea82273ee277ac377ff1e3d7e135b 100644
--- a/src/routes/servers/server_create.rs
+++ b/src/routes/servers/server_create.rs
@@ -39,13 +39,24 @@ pub async fn req(user: User, info: Json<Data>) -> Result<JsonValue> {
     }
 
     let id = Ulid::new().to_string();
+    let cid = Ulid::new().to_string();
+    
+    Channel::TextChannel {
+        id: cid.clone(),
+        server: id.clone(),
+        nonce: Some(info.nonce.clone()),
+        name: "general".to_string(),
+        description: None,
+        icon: None,
+    }.publish().await?;
+
     let server = Server {
         id: id.clone(),
         nonce: Some(info.nonce.clone()),
         owner: user.id.clone(),
 
         name: info.name.clone(),
-        channels: vec![],
+        channels: vec![ cid ],
 
         icon: None,
         banner: None,