diff --git a/amadeus/i18n/en/amadeus.ftl b/amadeus/i18n/en/amadeus.ftl
index aaaeaad607df84ea2cb0888f1dbb9623384e4bc5..9c4207ccd3ab6b08b4870590f4da76b6b93dcedd 100644
--- a/amadeus/i18n/en/amadeus.ftl
+++ b/amadeus/i18n/en/amadeus.ftl
@@ -15,6 +15,7 @@ page-id   = Page { $num }
 empty-queue     = Empty Queue
 empty-history   = Empty History
 empty-playlists = Empty playlists
+empty-playlist  = Empty playlists { $name }
 
 next-kara        = Next kara
 prev-kara        = Previous kara
diff --git a/amadeus/i18n/es-ES/amadeus.ftl b/amadeus/i18n/es-ES/amadeus.ftl
index 0aacad98a95eb84847d01dfed3d3ac59c47a9d63..91078f9aa6181753e247139d537f09ecef72f074 100644
--- a/amadeus/i18n/es-ES/amadeus.ftl
+++ b/amadeus/i18n/es-ES/amadeus.ftl
@@ -15,6 +15,7 @@ page-id   = Pagina { $num }
 empty-queue     = No hay nada en la cola de reproducción
 empty-history   = No has escuchado nada recientemente
 empty-playlists = No tienes listas de reproducción
+empty-playlist  = No hay nada en la lista { $name }
 
 next-kara        = Póxima kara
 prev-kara        = Previo kara
diff --git a/amadeus/i18n/fr-FR/amadeus.ftl b/amadeus/i18n/fr-FR/amadeus.ftl
index 8e1af80c132eaef627391841110450f18ad76f1d..9b53636cf2dbc2466aeb332f5b4f3edd0f306c49 100644
--- a/amadeus/i18n/fr-FR/amadeus.ftl
+++ b/amadeus/i18n/fr-FR/amadeus.ftl
@@ -15,6 +15,7 @@ page-id   = Page { $num }
 empty-queue     = La queue est vide
 empty-history   = L'historique est vide
 empty-playlists = Il n'y a pas de listes de lecture de disponibles
+empty-playlist  = La liste de lecture { $name } est vide
 
 next-kara        = Kara suivant
 prev-kara        = Kara précédent
diff --git a/amadeus/rsc/icons/fontawesome/goback.svg b/amadeus/rsc/icons/fontawesome/goback.svg
new file mode 100644
index 0000000000000000000000000000000000000000..30ecb4886c24e04aa0b329555ccd719075ba6865
--- /dev/null
+++ b/amadeus/rsc/icons/fontawesome/goback.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--!Font Awesome Free 6.6.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.--><path d="M9.4 233.4c-12.5 12.5-12.5 32.8 0 45.3l192 192c12.5 12.5 32.8 12.5 45.3 0s12.5-32.8 0-45.3L77.3 256 246.6 86.6c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0l-192 192z"/></svg>
diff --git a/amadeus/src/app.rs b/amadeus/src/app.rs
index 003e1056301e8047905238e5683e70070d54e3de..7f98e9e6a706e948b737e215ec22993c861547f1 100644
--- a/amadeus/src/app.rs
+++ b/amadeus/src/app.rs
@@ -74,6 +74,9 @@ pub struct AppModel {
     /// Informations about the lektord server.
     lektord_state: LektordState,
 
+    /// The selected playlist in the playlists tab.
+    selected_playlist: Option<KId>,
+
     /// The store where we cache the playlists, queue, history, etc.
     store: Store,
 
@@ -176,6 +179,10 @@ pub enum Message {
     OpenKaraInfo(KId),
     ToggleContextPage(ContextPage),
 
+    // Playlist selection stuff
+    SelectPlaylist(KId),
+    UnSelectPlaylist,
+
     // Update the configuration
     UpdateConfig(ConfigMessage),
 
@@ -223,6 +230,7 @@ impl Application for AppModel {
             context_page: Default::default(),
 
             lektord_state: LektordState::Disconnected,
+            selected_playlist: None,
             store: Store::default(),
             search_filter: Filter::default(),
             search_results: Vec::default(),
@@ -335,16 +343,15 @@ impl Application for AppModel {
     /// Describes the interface based on the current state of the application model.
     fn view(&self) -> Element<Self::Message> {
         let page = match self.nav.active_data::<Page>().copied() {
-            Some(Page::Home) => pages::home::view().into(),
-            Some(Page::Queue) => pages::queue::view(&self.store).into(),
-            Some(Page::History) => pages::history::view(&self.store).into(),
-            Some(Page::Search) => pages::search::view(self).into(),
-            Some(Page::Playlists) => pages::playlists::view(&self.store).into(),
-            Some(Page::Playlist(id)) => pages::playlist::view(&self.store, id).into(),
-            page => pages::not_found(page).into(),
+            Some(Page::Home) => pages::home::view(),
+            Some(Page::Queue) => pages::queue::view(&self.store),
+            Some(Page::History) => pages::history::view(&self.store),
+            Some(Page::Search) => pages::search::view(self),
+            Some(Page::Playlists) => pages::playlists::view(&self.store, self.selected_playlist),
+            page => pages::not_found(page),
         };
 
-        widget::column()
+        widget::column::with_capacity(2)
             .push(page)
             .push(bottom_bar::view(self))
             .apply(widget::container)
@@ -415,14 +422,22 @@ impl Application for AppModel {
                 cosmic::command::future(async move {
                     requests::search_karas(&*config.read().await, SearchFrom::Database, filters)
                         .await
-                        .map(Message::QueryWithFiltersResults)
-                        .map(cosmic::app::message::app)
+                        .map(|res| cosmic::app::message::app(Message::QueryWithFiltersResults(res)))
                         .unwrap_or_else(|err| {
                             log::error!("failed to query with filters: {err}");
                             cosmic::app::message::none()
                         })
                 })
             }
+
+            Message::SelectPlaylist(kid) => {
+                self.selected_playlist = Some(kid);
+                Task::none()
+            }
+            Message::UnSelectPlaylist => {
+                self.selected_playlist = None;
+                Task::none()
+            }
         }
     }
 
diff --git a/amadeus/src/app/pages.rs b/amadeus/src/app/pages.rs
index c79b3c02417d49bdbd3e771c16dcd8fc4e6b7c25..2957cd3c75c5902868817cdab07419e1de716180 100644
--- a/amadeus/src/app/pages.rs
+++ b/amadeus/src/app/pages.rs
@@ -8,16 +8,13 @@ use cosmic::{
         Alignment, Length,
     },
     prelude::*,
-    style, theme,
-    widget::{self, icon, nav_bar, Icon},
+    style, theme, widget,
 };
 use derive_more::Display;
-use lektor_payloads::KId;
 use std::marker;
 
 pub mod history;
 pub mod home;
-pub mod playlist;
 pub mod playlists;
 pub mod queue;
 pub mod search;
@@ -41,27 +38,26 @@ pub enum Page {
 
     #[display("{}", fl!("playlists"))]
     Playlists,
-
-    #[display("{}", fl!("playlist"))]
-    Playlist(KId),
 }
 
 impl Page {
     /// Get the icon associated with the page, to be displayed along with the [nav_bar::Model].
-    pub fn icon(&self) -> Icon {
-        let icon = match self {
+    pub fn icon(&self) -> widget::Icon {
+        match self {
             Page::Home => crate::icons::USER,
             Page::Queue => crate::icons::QUEUE,
-            Page::History => crate::icons::HISTORY,
             Page::Search => crate::icons::SEARCH,
-            Page::Playlists | Page::Playlist(_) => crate::icons::ARCHIVE,
-        };
-        icon::icon(icon::from_svg_bytes(icon).symbolic(true))
+            Page::History => crate::icons::HISTORY,
+            Page::Playlists => crate::icons::ARCHIVE,
+        }
+        .apply(widget::icon::from_svg_bytes)
+        .symbolic(true)
+        .apply(widget::icon::icon)
     }
 }
 
 /// Get the navigation bar for the pages.
-pub fn nav_bar_model() -> nav_bar::Model {
+pub fn nav_bar_model() -> widget::nav_bar::Model {
     macro_rules! insert {
         ($b:expr, $page:ident) => {
             $b.text(Page::$page.to_string())
@@ -69,7 +65,7 @@ pub fn nav_bar_model() -> nav_bar::Model {
                 .data(Page::$page)
         };
     }
-    nav_bar::Model::builder()
+    widget::nav_bar::Model::builder()
         .insert(|b| insert!(b, Home).activate())
         .insert(|b| insert!(b, Queue))
         .insert(|b| insert!(b, History))
@@ -79,7 +75,7 @@ pub fn nav_bar_model() -> nav_bar::Model {
 }
 
 /// We got a page that was not implemented, or no page at all.
-pub fn not_found<'a>(page: Option<Page>) -> impl Into<Element<'a, Message>> {
+pub fn not_found<'a>(page: Option<Page>) -> Element<'a, Message> {
     widget::column()
         .push(widget::text::title1(fl!("error-found")))
         .push_maybe(
@@ -91,13 +87,14 @@ pub fn not_found<'a>(page: Option<Page>) -> impl Into<Element<'a, Message>> {
         .height(Length::Fill)
         .align_x(Horizontal::Center)
         .align_y(Vertical::Center)
+        .into()
 }
 
 /// Helper for the icons at the right of the title in pages.
 #[must_use]
 struct PageViewControl<'a> {
     icon: &'static [u8],
-    message: Message,
+    message: Option<Message>,
     on_non_empty_content: bool,
     is_destructive_icon: bool,
     marker: marker::PhantomData<Element<'a, Message>>,
@@ -105,16 +102,24 @@ struct PageViewControl<'a> {
 
 impl<'a> PageViewControl<'a> {
     /// Create a new control with an icon and an associated message.
-    pub fn new(icon: &'static [u8], message: Message) -> Self {
+    pub fn new(icon: &'static [u8]) -> Self {
         Self {
             icon,
-            message,
+            message: None,
             on_non_empty_content: false,
             is_destructive_icon: false,
             marker: marker::PhantomData,
         }
     }
 
+    /// Set the message to use when the button will be pressed.
+    pub fn message(self, message: Message) -> Self {
+        Self {
+            message: Some(message),
+            ..self
+        }
+    }
+
     /// Make the button a destructive one.
     pub fn destructive(self) -> Self {
         Self {
@@ -146,7 +151,11 @@ impl<'a> PageViewControl<'a> {
         let button = widget::icon::from_svg_bytes(icon)
             .symbolic(true)
             .apply(widget::button::icon)
-            .on_press_maybe((!page_is_empty || !on_non_empty_content).then_some(message))
+            .on_press_maybe(
+                (!page_is_empty || !on_non_empty_content)
+                    .then_some(message)
+                    .flatten(),
+            )
             .padding(space_xxs)
             .width(32)
             .height(32);
diff --git a/amadeus/src/app/pages/history.rs b/amadeus/src/app/pages/history.rs
index 7f768e0503eb6f527cf9733eadae1e509423390f..2c67b24b5bff33053a428e651ff9afcb0fb818cc 100644
--- a/amadeus/src/app/pages/history.rs
+++ b/amadeus/src/app/pages/history.rs
@@ -4,26 +4,22 @@ use crate::{
         pages::{PageView, PageViewControl},
         LektordCommand, Message,
     },
-    fl,
+    fl, icons,
     store::Store,
 };
 use cosmic::{prelude::*, widget};
 
 /// Display the history page.
-pub fn view(store: &Store) -> impl Into<Element<Message>> {
+pub fn view(store: &Store) -> Element<Message> {
     PageView::default()
         .titles(fl!("history"), fl!("empty-history"))
         .controls([
-            PageViewControl::new(
-                crate::icons::RETRY,
-                Message::SendCommand(LektordCommand::HistoryGet),
-            ),
-            PageViewControl::new(
-                crate::icons::METEOR,
-                Message::SendCommand(LektordCommand::HistoryClear),
-            )
-            .destructive()
-            .need_content(),
+            PageViewControl::new(icons::RETRY)
+                .message(Message::SendCommand(LektordCommand::HistoryGet)),
+            PageViewControl::new(icons::METEOR)
+                .message(Message::SendCommand(LektordCommand::HistoryClear))
+                .destructive()
+                .need_content(),
         ])
         .push_when(!store.iter_history().is_empty(), || {
             (store.iter_history()).fold(widget::list_column(), |list, kid| {
@@ -31,4 +27,5 @@ pub fn view(store: &Store) -> impl Into<Element<Message>> {
             })
         })
         .view()
+        .into()
 }
diff --git a/amadeus/src/app/pages/home.rs b/amadeus/src/app/pages/home.rs
index 71d31c083db8fe707988f7542e4ba0046d07496e..96e01a1c01131445221909446153ca8689656ff9 100644
--- a/amadeus/src/app/pages/home.rs
+++ b/amadeus/src/app/pages/home.rs
@@ -5,6 +5,6 @@ use crate::{
 use cosmic::prelude::*;
 
 /// Display the home page.
-pub fn view<'a>() -> impl Into<Element<'a, Message>> {
-    PageView::default().title(fl!("home")).view()
+pub fn view<'a>() -> Element<'a, Message> {
+    PageView::default().title(fl!("home")).view().into()
 }
diff --git a/amadeus/src/app/pages/playlist.rs b/amadeus/src/app/pages/playlist.rs
deleted file mode 100644
index 007ba72c650fb5421b9cbb7abf1da086726e4653..0000000000000000000000000000000000000000
--- a/amadeus/src/app/pages/playlist.rs
+++ /dev/null
@@ -1,84 +0,0 @@
-use crate::{
-    app::{
-        kard,
-        pages::{PageView, PageViewControl},
-        LektordCommand, Message,
-    },
-    fl,
-    store::Store,
-};
-use cosmic::{prelude::*, style, widget};
-use lektor_payloads::{KId, PlaylistInfo};
-
-/// Display the page about a specific playlist.
-pub fn view(store: &Store, id: KId) -> impl Into<Element<Message>> {
-    let Some(infos) = store.playlist(id) else {
-        todo!()
-    };
-
-    let name = infos
-        .name()
-        .map(|name| fl!("playlist", name = name))
-        .unwrap_or_else(|| "untitled".to_string());
-
-    let owners = infos
-        .infos()
-        .into_iter()
-        .flat_map(PlaylistInfo::owners)
-        .map(|owner| -> Element<'_, Message> {
-            widget::text::body(owner)
-                .apply(widget::button::custom)
-                .class(style::Button::Transparent)
-                .into()
-        });
-
-    let (created_at, updated_at) = infos
-        .infos()
-        .map(|infos| (infos.created_at(), infos.updated_at()))
-        .unwrap_or_default();
-
-    let infos = widget::settings::section()
-        .add(widget::settings::item(
-            "owners",
-            widget::row::with_children(owners.collect()),
-        ))
-        .add(widget::settings::item(
-            "created at",
-            widget::text::body(created_at.format("%Y-%m-%d %H:%M:%S").to_string()),
-        ))
-        .add(widget::settings::item(
-            "last modified at",
-            widget::text::body(updated_at.format("%Y-%m-%d %H:%M:%S").to_string()),
-        ));
-
-    let display_playlist_content = || {
-        (store.iter_playlist_content(id)).fold(widget::list_column(), |list, kid| {
-            list.add(kard::view(store.get(kid)))
-        })
-    };
-
-    PageView::default()
-        .titles(&name, format!("The playlist {name} is empty"))
-        .controls([
-            PageViewControl::new(
-                crate::icons::SHUFFLE,
-                Message::SendCommand(LektordCommand::PlaylistShuffleContent(id)),
-            )
-            .need_content(),
-            PageViewControl::new(
-                crate::icons::RETRY,
-                Message::SendCommand(LektordCommand::PlaylistGetContent(id)),
-            ),
-            PageViewControl::new(
-                crate::icons::METEOR,
-                Message::SendCommand(LektordCommand::PlaylistDelete(id)),
-            )
-            .destructive(),
-        ])
-        .push_and_ignore_for_empty(infos)
-        .push_when(
-            !store.iter_playlist_content(id).is_empty(),
-            display_playlist_content,
-        )
-        .view()
-}
diff --git a/amadeus/src/app/pages/playlists.rs b/amadeus/src/app/pages/playlists.rs
index 51745b73d0e136c4cd084e24921b39ae7dafbf70..cb3975858925a941744788166b1b0c949483aecb 100644
--- a/amadeus/src/app/pages/playlists.rs
+++ b/amadeus/src/app/pages/playlists.rs
@@ -1,33 +1,117 @@
 use crate::{
     app::{
+        kard,
         pages::{PageView, PageViewControl},
         LektordCommand, Message,
     },
-    fl,
+    fl, icons,
     playlist::Playlist,
     store::Store,
 };
-use cosmic::{prelude::*, widget};
+use cosmic::{prelude::*, style, widget};
+use lektor_payloads::{KId, PlaylistInfo};
 
-fn view_playlist_card(playlist: &Playlist) -> impl Into<Element<Message>> {
-    widget::text(playlist.name().unwrap_or("untitled"))
+/// Display a card that summerize the playlist, when pressed will select the given playlist.
+fn view_playlist_card(playlist: &Playlist) -> Option<Element<Message>> {
+    let infos = playlist.infos()?;
+    let card = widget::text(infos.name())
+        .apply(widget::button::custom)
+        .on_press(Message::SelectPlaylist(infos.local_id()));
+    Some(card.into())
 }
 
-/// Display all playlists in a page.
-pub fn view(store: &Store) -> impl Into<Element<Message>> {
+/// Display all the cards for all the available playlists.
+fn view_playlists_cards(store: &Store) -> Element<Message> {
     PageView::default()
         .titles(fl!("playlists"), fl!("empty-playlists"))
-        .controls([PageViewControl::new(
-            crate::icons::RETRY,
-            Message::SendCommand(LektordCommand::PlaylistsGet),
-        )])
+        .controls([PageViewControl::new(crate::icons::RETRY)
+            .message(Message::SendCommand(LektordCommand::PlaylistsGet))])
         .push_when(store.iter_playlists().count() != 0, || {
             store
                 .iter_playlists()
-                .map(view_playlist_card)
-                .map(Into::into)
+                .flat_map(view_playlist_card)
                 .collect::<Vec<_>>()
                 .apply(widget::flex_row)
         })
         .view()
+        .into()
+}
+
+/// Display the page about a specific playlist.
+fn view_playlist_content(store: &Store, id: KId) -> Element<Message> {
+    let Some(infos) = store.playlist(id) else {
+        todo!()
+    };
+
+    let name = infos
+        .name()
+        .map(|name| fl!("playlist", name = name))
+        .unwrap_or_else(|| "untitled".to_string());
+
+    let owners = infos
+        .infos()
+        .into_iter()
+        .flat_map(PlaylistInfo::owners)
+        .map(|owner| -> Element<'_, Message> {
+            widget::text::body(owner)
+                .apply(widget::button::custom)
+                .class(style::Button::Transparent)
+                .into()
+        });
+
+    let (created_at, updated_at) = infos
+        .infos()
+        .map(|infos| (infos.created_at(), infos.updated_at()))
+        .unwrap_or_default();
+
+    let infos = widget::settings::section()
+        .add(widget::settings::item(
+            "owners",
+            widget::row::with_children(owners.collect()),
+        ))
+        .add(widget::settings::item(
+            "created at",
+            widget::text::body(created_at.format("%Y-%m-%d %H:%M:%S").to_string()),
+        ))
+        .add(widget::settings::item(
+            "last modified at",
+            widget::text::body(updated_at.format("%Y-%m-%d %H:%M:%S").to_string()),
+        ));
+
+    let display_playlist_content = || {
+        (store.iter_playlist_content(id)).fold(widget::list_column(), |list, kid| {
+            list.add(kard::view(store.get(kid)))
+        })
+    };
+
+    PageView::default()
+        .titles(&name, fl!("empty-playlist", name = name.clone()))
+        .controls([
+            PageViewControl::new(icons::GOBACK).message(Message::UnSelectPlaylist),
+            PageViewControl::new(icons::SHUFFLE)
+                .message(Message::SendCommand(
+                    LektordCommand::PlaylistShuffleContent(id),
+                ))
+                .need_content(),
+            PageViewControl::new(icons::RETRY)
+                .message(Message::SendCommand(LektordCommand::PlaylistGetContent(id))),
+            PageViewControl::new(icons::METEOR)
+                .message(Message::SendCommand(LektordCommand::PlaylistDelete(id)))
+                .destructive(),
+        ])
+        .push_and_ignore_for_empty(infos)
+        .push_when(
+            !store.iter_playlist_content(id).is_empty(),
+            display_playlist_content,
+        )
+        .view()
+        .into()
+}
+
+/// Display all playlists in a page, or the selected playlist.
+pub fn view(store: &Store, selected_playlist: Option<KId>) -> Element<Message> {
+    match selected_playlist {
+        Some(id) => view_playlist_content(store, id),
+        None => view_playlists_cards(store),
+    }
 }
diff --git a/amadeus/src/app/pages/queue.rs b/amadeus/src/app/pages/queue.rs
index bc7ab1e839b0d131aface18f063d89511d700f18..9ca0a56840deeb27c6f71f28ac7174b72d996cd5 100644
--- a/amadeus/src/app/pages/queue.rs
+++ b/amadeus/src/app/pages/queue.rs
@@ -1,6 +1,6 @@
 use crate::{
     app::{kard, pages::PageView, LektordCommand, Message},
-    fl,
+    fl, icons,
     store::Store,
 };
 use cosmic::{prelude::*, style, widget};
@@ -13,21 +13,17 @@ fn view_queue_level(store: &Store, level: Priority) -> impl IntoIterator<Item =
         widget::text::title2(format!("{} {level}", fl!("queue"))).class(style::Text::Default),
         false,
         vec![
-            PageViewControl::new(
-                crate::icons::SHUFFLE,
-                Message::SendCommand(LektordCommand::QueueLevelShuffle(level)),
-            )
-            .need_content(),
-            PageViewControl::new(
-                crate::icons::RETRY,
-                Message::SendCommand(LektordCommand::QueueLevelGet(level)),
-            ),
-            PageViewControl::new(
-                crate::icons::METEOR,
-                Message::SendCommand(LektordCommand::QueueLevelClear(level)),
-            )
-            .need_content()
-            .destructive(),
+            PageViewControl::new(icons::SHUFFLE)
+                .message(Message::SendCommand(LektordCommand::QueueLevelShuffle(
+                    level,
+                )))
+                .need_content(),
+            PageViewControl::new(icons::RETRY)
+                .message(Message::SendCommand(LektordCommand::QueueLevelGet(level))),
+            PageViewControl::new(icons::METEOR)
+                .message(Message::SendCommand(LektordCommand::QueueLevelClear(level)))
+                .need_content()
+                .destructive(),
         ],
         store.iter_queue_level(level).is_empty(),
     );
@@ -42,31 +38,23 @@ fn view_queue_level(store: &Store, level: Priority) -> impl IntoIterator<Item =
 }
 
 /// Displays the page with the queue.
-pub fn view(store: &Store) -> impl Into<Element<Message>> {
+pub fn view(store: &Store) -> Element<Message> {
     PageView::default()
         .titles(fl!("queue"), fl!("empty-queue"))
         .controls([
-            PageViewControl::new(
-                crate::icons::SHUFFLE,
-                Message::SendCommand(LektordCommand::QueueShuffle),
-            )
-            .need_content(),
-            PageViewControl::new(
-                crate::icons::RETRY,
-                Message::SendCommand(LektordCommand::QueueGet),
-            ),
-            PageViewControl::new(
-                crate::icons::CROP,
-                Message::SendCommand(LektordCommand::QueueCrop),
-            )
-            .need_content()
-            .destructive(),
-            PageViewControl::new(
-                crate::icons::METEOR,
-                Message::SendCommand(LektordCommand::QueueClear),
-            )
-            .need_content()
-            .destructive(),
+            PageViewControl::new(icons::SHUFFLE)
+                .message(Message::SendCommand(LektordCommand::QueueShuffle))
+                .need_content(),
+            PageViewControl::new(icons::RETRY)
+                .message(Message::SendCommand(LektordCommand::QueueGet)),
+            PageViewControl::new(icons::CROP)
+                .message(Message::SendCommand(LektordCommand::QueueCrop))
+                .need_content()
+                .destructive(),
+            PageViewControl::new(icons::METEOR)
+                .message(Message::SendCommand(LektordCommand::QueueClear))
+                .need_content()
+                .destructive(),
         ])
         .extend(
             (PRIORITY_VALUES.iter().rev())
@@ -76,4 +64,5 @@ pub fn view(store: &Store) -> impl Into<Element<Message>> {
                 .flatten(),
         )
         .view()
+        .into()
 }
diff --git a/amadeus/src/app/pages/search.rs b/amadeus/src/app/pages/search.rs
index c305e7a55272082e3b084821a6e54a242e752611..3e1b6fcb8d14ab12070c08e8fd8e82c40d85cdcb 100644
--- a/amadeus/src/app/pages/search.rs
+++ b/amadeus/src/app/pages/search.rs
@@ -1,6 +1,13 @@
 //! Contains everything to implement search from Amadeus.
 
-use crate::app::{kard, pages::PageView, AppModel, Message};
+use crate::{
+    app::{
+        kard,
+        pages::{PageView, PageViewControl},
+        AppModel, Message,
+    },
+    icons,
+};
 use cosmic::{iced::Alignment, prelude::*, style, theme, widget};
 use lektor_payloads::KaraBy;
 use std::{
@@ -9,8 +16,6 @@ use std::{
     sync::atomic::{AtomicUsize, Ordering},
 };
 
-use super::PageViewControl;
-
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct FilterAtom(FilterAtomId, KaraBy);
 
@@ -20,14 +25,6 @@ pub struct FilterAtomId(usize);
 #[derive(Debug, Default)]
 pub struct Filter(String, Vec<FilterAtom>);
 
-macro_rules! icon {
-    ($icon:ident) => {
-        widget::icon::from_svg_bytes(crate::icons::$icon)
-            .symbolic(true)
-            .apply(widget::icon)
-    };
-}
-
 impl FromStr for FilterAtom {
     type Err = Infallible;
 
@@ -45,6 +42,14 @@ impl FilterAtomId {
 
 impl FilterAtom {
     fn view(&self) -> Element<Message> {
+        macro_rules! icon {
+            ($icon:ident) => {
+                widget::icon::from_svg_bytes(icons::$icon)
+                    .symbolic(true)
+                    .apply(widget::icon)
+            };
+        }
+
         let (icon, text) = match &self.1 {
             KaraBy::Id(id) => (icon!(HASHTAG), id.to_string()),
             KaraBy::Query(query) => (icon!(FILTER), query.clone()),
@@ -113,21 +118,22 @@ impl Filter {
     }
 
     pub fn remove(&mut self, id: FilterAtomId) {
-        if let Some(idx) = (self.1.iter().enumerate())
+        _ = (self.1.iter().enumerate())
             .find_map(|(idx, FilterAtom(atom, _))| (*atom == id).then_some(idx))
-        {
-            self.1.remove(idx);
-        }
+            .map(|idx| self.1.remove(idx));
     }
 }
 
 /// Display the search page.
-pub fn view(app: &AppModel) -> impl Into<Element<Message>> {
+pub fn view(app: &AppModel) -> Element<Message> {
     PageView::default()
         .custom_title(app.search_filter.view_staging_row())
         .controls([
-            PageViewControl::new(crate::icons::FILTER, Message::QueryWithFilters).need_content(),
-            PageViewControl::new(crate::icons::METEOR, Message::ClearFilters)
+            PageViewControl::new(icons::FILTER)
+                .message(Message::QueryWithFilters)
+                .need_content(),
+            PageViewControl::new(icons::METEOR)
+                .message(Message::ClearFilters)
                 .need_content()
                 .destructive(),
         ])
@@ -139,4 +145,5 @@ pub fn view(app: &AppModel) -> impl Into<Element<Message>> {
             })
         })
         .view()
+        .into()
 }
diff --git a/amadeus/src/icons.rs b/amadeus/src/icons.rs
index 28320f56464f4f0bc2830b343c9d024d19322325..05dfb909cf93019ead4a1e1d822609e1b125ca2c 100644
--- a/amadeus/src/icons.rs
+++ b/amadeus/src/icons.rs
@@ -47,3 +47,4 @@ icon!(PLAY:         "fontawesome/play");
 icon!(PAUSE:        "fontawesome/pause");
 icon!(RETRY:        "fontawesome/retry");
 icon!(CROP:         "fontawesome/crop");
+icon!(GOBACK:       "fontawesome/goback");