diff --git a/README.md b/README.md
index 8f34853..d83568d 100644
--- a/README.md
+++ b/README.md
@@ -67,7 +67,6 @@ Potential improvements:
 - [Application] Allow user-provided TLS certificate.
 - [Distribution] Flatpack release.
 - [Distribution] compiled binary in GitHub release.
-- [UI] Sort bookmarks.
 
 Things to consider:
 
@@ -77,6 +76,7 @@ Things to consider:
 - [Application] Consider leveraging linkding's `/check` endpoint when adding bookmarks.
 - [Application] Do not block on when executing local database queries.
 - [UI] Loading indicator when performing long HTTP calls.
+- [UI] Dynamically generate tags that affect filter.
 
 ## Thanks
 
diff --git a/i18n/en/cosmicding.ftl b/i18n/en/cosmicding.ftl
index 486bf04..c72ed5f 100644
--- a/i18n/en/cosmicding.ftl
+++ b/i18n/en/cosmicding.ftl
@@ -9,6 +9,10 @@ added-bookmark-to-account = Added bookmark {$bkmrk} to {$acc}
 api-key = API Key
 appearance = Appearance
 archived = Archived
+bookmark-date-newest = Newest First
+bookmark-date-oldest = Oldest First
+bookmark-alphabetical-ascending = A-Z (Bookmark Title) 
+bookmark-alphabetical-descending = Z-A (Bookmark Title) 
 bookmarks = Bookmarks
 bookmarks-with-count = Bookmarks ({$count})
 cancel = Cancel
@@ -59,6 +63,7 @@ settings = Settings
 shared = Shared
 shared-disabled = Shared (Disabled)
 snapshot = Snapshot
+sort = Sort
 successful = successful
 tags = Tags
 tags-subtext = Enter any number of tags separated by space.
diff --git a/res/screenshots/bookmarks.png b/res/screenshots/bookmarks.png
index 8d3b1f4..d6158a4 100644
Binary files a/res/screenshots/bookmarks.png and b/res/screenshots/bookmarks.png differ
diff --git a/src/app.rs b/src/app.rs
index 91f9d11..01e2c64 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -1,4 +1,4 @@
-use crate::config::{AppTheme, Config, CONFIG_VERSION};
+use crate::config::{AppTheme, Config, SortOption, CONFIG_VERSION};
 use crate::db::{self, SqliteDatabase};
 use crate::fl;
 use crate::http::{self};
@@ -102,6 +102,7 @@ pub enum Message {
     SetBookmarkTitle(String),
     SetBookmarkURL(String),
     SetBookmarkUnread(bool),
+    SortOption(SortOption),
     StartRefreshAccountProfile(Account),
     StartRefreshBookmarksForAccount(Account),
     StartRefreshBookmarksForAllAccounts,
@@ -197,6 +198,7 @@ impl Application for Cosmicding {
             &self.key_binds,
             !self.accounts_view.accounts.is_empty(),
             !self.bookmarks_view.bookmarks.is_empty(),
+            self.config.sort_option,
         )]
     }
 
@@ -366,6 +368,12 @@ impl Application for Cosmicding {
                 config_set!(app_theme, app_theme);
                 return self.update_config();
             }
+            Message::SortOption(sort_option) => {
+                config_set!(sort_option, sort_option);
+                if !self.bookmarks_view.bookmarks.is_empty() {
+                    return self.update(Message::LoadBookmarks);
+                }
+            }
             Message::SystemThemeModeChange => {
                 return self.update_config();
             }
@@ -894,6 +902,40 @@ impl Application for Cosmicding {
             Message::LoadBookmarks => {
                 self.bookmarks_view.bookmarks =
                     block_on(async { db::SqliteDatabase::fetch_bookmarks(&mut self.db).await });
+                match self.config.sort_option {
+                    SortOption::BookmarksDateNewest => {
+                        self.bookmarks_view.bookmarks.sort_by(|a, b| {
+                            b.clone()
+                                .date_added
+                                .unwrap()
+                                .cmp(&a.clone().date_added.unwrap())
+                        });
+                    }
+                    SortOption::BookmarksDateOldest => {
+                        self.bookmarks_view.bookmarks.sort_by(|a, b| {
+                            a.clone()
+                                .date_added
+                                .unwrap()
+                                .cmp(&b.clone().date_added.unwrap())
+                        });
+                    }
+                    SortOption::BookmarkAlphabeticalAscending => {
+                        self.bookmarks_view.bookmarks.sort_by(|a, b| {
+                            a.clone()
+                                .title
+                                .to_lowercase()
+                                .cmp(&b.clone().title.to_lowercase())
+                        });
+                    }
+                    SortOption::BookmarkAlphabeticalDescending => {
+                        self.bookmarks_view.bookmarks.sort_by(|a, b| {
+                            b.clone()
+                                .title
+                                .to_lowercase()
+                                .cmp(&a.clone().title.to_lowercase())
+                        });
+                    }
+                }
             }
             Message::StartupCompleted => {
                 for account in self.accounts_view.accounts.clone() {
@@ -901,6 +943,7 @@ impl Application for Cosmicding {
                 }
                 commands.push(Task::perform(
                     async {
+                        // Initial delay for refresh
                         tokio::time::sleep(Duration::from_secs(1)).await;
                         crate::app::Message::StartRefreshBookmarksForAllAccounts
                     },
@@ -1030,6 +1073,7 @@ pub enum MenuAction {
     Empty,
     RefreshBookmarks,
     Settings,
+    SetSortBookmarks(SortOption),
 }
 
 impl _MenuAction for MenuAction {
@@ -1043,6 +1087,7 @@ impl _MenuAction for MenuAction {
             MenuAction::Settings => Message::ToggleContextPage(ContextPage::Settings),
             MenuAction::AddBookmark => Message::AddBookmarkForm,
             MenuAction::RefreshBookmarks => Message::StartRefreshBookmarksForAllAccounts,
+            MenuAction::SetSortBookmarks(option) => Message::SortOption(*option),
         }
     }
 }
diff --git a/src/config.rs b/src/config.rs
index 932b2da..5796855 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -31,16 +31,26 @@ impl AppTheme {
     }
 }
 
+#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
+pub enum SortOption {
+    BookmarksDateNewest,
+    BookmarksDateOldest,
+    BookmarkAlphabeticalAscending,
+    BookmarkAlphabeticalDescending,
+}
+
 #[derive(Debug, Clone, CosmicConfigEntry, Eq, PartialEq)]
 #[version = 1]
 pub struct Config {
     pub app_theme: AppTheme,
+    pub sort_option: SortOption,
 }
 
 impl Default for Config {
     fn default() -> Self {
         Self {
             app_theme: AppTheme::System,
+            sort_option: SortOption::BookmarksDateNewest,
         }
     }
 }
diff --git a/src/menu.rs b/src/menu.rs
index 2ca4cd5..a1a75f4 100644
--- a/src/menu.rs
+++ b/src/menu.rs
@@ -1,5 +1,6 @@
 use std::collections::HashMap;
 
+use crate::config::SortOption;
 use cosmic::widget::menu::key_bind::KeyBind;
 use cosmic::{
     widget::menu::{items, root, Item, ItemHeight, ItemWidth, MenuBar, Tree},
@@ -16,6 +17,7 @@ pub fn menu_bar<'a>(
     key_binds: &HashMap<KeyBind, MenuAction>,
     accounts_present: bool,
     bookmarks_present: bool,
+    sort_option: SortOption,
 ) -> Element<'a, Message> {
     MenuBar::new(vec![
         Tree::with_children(
@@ -48,6 +50,55 @@ pub fn menu_bar<'a>(
                 ],
             ),
         ),
+        // TODO: (vkhitrin) dynamically generate enabled/disabled entries
+        //       instead of writing manual code
+        Tree::with_children(
+            root(fl!("sort")),
+            items(
+                key_binds,
+                if bookmarks_present {
+                    vec![
+                        Item::CheckBox(
+                            fl!("bookmark-date-newest"),
+                            matches!(sort_option, SortOption::BookmarksDateNewest),
+                            MenuAction::SetSortBookmarks(SortOption::BookmarksDateNewest),
+                        ),
+                        Item::CheckBox(
+                            fl!("bookmark-date-oldest"),
+                            matches!(sort_option, SortOption::BookmarksDateOldest),
+                            MenuAction::SetSortBookmarks(SortOption::BookmarksDateOldest),
+                        ),
+                        Item::Divider,
+                        Item::CheckBox(
+                            fl!("bookmark-alphabetical-ascending"),
+                            matches!(sort_option, SortOption::BookmarkAlphabeticalAscending),
+                            MenuAction::SetSortBookmarks(SortOption::BookmarkAlphabeticalAscending),
+                        ),
+                        Item::CheckBox(
+                            fl!("bookmark-alphabetical-descending"),
+                            matches!(sort_option, SortOption::BookmarkAlphabeticalDescending),
+                            MenuAction::SetSortBookmarks(
+                                SortOption::BookmarkAlphabeticalDescending,
+                            ),
+                        ),
+                    ]
+                } else {
+                    vec![
+                        Item::ButtonDisabled(fl!("bookmark-date-newest"), MenuAction::Empty),
+                        Item::ButtonDisabled(fl!("bookmark-date-oldest"), MenuAction::Empty),
+                        Item::Divider,
+                        Item::ButtonDisabled(
+                            fl!("bookmark-alphabetical-ascending"),
+                            MenuAction::Empty,
+                        ),
+                        Item::ButtonDisabled(
+                            fl!("bookmark-alphabetical-descending"),
+                            MenuAction::Empty,
+                        ),
+                    ]
+                },
+            ),
+        ),
     ])
     .item_height(ItemHeight::Dynamic(40))
     .item_width(ItemWidth::Uniform(240))