diff --git a/app/Authorization/FlatAuthorization.php b/app/Authorization/FlatAuthorization.php
index a732a8cbfdbf0dce34f95eb8b996202f4eb06c4a..f96fb2aa7b77fdf7e6d0c483a11fcbf6ed0b3999 100644
--- a/app/Authorization/FlatAuthorization.php
+++ b/app/Authorization/FlatAuthorization.php
@@ -49,7 +49,7 @@ class FlatAuthorization extends \Myth\Auth\Authorization\FlatAuthorization
     }
 
     /**
-     * Makes a member a part of multiple groups.
+     * Makes user part of given groups.
      *
      * @param $userId
      * @param array|null $groups // Either collection of ID or names
diff --git a/app/Config/Routes.php b/app/Config/Routes.php
index 84a96218aca70886e2e5c6cbf0066bfc986b9d55..e288b15e2e497157f97331aa3a90941de637b205 100644
--- a/app/Config/Routes.php
+++ b/app/Config/Routes.php
@@ -77,11 +77,11 @@ $routes->group(
         $routes->get('podcasts', 'Podcast::list', [
             'as' => 'podcast_list',
         ]);
-        $routes->get('new-podcast', 'Podcast::create', [
+        $routes->get('podcasts/new', 'Podcast::create', [
             'as' => 'podcast_create',
             'filter' => 'permission:podcasts-create',
         ]);
-        $routes->post('new-podcast', 'Podcast::attemptCreate', [
+        $routes->post('podcasts/new', 'Podcast::attemptCreate', [
             'filter' => 'permission:podcasts-create',
         ]);
 
@@ -108,19 +108,19 @@ $routes->group(
                 'as' => 'episode_list',
                 'filter' => 'permission:podcasts-view,podcast-view',
             ]);
-            $routes->get('new-episode', 'Episode::create/$1', [
+            $routes->get('episodes/new', 'Episode::create/$1', [
                 'as' => 'episode_create',
                 'filter' =>
                     'permission:episodes-create,podcast_episodes-create',
             ]);
-            $routes->post('new-episode', 'Episode::attemptCreate/$1', [
+            $routes->post('episodes/new', 'Episode::attemptCreate/$1', [
                 'filter' =>
                     'permission:episodes-create,podcast_episodes-create',
             ]);
 
             $routes->get('episodes/(:num)', 'Episode::view/$1/$2', [
                 'as' => 'episode_view',
-                'filter' => 'permission:episodes-list,podcast_episodes-list',
+                'filter' => 'permission:episodes-view,podcast_episodes-view',
             ]);
             $routes->get('episodes/(:num)/edit', 'Episode::edit/$1/$2', [
                 'as' => 'episode_edit',
@@ -146,15 +146,18 @@ $routes->group(
                 'filter' =>
                     'permission:podcasts-manage_contributors,podcast-manage_contributors',
             ]);
-            $routes->get('add-contributor', 'Contributor::add/$1', [
+            $routes->get('contributors/add', 'Contributor::add/$1', [
                 'as' => 'contributor_add',
                 'filter' =>
                     'permission:podcasts-manage_contributors,podcast-manage_contributors',
             ]);
-            $routes->post('add-contributor', 'Contributor::attemptAdd/$1', [
+            $routes->post('contributors/add', 'Contributor::attemptAdd/$1', [
                 'filter' =>
                     'permission:podcasts-manage_contributors,podcast-manage_contributors',
             ]);
+            $routes->get('contributors/(:num)', 'Contributor::view/$1/$2', [
+                'as' => 'contributor_view',
+            ]);
             $routes->get(
                 'contributors/(:num)/edit',
                 'Contributor::edit/$1/$2',
@@ -188,11 +191,15 @@ $routes->group(
             'as' => 'user_list',
             'filter' => 'permission:users-list',
         ]);
-        $routes->get('new-user', 'User::create', [
+        $routes->get('users/new', 'User::create', [
             'as' => 'user_create',
             'filter' => 'permission:users-create',
         ]);
-        $routes->post('new-user', 'User::attemptCreate', [
+        $routes->get('users/(:num)', 'User::view/$1', [
+            'as' => 'user_view',
+            'filter' => 'permission:users-view',
+        ]);
+        $routes->post('users/new', 'User::attemptCreate', [
             'filter' => 'permission:users-create',
         ]);
         $routes->get('users/(:num)/edit', 'User::edit/$1', [
diff --git a/app/Config/Services.php b/app/Config/Services.php
index 275caab2378c034309dc7a1ea9327ba241fa0bdb..27d601fae5d0d6ae1398dad31cf9b242946679f4 100644
--- a/app/Config/Services.php
+++ b/app/Config/Services.php
@@ -7,6 +7,7 @@ use CodeIgniter\Model;
 use App\Authorization\FlatAuthorization;
 use App\Authorization\PermissionModel;
 use App\Authorization\GroupModel;
+use App\Libraries\Breadcrumb;
 use App\Models\UserModel;
 use Myth\Auth\Models\LoginModel;
 
@@ -91,4 +92,13 @@ class Services extends CoreServices
 
         return $instance->setUserModel($userModel);
     }
+
+    public static function breadcrumb(bool $getShared = true)
+    {
+        if ($getShared) {
+            return self::getSharedInstance('breadcrumb');
+        }
+
+        return new Breadcrumb();
+    }
 }
diff --git a/app/Controllers/Admin/BaseController.php b/app/Controllers/Admin/BaseController.php
index a10692c9e765010a296e8461e748fcfa21ca2ffd..92f4849ab40c42b399f2264210c53558ad081147 100644
--- a/app/Controllers/Admin/BaseController.php
+++ b/app/Controllers/Admin/BaseController.php
@@ -26,7 +26,7 @@ class BaseController extends Controller
      *
      * @var array
      */
-    protected $helpers = ['auth'];
+    protected $helpers = ['auth', 'breadcrumb', 'svg'];
 
     /**
      * Constructor.
diff --git a/app/Controllers/Admin/Contributor.php b/app/Controllers/Admin/Contributor.php
index 4f5a8ae8250513d9ec91be83a92c7922f85a6bdc..2f8ed6d5f46a3554193510a46f900326281240b1 100644
--- a/app/Controllers/Admin/Contributor.php
+++ b/app/Controllers/Admin/Contributor.php
@@ -41,7 +41,24 @@ class Contributor extends BaseController
             'podcast' => $this->podcast,
         ];
 
-        echo view('admin/contributor/list', $data);
+        replace_breadcrumb_params([0 => $this->podcast->title]);
+        return view('admin/contributor/list', $data);
+    }
+
+    public function view()
+    {
+        $data = [
+            'contributor' => (new UserModel())->getPodcastContributor(
+                $this->user->id,
+                $this->podcast->id
+            ),
+        ];
+
+        replace_breadcrumb_params([
+            0 => $this->podcast->title,
+            1 => $this->user->username,
+        ]);
+        return view('admin/contributor/view', $data);
     }
 
     public function add()
@@ -52,7 +69,8 @@ class Contributor extends BaseController
             'roles' => (new GroupModel())->getContributorRoles(),
         ];
 
-        echo view('admin/contributor/add', $data);
+        replace_breadcrumb_params([0 => $this->podcast->title]);
+        return view('admin/contributor/add', $data);
     }
 
     public function attemptAdd()
@@ -87,7 +105,11 @@ class Contributor extends BaseController
             'roles' => (new GroupModel())->getContributorRoles(),
         ];
 
-        echo view('admin/contributor/edit', $data);
+        replace_breadcrumb_params([
+            0 => $this->podcast->title,
+            1 => $this->user->username,
+        ]);
+        return view('admin/contributor/edit', $data);
     }
 
     public function attemptEdit()
diff --git a/app/Controllers/Admin/Episode.php b/app/Controllers/Admin/Episode.php
index 0c5ce4c2736ff318d34bd274718fb3f0c9a014eb..b639512ef16e95b5eb07c2827aae69b0a60e020d 100644
--- a/app/Controllers/Admin/Episode.php
+++ b/app/Controllers/Admin/Episode.php
@@ -42,6 +42,9 @@ class Episode extends BaseController
             'podcast' => $this->podcast,
         ];
 
+        replace_breadcrumb_params([
+            0 => $this->podcast->title,
+        ]);
         return view('admin/episode/list', $data);
     }
 
@@ -49,6 +52,10 @@ class Episode extends BaseController
     {
         $data = ['episode' => $this->episode];
 
+        replace_breadcrumb_params([
+            0 => $this->podcast->title,
+            1 => $this->episode->title,
+        ]);
         return view('admin/episode/view', $data);
     }
 
@@ -60,7 +67,10 @@ class Episode extends BaseController
             'podcast' => $this->podcast,
         ];
 
-        echo view('admin/episode/create', $data);
+        replace_breadcrumb_params([
+            0 => $this->podcast->title,
+        ]);
+        return view('admin/episode/create', $data);
     }
 
     public function attemptCreate()
@@ -115,7 +125,11 @@ class Episode extends BaseController
             'episode' => $this->episode,
         ];
 
-        echo view('admin/episode/edit', $data);
+        replace_breadcrumb_params([
+            0 => $this->podcast->title,
+            1 => $this->episode->title,
+        ]);
+        return view('admin/episode/edit', $data);
     }
 
     public function attemptEdit()
diff --git a/app/Controllers/Admin/Podcast.php b/app/Controllers/Admin/Podcast.php
index 99209e0761201f49b2eb9de4661a7becd585aa3b..c0e5b2cb33adb0eb56e29c75ddc2e48a7ea770d7 100644
--- a/app/Controllers/Admin/Podcast.php
+++ b/app/Controllers/Admin/Podcast.php
@@ -52,6 +52,7 @@ class Podcast extends BaseController
     {
         $data = ['podcast' => $this->podcast];
 
+        replace_breadcrumb_params([0 => $this->podcast->title]);
         return view('admin/podcast/view', $data);
     }
 
@@ -69,7 +70,7 @@ class Podcast extends BaseController
             ),
         ];
 
-        echo view('admin/podcast/create', $data);
+        return view('admin/podcast/create', $data);
     }
 
     public function attemptCreate()
@@ -145,7 +146,8 @@ class Podcast extends BaseController
             'categories' => (new CategoryModel())->findAll(),
         ];
 
-        echo view('admin/podcast/edit', $data);
+        replace_breadcrumb_params([0 => $this->podcast->title]);
+        return view('admin/podcast/edit', $data);
     }
 
     public function attemptEdit()
diff --git a/app/Controllers/Admin/User.php b/app/Controllers/Admin/User.php
index 98470cf13f8a805f1559cdee48b92fb979ea3b19..872d973ff82707e03e4cb408720a235b9ca5099d 100644
--- a/app/Controllers/Admin/User.php
+++ b/app/Controllers/Admin/User.php
@@ -34,13 +34,21 @@ class User extends BaseController
         return view('admin/user/list', $data);
     }
 
+    public function view()
+    {
+        $data = ['user' => $this->user];
+
+        replace_breadcrumb_params([0 => $this->user->username]);
+        return view('admin/user/view', $data);
+    }
+
     public function create()
     {
         $data = [
             'roles' => (new GroupModel())->getUserRoles(),
         ];
 
-        echo view('admin/user/create', $data);
+        return view('admin/user/create', $data);
     }
 
     public function attemptCreate()
@@ -99,7 +107,8 @@ class User extends BaseController
             'roles' => (new GroupModel())->getUserRoles(),
         ];
 
-        echo view('admin/user/edit', $data);
+        replace_breadcrumb_params([0 => $this->user->username]);
+        return view('admin/user/edit', $data);
     }
 
     public function attemptEdit()
diff --git a/app/Database/Seeds/AuthSeeder.php b/app/Database/Seeds/AuthSeeder.php
index 5ce7edcce68040bec8dcd350c54dadfdd94e340f..6ddfd950128b5fff43f9e08992afb6be8408ddcb 100644
--- a/app/Database/Seeds/AuthSeeder.php
+++ b/app/Database/Seeds/AuthSeeder.php
@@ -50,6 +50,11 @@ class AuthSeeder extends Seeder
                 'description' => 'List all users',
                 'has_permission' => ['superadmin'],
             ],
+            [
+                'name' => 'view',
+                'description' => 'View any user info',
+                'has_permission' => ['superadmin'],
+            ],
             [
                 'name' => 'manage_authorizations',
                 'description' => 'Add or remove roles/permissions to a user',
@@ -128,6 +133,11 @@ class AuthSeeder extends Seeder
                 'description' => 'List all episodes of any podcast',
                 'has_permission' => ['superadmin'],
             ],
+            [
+                'name' => 'view',
+                'description' => 'View any episode of any podcast',
+                'has_permission' => ['superadmin'],
+            ],
             [
                 'name' => 'create',
                 'description' => 'Add a new episode to any podcast',
@@ -195,6 +205,11 @@ class AuthSeeder extends Seeder
                 'description' => 'List all episodes of a podcast',
                 'has_permission' => ['podcast_admin'],
             ],
+            [
+                'name' => 'view',
+                'description' => 'View any episode of a podcast',
+                'has_permission' => ['podcast_admin'],
+            ],
             [
                 'name' => 'create',
                 'description' => 'Add new episodes for a podcast',
diff --git a/app/Entities/User.php b/app/Entities/User.php
index f710fd069260536d58b2e25da50239996f314b86..88fe6ed9621c106d00650832b9a5b09e17e93706 100644
--- a/app/Entities/User.php
+++ b/app/Entities/User.php
@@ -12,6 +12,12 @@ class User extends \Myth\Auth\Entities\User
      */
     protected $podcasts = [];
 
+    /**
+     * The podcast user is contributing to
+     * @var \App\Entities\Podcast
+     */
+    protected $podcast;
+
     /**
      * Array of field names and the type of value to cast them as
      * when they are accessed.
@@ -20,6 +26,7 @@ class User extends \Myth\Auth\Entities\User
         'active' => 'boolean',
         'force_pass_reset' => 'boolean',
         'podcast_role' => '?string',
+        'podcast_id' => '?integer',
     ];
 
     /**
@@ -41,4 +48,19 @@ class User extends \Myth\Auth\Entities\User
 
         return $this->podcasts;
     }
+
+    public function getPodcast()
+    {
+        if (empty($this->podcast_id)) {
+            throw new \RuntimeException(
+                'Podcast_id must be set before getting podcast.'
+            );
+        }
+
+        if (empty($this->podcast)) {
+            $this->podcast = (new PodcastModel())->find($this->podcast_id);
+        }
+
+        return $this->podcast;
+    }
 }
diff --git a/app/Helpers/breadcrumb_helper.php b/app/Helpers/breadcrumb_helper.php
new file mode 100644
index 0000000000000000000000000000000000000000..52022860be06c48f5371bfa881ccd867972a8ab9
--- /dev/null
+++ b/app/Helpers/breadcrumb_helper.php
@@ -0,0 +1,28 @@
+<?php
+
+/**
+ * @copyright  2020 Podlibre
+ * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
+ * @link       https://castopod.org/
+ */
+
+use Config\Services;
+
+/**
+ * Returns the inline svg icon
+ *
+ * @param  string $name name of the icon file without the .svg extension
+ * @param  string $class to be added to the svg string
+ * @return string html breadcrumb
+ */
+function render_breadcrumb()
+{
+    $breadcrumb = Services::breadcrumb();
+    return $breadcrumb->render();
+}
+
+function replace_breadcrumb_params($newParams)
+{
+    $breadcrumb = Services::breadcrumb();
+    $breadcrumb->replaceParams($newParams);
+}
diff --git a/app/Helpers/html_helper.php b/app/Helpers/svg_helper.php
similarity index 100%
rename from app/Helpers/html_helper.php
rename to app/Helpers/svg_helper.php
diff --git a/app/Language/en/Breadcrumb.php b/app/Language/en/Breadcrumb.php
new file mode 100644
index 0000000000000000000000000000000000000000..6ef22d33d2b1a3e972595ad51cb0edc6be069d66
--- /dev/null
+++ b/app/Language/en/Breadcrumb.php
@@ -0,0 +1,22 @@
+<?php
+
+/**
+ * @copyright  2020 Podlibre
+ * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
+ * @link       https://castopod.org/
+ */
+
+return [
+    'label' => 'breadcrumb',
+    config('App')->adminGateway => 'Home',
+    'my-podcasts' => 'my podcasts',
+    'podcasts' => 'podcasts',
+    'episodes' => 'episodes',
+    'contributors' => 'contributors',
+    'add' => 'add',
+    'new' => 'new',
+    'edit' => 'edit',
+    'users' => 'users',
+    'my-account' => 'my account',
+    'change-password' => 'change password',
+];
diff --git a/app/Language/en/Contributor.php b/app/Language/en/Contributor.php
index a9bf108bc5320859c11a096c41fa083489995f63..25fed243667fe145cd0d15026906c0ccf67725e8 100644
--- a/app/Language/en/Contributor.php
+++ b/app/Language/en/Contributor.php
@@ -8,6 +8,7 @@
 
 return [
     'podcast_contributors' => 'Podcast contributors',
+    'view' => '{username}\'s contribution to {podcastName}',
     'add' => 'Add contributor',
     'add_contributor' => 'Add a contributor for {0}',
     'edit_role' => 'Update role for {0}',
diff --git a/app/Language/en/MyAccount.php b/app/Language/en/MyAccount.php
index c65d934460b65139629a421417b8b090323f5d32..b675cc177005156f91041bb8e2fa59407929517d 100644
--- a/app/Language/en/MyAccount.php
+++ b/app/Language/en/MyAccount.php
@@ -8,8 +8,8 @@
 
 return [
     'info' => 'My account info',
+    'changePassword' => 'Change my password',
     'messages' => [
         'passwordChangeSuccess' => 'Password has been successfully changed!',
-        'changePassword' => 'Change my password',
     ],
 ];
diff --git a/app/Language/en/User.php b/app/Language/en/User.php
index 2cdc1e332a766bed8c4a7d486b288362dd5a8ff3..0e742c2a3200b228dd476a1e75128ae02ab4618d 100644
--- a/app/Language/en/User.php
+++ b/app/Language/en/User.php
@@ -13,6 +13,7 @@ return [
     'unban' => 'Unban',
     'delete' => 'Delete',
     'create' => 'Create a user',
+    'view' => '{username}\'s info',
     'all_users' => 'All users',
     'form' => [
         'email' => 'Email',
diff --git a/app/Libraries/Breadcrumb.php b/app/Libraries/Breadcrumb.php
new file mode 100644
index 0000000000000000000000000000000000000000..43cb2f951ac2db08ad8686004233d9effa29fa12
--- /dev/null
+++ b/app/Libraries/Breadcrumb.php
@@ -0,0 +1,104 @@
+<?php
+
+/**
+ * Generates and renders a breadcrumb based on the current url segments
+ *
+ * @copyright  2020 Podlibre
+ * @license    https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
+ * @link       https://castopod.org/
+ */
+
+namespace App\Libraries;
+
+class Breadcrumb
+{
+    /**
+     * List of breadcrumb links.
+     *
+     * @var array
+     * $links = [
+     *  'text' => (string) the anchor text,
+     *  'href' => (string) the anchor href,
+     * ]
+     */
+    protected $links = [];
+
+    /**
+     * Initializes the Breadcrumb object using the segments from
+     * current_url by populating the $links property with text and href data
+     */
+    public function __construct()
+    {
+        $uri = '';
+        foreach (current_url(true)->getSegments() as $segment) {
+            $uri .= '/' . $segment;
+            array_push($this->links, [
+                'text' => is_numeric($segment)
+                    ? $segment
+                    : lang('Breadcrumb.' . $segment),
+                'href' => base_url($uri),
+            ]);
+        }
+    }
+
+    /**
+     * Replaces all numeric text in breadcrumb's $link property
+     * with new params at same position
+     *
+     * Given a breadcrumb with numeric params, this function
+     * replaces them with the values provided in $newParams
+     *
+     * Example with `Home / podcasts / 1 / episodes / 1`
+     *
+     * $newParams = [
+     *  0 => 'foo',
+     *  1 => 'bar'
+     * ]
+     * replaceParams($newParams);
+     *
+     * The breadcrumb is now `Home / podcasts / foo / episodes / bar`
+     *
+     * @param array $newParams
+     */
+    public function replaceParams($newParams)
+    {
+        foreach ($this->links as $key => $link) {
+            if (is_numeric($link['text'])) {
+                $this->links[$key]['text'] = $newParams[0];
+                array_shift($newParams);
+            }
+        }
+    }
+
+    /**
+     * Renders the breadcrumb object as an accessible html breadcrumb nav
+     *
+     * @return string
+     */
+    public function render()
+    {
+        $listItems = '';
+        $keys = array_keys($this->links);
+        foreach ($this->links as $key => $link) {
+            if (end($keys) == $key) {
+                $listItem =
+                    '<li class="breadcrumb-item active" aria-current="page">' .
+                    $link['text'] .
+                    '</li>';
+            } else {
+                $listItem =
+                    '<li class="breadcrumb-item">' .
+                    anchor($link['href'], $link['text']) .
+                    '</li>';
+            }
+
+            $listItems .= $listItem;
+        }
+
+        return '<nav aria-label="' .
+            lang('Breadcrumb.label') .
+            '"><ol class="breadcrumb">' .
+            $listItems .
+            '</ol></nav>';
+    }
+}
diff --git a/app/Models/UserModel.php b/app/Models/UserModel.php
index 420c002dae5a76cc68ca0ce46e9bae69c84905bb..4f9f7d033370db62677288fbb2b27928af724437 100644
--- a/app/Models/UserModel.php
+++ b/app/Models/UserModel.php
@@ -17,8 +17,11 @@ class UserModel extends \Myth\Auth\Models\UserModel
 
     public function getPodcastContributor($user_id, $podcast_id)
     {
-        return $this->select('users.*')
+        return $this->select(
+            'users.*, users_podcasts.podcast_id as podcast_id, auth_groups.name as podcast_role'
+        )
             ->join('users_podcasts', 'users_podcasts.user_id = users.id')
+            ->join('auth_groups', 'auth_groups.id = users_podcasts.group_id')
             ->where([
                 'users.id' => $user_id,
                 'podcast_id' => $podcast_id,
diff --git a/app/Views/_assets/styles/breadcrumb.css b/app/Views/_assets/styles/breadcrumb.css
new file mode 100644
index 0000000000000000000000000000000000000000..f2cb91620f3d705ceb52a267340bca7250dd1e81
--- /dev/null
+++ b/app/Views/_assets/styles/breadcrumb.css
@@ -0,0 +1,20 @@
+.breadcrumb {
+  @apply inline-flex flex-wrap px-1 py-2 text-sm text-gray-800;
+}
+
+.breadcrumb-item + .breadcrumb-item::before {
+  @apply inline-block px-1 text-gray-500;
+  content: "/";
+}
+
+.breadcrumb-item a {
+  @apply no-underline;
+
+  &:hover {
+    @apply underline;
+  }
+}
+
+.breadcrumb-item.active {
+  @apply font-semibold;
+}
diff --git a/app/Views/_assets/styles/index.css b/app/Views/_assets/styles/index.css
index 5f4c3b7fdaec0ce2056abacf6e69a053408fd33b..f12f46bb993ef86487ccce073593a77c8abe5439 100644
--- a/app/Views/_assets/styles/index.css
+++ b/app/Views/_assets/styles/index.css
@@ -1,2 +1,3 @@
 @import "./tailwind.css";
 @import "./layout.css";
+@import "./breadcrumb.css";
diff --git a/app/Views/admin/_header.php b/app/Views/admin/_header.php
index 3fc1d87718cadc62d28d5518eed3e24315a82457..b97236e3cf7829abf2332ae91be094cb7ce8d20a 100644
--- a/app/Views/admin/_header.php
+++ b/app/Views/admin/_header.php
@@ -1,10 +1,13 @@
 <header class="<?= $class ?>">
-    <a href="<?= route_to(
-        'admin_home'
-    ) ?>" class="inline-flex items-center text-xl">
-        <?= svg('logo-castopod', 'text-3xl mr-2 -ml-2') ?>
-        Admin
-    </a>
+    <div class="w-64">
+        <a href="<?= route_to(
+            'admin_home'
+        ) ?>" class="inline-flex items-center text-xl">
+            <?= svg('logo-castopod', 'text-3xl mr-2') ?>
+            Admin
+        </a>
+    </div>
+    <?= render_breadcrumb() ?>
     <div class="relative ml-auto" data-toggle="dropdown">
         <button type="button" class="inline-flex items-center px-2 py-1 outline-none focus:shadow-outline" id="myAccountDropdown" data-popper="button" aria-haspopup="true" aria-expanded="false">
             Hey <?= user()->username ?>
diff --git a/app/Views/admin/_layout.php b/app/Views/admin/_layout.php
index 75b11ac5ed750872c6f289822207b36c9565e1d8..f87c44f151c22d3f91e16bb9ea922f2a7e0f8b54 100644
--- a/app/Views/admin/_layout.php
+++ b/app/Views/admin/_layout.php
@@ -1,7 +1,3 @@
-<?php
-
-helper('html'); ?>
-
 <!DOCTYPE html>
 <html lang="en">
 
diff --git a/app/Views/admin/_partials/_episode-card.php b/app/Views/admin/_partials/_episode-card.php
index baf0b5677fb02b6236c30d87277d17dd38b1a24d..af1b46de638f237cf9e7fa246414154edcfcba84 100644
--- a/app/Views/admin/_partials/_episode-card.php
+++ b/app/Views/admin/_partials/_episode-card.php
@@ -1,7 +1,3 @@
-<?php
-
-helper('html'); ?>
-
 <article class="flex w-full max-w-lg mb-4 bg-white border rounded shadow">
     <img src="<?= $episode->image_url ?>" alt="<?= $episode->title ?>" class="object-cover w-32 h-32 rounded-l" />
     <div class="flex flex-col flex-1 px-4 py-2">
diff --git a/app/Views/admin/_partials/_user_info.php b/app/Views/admin/_partials/_user_info.php
new file mode 100644
index 0000000000000000000000000000000000000000..576311f197a6651403d56b3e10f0c3f15c70b53d
--- /dev/null
+++ b/app/Views/admin/_partials/_user_info.php
@@ -0,0 +1,32 @@
+<div class="px-4 py-5 bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
+    <dt class="text-sm font-medium leading-5 text-gray-500">
+    Email
+    </dt>
+    <dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
+    <?= $user->email ?>
+    </dd>
+</div>
+<div class="px-4 py-5 bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
+    <dt class="text-sm font-medium leading-5 text-gray-500">
+    Username
+    </dt>
+    <dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
+    <?= $user->username ?>
+    </dd>
+</div>
+<div class="px-4 py-5 bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
+    <dt class="text-sm font-medium leading-5 text-gray-500">
+    Roles
+    </dt>
+    <dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
+    [<?= implode(', ', $user->roles) ?>]
+    </dd>
+</div>
+<div class="px-4 py-5 bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
+    <dt class="text-sm font-medium leading-5 text-gray-500">
+    Permissions
+    </dt>
+    <dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
+    [<?= implode(', ', $user->permissions) ?>]
+    </dd>
+</div>
\ No newline at end of file
diff --git a/app/Views/admin/_sidenav.php b/app/Views/admin/_sidenav.php
index 8b51f3139707135965eaeacd974c656659ba366d..fa349177e1159796f9062149e296aa81a9d76a67 100644
--- a/app/Views/admin/_sidenav.php
+++ b/app/Views/admin/_sidenav.php
@@ -11,7 +11,7 @@ $navigation = [
 <nav class="<?= $class ?>">
     <?php foreach ($navigation as $section => $data): ?>
     <div class="mb-4">
-        <button class="inline-flex items-center w-full px-4 py-1 outline-none focus:shadow-outline" type="button">
+        <button class="inline-flex items-center w-full px-6 py-1 outline-none focus:shadow-outline" type="button">
             <?= icon($data['icon'], 'text-gray-500') ?>
             <span class="ml-2"><?= lang('AdminNavigation.' . $section) ?></span>
         </button>
diff --git a/app/Views/admin/contributor/list.php b/app/Views/admin/contributor/list.php
index f80732a2cf36c5fb89588ff590f6f6fa1fb0b322..b0e7eb41a074f809d7c75e7073a3223f72f518be 100644
--- a/app/Views/admin/contributor/list.php
+++ b/app/Views/admin/contributor/list.php
@@ -1,5 +1,3 @@
-<?php helper('html'); ?>
-
 <?= $this->extend('admin/_layout') ?>
 
 <?= $this->section('title') ?>
diff --git a/app/Views/admin/contributor/view.php b/app/Views/admin/contributor/view.php
new file mode 100644
index 0000000000000000000000000000000000000000..2aca7825701db03e64240e2e3d0daf3891c8ba93
--- /dev/null
+++ b/app/Views/admin/contributor/view.php
@@ -0,0 +1,28 @@
+<?= $this->extend('admin/_layout') ?>
+
+<?= $this->section('title') ?>
+<?= lang('Contributor.view', [
+    'username' => $contributor->username,
+    'podcastName' => $contributor->podcast->name,
+]) ?>
+<?= $this->endSection() ?>
+
+
+<?= $this->section('content') ?>
+<div class="px-4 py-5 bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
+    <dt class="text-sm font-medium leading-5 text-gray-500">
+    Username
+    </dt>
+    <dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
+    <?= $contributor->username ?>
+    </dd>
+</div>
+<div class="px-4 py-5 bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
+    <dt class="text-sm font-medium leading-5 text-gray-500">
+    Role
+    </dt>
+    <dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
+    <?= $contributor->podcast_role ?>
+    </dd>
+</div>
+<?= $this->endSection() ?>
diff --git a/app/Views/admin/episode/list.php b/app/Views/admin/episode/list.php
index 1b86523d64526d03e85478f5166650905eaccefa..59f457c40da05135c384f093fca3599634098ca1 100644
--- a/app/Views/admin/episode/list.php
+++ b/app/Views/admin/episode/list.php
@@ -3,17 +3,18 @@
 <?= $this->section('title') ?>
 
 <?= lang('Episode.all_podcast_episodes') ?> (<?= count($podcast->episodes) ?>)
+<a class="inline-flex items-center px-2 py-1 mb-2 ml-2 text-sm text-white bg-green-500 rounded shadow-xs outline-none hover:bg-green-600 focus:shadow-outline" href="<?= route_to(
+    'episode_create',
+    $podcast->id
+) ?>">
+<?= icon('add', 'mr-2') ?>
+<?= lang('Episode.create') ?></a>
 
 <?= $this->endSection() ?>
 
 
 <?= $this->section('content') ?>
 
-<a class="inline-block px-4 py-2 mb-2 border hover:bg-gray-100" href="<?= route_to(
-    'episode_create',
-    $podcast->id
-) ?>"><?= lang('Episode.create') ?></a>
-
 <?= view('admin/_partials/_episode-list.php', [
     'episodes' => $podcast->episodes,
 ]) ?>
diff --git a/app/Views/admin/episode/view.php b/app/Views/admin/episode/view.php
index 5bea39c45aaef7e388e69a914c1b2bc6594680a5..90b9a343ae0a12d6a343fae359963f41d3844430 100644
--- a/app/Views/admin/episode/view.php
+++ b/app/Views/admin/episode/view.php
@@ -1,12 +1,11 @@
 <?= $this->extend('admin/_layout') ?>
 
+<?= $this->section('title') ?>
+<?= $episode->title ?>
+<?= $this->endSection() ?>
+
 <?= $this->section('content') ?>
 
-<a class="underline hover:no-underline" href="<?= route_to(
-    'podcast_view',
-    $episode->podcast->id
-) ?>">< <?= lang('Episode.back_to_podcast') ?></a>
-<h1 class="text-2xl font-semibold"><?= $episode->title ?></h1>
 <img src="<?= $episode->image_url ?>" alt="Episode cover"  class="object-cover w-40 h-40 mb-6" />
 <audio controls preload="none" class="mb-12">
   <source src="<?= $episode->enclosure_url ?>" type="<?= $episode->enclosure_type ?>">
diff --git a/app/Views/admin/my_account/view.php b/app/Views/admin/my_account/view.php
index 92ce2ed5b330879f9a9c67e1b68ba56b76970bdf..556876d561d73b3cc7d4447f1973f841ce7410bc 100644
--- a/app/Views/admin/my_account/view.php
+++ b/app/Views/admin/my_account/view.php
@@ -7,30 +7,7 @@
 
 <?= $this->section('content') ?>
 
-<div class="px-4 py-5 bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
-    <dt class="text-sm font-medium leading-5 text-gray-500">
-    Email
-    </dt>
-    <dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
-    <?= user()->email ?>
-    </dd>
-</div>
-<div class="px-4 py-5 bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
-    <dt class="text-sm font-medium leading-5 text-gray-500">
-    Username
-    </dt>
-    <dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
-    <?= user()->username ?>
-    </dd>
-</div>
-<div class="px-4 py-5 bg-gray-50 sm:grid sm:grid-cols-3 sm:gap-4 sm:px-6">
-    <dt class="text-sm font-medium leading-5 text-gray-500">
-    Permissions
-    </dt>
-    <dd class="mt-1 text-sm leading-5 text-gray-900 sm:mt-0 sm:col-span-2">
-    [<?= implode(', ', user()->permissions) ?>]
-    </dd>
-</div>
+<?= view('admin/_partials/_user_info.php', ['user' => user()]) ?>
 
 <?= $this->endSection()
 ?>
diff --git a/app/Views/admin/podcast/list.php b/app/Views/admin/podcast/list.php
index 9f18b1cfec73921a330bbab658bf0a6140200fca..2efbe4d931ec7a74c120636ebd79d2f1c16be014 100644
--- a/app/Views/admin/podcast/list.php
+++ b/app/Views/admin/podcast/list.php
@@ -1,5 +1,3 @@
-<?php helper('html'); ?>
-
 <?= $this->extend('admin/_layout') ?>
 
 <?= $this->section('title') ?>
diff --git a/app/Views/admin/podcast/view.php b/app/Views/admin/podcast/view.php
index 9a781031c0ad784d2b7fce6d6d93f55879344b26..3f21185e41a7191bae3a312492f63102d246bb7a 100644
--- a/app/Views/admin/podcast/view.php
+++ b/app/Views/admin/podcast/view.php
@@ -1,7 +1,3 @@
-<?php
-
-helper('html'); ?>
-
 <?= $this->extend('admin/_layout') ?>
 
 <?= $this->section('title') ?>
diff --git a/app/Views/admin/user/list.php b/app/Views/admin/user/list.php
index 078d14ea70758331802af5dce8b2cbb3e7193e67..a8d096358b4d1d83b1ab3f24b7acf5f9083d51df 100644
--- a/app/Views/admin/user/list.php
+++ b/app/Views/admin/user/list.php
@@ -1,5 +1,3 @@
-<?php helper('html'); ?>
-
 <?= $this->extend('admin/_layout') ?>
 
 <?= $this->section('title') ?>
diff --git a/app/Views/admin/user/view.php b/app/Views/admin/user/view.php
new file mode 100644
index 0000000000000000000000000000000000000000..42aa6495f80ad76e5493c7f64fec78628120a4ca
--- /dev/null
+++ b/app/Views/admin/user/view.php
@@ -0,0 +1,12 @@
+<?= $this->extend('admin/_layout') ?>
+
+<?= $this->section('title') ?>
+<?= lang('User.view', ['username' => $user->username]) ?>
+<?= $this->endSection() ?>
+
+
+<?= $this->section('content') ?>
+
+<?= view('admin/_partials/_user_info.php', ['user' => $user]) ?>
+
+<?= $this->endSection() ?>
diff --git a/tailwind.config.js b/tailwind.config.js
index 52ddd9b497584b0ab739d546cf3536d5d2cdf2a7..2f7c33d367518e1d93726802f37a628f1cc95698 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -1,7 +1,7 @@
 /* eslint-disable */
 
 module.exports = {
-  purge: ["./app/Views/**/*.php", "./app/Views/**/*.js"],
+  purge: ["./app/Views/**/*.php", "./app/Views/**/*.ts"],
   theme: {
     extend: {},
   },