diff --git a/api/funkwhale_api/radios/serializers.py b/api/funkwhale_api/radios/serializers.py
index 520e98652f4238de071ae49f419525f745e97785..2e7e6a409fb4e4102f1d713faaeb94ca3b7e759a 100644
--- a/api/funkwhale_api/radios/serializers.py
+++ b/api/funkwhale_api/radios/serializers.py
@@ -1,6 +1,7 @@
 from rest_framework import serializers
 
 from funkwhale_api.music.serializers import TrackSerializerNested
+from funkwhale_api.users.serializers import UserBasicSerializer
 
 from . import filters
 from . import models
@@ -15,6 +16,8 @@ class FilterSerializer(serializers.Serializer):
 
 
 class RadioSerializer(serializers.ModelSerializer):
+    user = UserBasicSerializer(read_only=True)
+
     class Meta:
         model = models.Radio
         fields = (
diff --git a/api/funkwhale_api/radios/views.py b/api/funkwhale_api/radios/views.py
index 42652644224446ccade4d43b36c995581bb15783..ffd1d16593ddc2648ec2748dc3b4174afe41f7ed 100644
--- a/api/funkwhale_api/radios/views.py
+++ b/api/funkwhale_api/radios/views.py
@@ -20,6 +20,7 @@ class RadioViewSet(
         mixins.RetrieveModelMixin,
         mixins.UpdateModelMixin,
         mixins.ListModelMixin,
+        mixins.DestroyModelMixin,
         viewsets.GenericViewSet):
 
     serializer_class = serializers.RadioSerializer
@@ -40,6 +41,16 @@ class RadioViewSet(
             raise Http404
         return serializer.save(user=self.request.user)
 
+    @detail_route(methods=['get'])
+    def tracks(self, request, *args, **kwargs):
+        radio = self.get_object()
+        tracks = radio.get_candidates().for_nested_serialization()
+
+        page = self.paginate_queryset(tracks)
+        if page is not None:
+            serializer = TrackSerializerNested(page, many=True)
+            return self.get_paginated_response(serializer.data)
+
     @list_route(methods=['get'])
     def filters(self, request, *args, **kwargs):
         serializer = serializers.FilterSerializer(
diff --git a/changes/changelog.d/64.feature b/changes/changelog.d/64.feature
new file mode 100644
index 0000000000000000000000000000000000000000..87fe7052232c5e85ff9961e90710458f082a0fad
--- /dev/null
+++ b/changes/changelog.d/64.feature
@@ -0,0 +1 @@
+Add a detail page for radios (#64)
\ No newline at end of file
diff --git a/front/src/components/library/radios/Builder.vue b/front/src/components/library/radios/Builder.vue
index 9b8786cc6eb91181dcbb3e17a697f6b5a8edc881..5fbf0c992618616e0c0be0f76e458deb997737b8 100644
--- a/front/src/components/library/radios/Builder.vue
+++ b/front/src/components/library/radios/Builder.vue
@@ -180,7 +180,7 @@ export default {
         let url = 'radios/radios/'
         axios.post(url, final).then((response) => {
           self.$router.push({
-            name: 'library.radios.edit',
+            name: 'library.radios.detail',
             params: {
               id: response.data.id
             }
diff --git a/front/src/components/radios/Card.vue b/front/src/components/radios/Card.vue
index d2c14c37c78dfbc23b858c93a5eddd28b3519fb9..17de3c85fe3c67d5a124d046aa9e5fa233503396 100644
--- a/front/src/components/radios/Card.vue
+++ b/front/src/components/radios/Card.vue
@@ -1,7 +1,11 @@
 <template>
     <div class="ui card">
       <div class="content">
-        <div class="header">{{ radio.name }}</div>
+        <div class="header">
+          <router-link class="discrete link" :to="{name: 'library.radios.detail', params: {id: radio.id}}">
+            {{ radio.name }}
+          </router-link>
+        </div>
         <div class="description">
           {{ radio.description }}
         </div>
diff --git a/front/src/router/index.js b/front/src/router/index.js
index 802844461325560a48cf8002f21ef8e3f5462594..d41764227bb1a1cbd3536791ae24275b7228d249 100644
--- a/front/src/router/index.js
+++ b/front/src/router/index.js
@@ -18,6 +18,7 @@ import LibraryTrack from '@/components/library/Track'
 import LibraryImport from '@/components/library/import/Main'
 import LibraryRadios from '@/components/library/Radios'
 import RadioBuilder from '@/components/library/radios/Builder'
+import RadioDetail from '@/views/radios/Detail'
 import BatchList from '@/components/library/import/BatchList'
 import BatchDetail from '@/components/library/import/BatchDetail'
 import RequestsList from '@/components/requests/RequestsList'
@@ -111,6 +112,7 @@ export default new Router({
         },
         { path: 'radios/build', name: 'library.radios.build', component: RadioBuilder, props: true },
         { path: 'radios/build/:id', name: 'library.radios.edit', component: RadioBuilder, props: true },
+        { path: 'radios/:id', name: 'library.radios.detail', component: RadioDetail, props: true },
         {
           path: 'playlists/',
           name: 'library.playlists.browse',
diff --git a/front/src/views/radios/Detail.vue b/front/src/views/radios/Detail.vue
new file mode 100644
index 0000000000000000000000000000000000000000..397dcb49ec3fbd7e05fa45007f38418712a2d3b7
--- /dev/null
+++ b/front/src/views/radios/Detail.vue
@@ -0,0 +1,110 @@
+<template>
+  <div>
+    <div v-if="isLoading" class="ui vertical segment" v-title="'Radio'">
+      <div :class="['ui', 'centered', 'active', 'inline', 'loader']"></div>
+    </div>
+    <div v-if="!isLoading && radio" class="ui head vertical center aligned stripe segment" v-title="radio.name">
+      <div class="segment-content">
+        <h2 class="ui center aligned icon header">
+          <i class="circular inverted feed blue icon"></i>
+          <div class="content">
+            {{ radio.name }}
+            <div class="sub header">
+              Radio containing {{ tracks.length }} tracks,
+              by <username :username="radio.user.username"></username>
+            </div>
+          </div>
+        </h2>
+        <div class="ui hidden divider"></div>
+        <radio-button type="custom" :custom-radio-id="radio.id"></radio-button>
+        <router-link class="ui icon button" :to="{name: 'library.radios.edit', params: {id: radio.id}}" exact>
+          <i class="pencil icon"></i>
+          Edit…
+        </router-link>
+        <dangerous-button class="labeled icon" :action="deleteRadio">
+          <i class="trash icon"></i> Delete
+          <p slot="modal-header">Do you want to delete the radio "{{ radio.name }}"?</p>
+          <p slot="modal-content">This will completely delete this radio and cannot be undone.</p>
+          <p slot="modal-confirm">Delete radio</p>
+        </dangerous-button>
+      </div>
+    </div>
+    <div class="ui vertical stripe segment">
+      <h2>Tracks</h2>
+      <track-table :tracks="tracks"></track-table>
+      <div class="ui center aligned basic segment">
+        <pagination
+          v-if="totalTracks > 25"
+          @page-changed="selectPage"
+          :current="page"
+          :paginate-by="25"
+          :total="totalTracks"
+          ></pagination>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import axios from 'axios'
+import TrackTable from '@/components/audio/track/Table'
+import RadioButton from '@/components/radios/Button'
+import Pagination from '@/components/Pagination'
+
+export default {
+  props: {
+    id: {required: true}
+  },
+  components: {
+    TrackTable,
+    RadioButton,
+    Pagination
+  },
+  data: function () {
+    return {
+      isLoading: false,
+      radio: null,
+      tracks: [],
+      totalTracks: 0,
+      page: 1
+    }
+  },
+  created: function () {
+    this.fetch()
+  },
+  methods: {
+    selectPage: function (page) {
+      this.page = page
+    },
+    fetch: function () {
+      let self = this
+      self.isLoading = true
+      let url = 'radios/radios/' + this.id + '/'
+      axios.get(url).then((response) => {
+        self.radio = response.data
+        axios.get(url + 'tracks', {params: {page: this.page}}).then((response) => {
+          console.log(response.data.count)
+          this.totalTracks = response.data.count
+          this.tracks = response.data.results
+        }).then(() => {
+          self.isLoading = false
+        })
+      })
+    },
+    deleteRadio () {
+      let self = this
+      let url = 'radios/radios/' + this.id + '/'
+      axios.delete(url).then((response) => {
+        self.$router.push({
+          path: '/library'
+        })
+      })
+    }
+  },
+  watch: {
+    page: function () {
+      this.fetch()
+    }
+  }
+}
+</script>