diff --git a/apps/dashboard/lib/Controller/DashboardController.php b/apps/dashboard/lib/Controller/DashboardController.php
index f6fea2aaf452edb82cc42b2ffd9e8145a1113ac7..1c11ca245185b8dce80da3f524a5d7e36a85b398 100644
--- a/apps/dashboard/lib/Controller/DashboardController.php
+++ b/apps/dashboard/lib/Controller/DashboardController.php
@@ -33,11 +33,13 @@ use OCP\AppFramework\Controller;
 use OCP\AppFramework\Http;
 use OCP\AppFramework\Http\FileDisplayResponse;
 use OCP\AppFramework\Http\JSONResponse;
+use OCP\AppFramework\Http\NotFoundResponse;
 use OCP\AppFramework\Http\TemplateResponse;
 use OCP\Dashboard\IManager;
 use OCP\Dashboard\IWidget;
 use OCP\Dashboard\RegisterWidgetEvent;
 use OCP\EventDispatcher\IEventDispatcher;
+use OCP\Files\NotFoundException;
 use OCP\IConfig;
 use OCP\IInitialStateService;
 use OCP\IRequest;
@@ -105,6 +107,7 @@ class DashboardController extends Controller {
 		$this->inititalStateService->provideInitialState('dashboard', 'layout', $userLayout);
 		$this->inititalStateService->provideInitialState('dashboard', 'firstRun', $this->config->getUserValue($this->userId, 'dashboard', 'firstRun', '1') === '1');
 		$this->inititalStateService->provideInitialState('dashboard', 'shippedBackgrounds', BackgroundService::SHIPPED_BACKGROUNDS);
+		$this->inititalStateService->provideInitialState('dashboard', 'background', $this->config->getUserValue($this->userId, 'dashboard', 'background', 'default'));
 		$this->config->setUserValue($this->userId, 'dashboard', 'firstRun', '0');
 
 		return new TemplateResponse('dashboard', 'index');
@@ -123,16 +126,20 @@ class DashboardController extends Controller {
 	/**
 	 * @NoAdminRequired
 	 */
-	public function setBackground($path = null, $url = null): JSONResponse {
+	public function setBackground($path = null, $url = null, $shipped = null): JSONResponse {
 		// FIXME: store current version of the background and return the result
 		// FIXME: handle shipped backgrounds  avoid file duplication
 		// FIXME: allow to reset to default ones
+		if ($shipped !== null) {
+			$this->backgroundService->setShippedBackground($shipped);
+		}
 		if ($path !== null) {
 			$this->backgroundService->setFileBackground($path);
 		}
 		if ($url !== null) {
 			$this->backgroundService->setUrlBackground($url);
 		}
+		$this->backgroundService->setDefaultBackground();
 		return new JSONResponse([]);
 	}
 
@@ -140,9 +147,13 @@ class DashboardController extends Controller {
 	 * @NoAdminRequired
 	 * @NoCSRFRequired
 	 */
-	public function getBackground(): FileDisplayResponse {
+	public function getBackground() {
 		$file = $this->backgroundService->getBackground();
-		$response = new FileDisplayResponse($file, Http::STATUS_OK, ['Content-Type' => $file->getMimeType()]);
-		return $response;
+		if ($file !== null) {
+			$response = new FileDisplayResponse($file, Http::STATUS_OK, ['Content-Type' => $file->getMimeType()]);
+			$response->cacheFor(24 * 60 * 60);
+			return $response;
+		}
+		return new NotFoundResponse();
 	}
 }
diff --git a/apps/dashboard/lib/Service/BackgroundService.php b/apps/dashboard/lib/Service/BackgroundService.php
index 2046513851f277f9caaa41b1d987daef6672a6f9..06e0a451b880e1ea1464f46bc5ab2b8f662012f9 100644
--- a/apps/dashboard/lib/Service/BackgroundService.php
+++ b/apps/dashboard/lib/Service/BackgroundService.php
@@ -32,6 +32,7 @@ use OCP\Files\IAppData;
 use OCP\Files\IRootFolder;
 use OCP\Files\NotFoundException;
 use OCP\Files\SimpleFS\ISimpleFile;
+use OCP\IConfig;
 
 class BackgroundService {
 
@@ -64,7 +65,7 @@ class BackgroundService {
 		'yana-sichikova-sergey-ovachev-stone-flower-2k.jpg',
 	];
 
-	public function __construct(IRootFolder $rootFolder, IAppData $appData, $userId) {
+	public function __construct(IRootFolder $rootFolder, IAppData $appData, IConfig $config, $userId) {
 		if ($userId === null) {
 			return;
 		}
@@ -74,14 +75,26 @@ class BackgroundService {
 		} catch (NotFoundException $e) {
 			$this->dashboardUserFolder = $appData->newFolder($userId);
 		}
+		$this->config = $config;
+		$this->userId = $userId;
+	}
+
+	public function setDefaultBackground() {
+		$this->config->deleteUserValue($this->userId, 'dashboard', 'background');
 	}
 
 	public function setFileBackground($path) {
+		$this->config->setUserValue($this->userId, 'dashboard', 'background', 'custom');
 		$file = $this->userFolder->get($path);
 		$newFile = $this->dashboardUserFolder->newFile('background.jpg', $file->fopen('r'));
 	}
 
+	public function setShippedBackground($fileName) {
+		$this->config->setUserValue($this->userId, 'dashboard', 'background', $fileName);
+	}
+
 	public function setUrlBackground($url) {
+		$this->config->setUserValue($this->userId, 'dashboard', 'background', 'custom');
 		if (substr($url, 0, 1) === '/') {
 			$url = \OC::$server->getURLGenerator()->getAbsoluteURL($url);
 		}
@@ -92,11 +105,15 @@ class BackgroundService {
 		$newFile = $this->dashboardUserFolder->newFile('background.jpg', $content);
 	}
 
-	/**
-	 * @throws NotFoundException
-	 */
-	public function getBackground(): ISimpleFile {
-		return $this->dashboardUserFolder->getFile('background.jpg');
+	public function getBackground() {
+		$background = $this->config->getUserValue($this->userId, 'dashboard', 'background', 'default');
+		if ($background === 'custom') {
+			try {
+				return $this->dashboardUserFolder->getFile('background.jpg');
+			} catch (NotFoundException $e) {
+			}
+		}
+		return null;
 	}
 
 }
diff --git a/apps/dashboard/src/App.vue b/apps/dashboard/src/App.vue
index 807a0e6f61ed54563d0710ab993f1875fefc858d..db2f20382b17412673f9588d76932850e66fb941 100644
--- a/apps/dashboard/src/App.vue
+++ b/apps/dashboard/src/App.vue
@@ -76,6 +76,7 @@ import BackgroundSettings from './components/BackgroundSettings'
 
 const panels = loadState('dashboard', 'panels')
 const firstRun = loadState('dashboard', 'firstRun')
+const background = loadState('dashboard', 'background')
 
 const prefixWithBaseUrl = (url) => generateFilePath('dashboard', '', 'img/') + url
 
@@ -103,18 +104,22 @@ export default {
 			modal: false,
 			appStoreUrl: generateUrl('/settings/apps/dashboard'),
 			statuses: {},
+			background,
 			backgroundTime: Date.now(),
 			defaultBackground: window.OCA.Accessibility.theme === 'dark' ? prefixWithBaseUrl('flickr-148302424@N05-36591009215.jpg?v=1') : prefixWithBaseUrl('flickr-paszczak000-8715851521.jpg?v=1'),
 		}
 	},
 	computed: {
 		backgroundImage() {
-			// FIXME: make this dependent if the default is set or not
-			return generateUrl('/apps/dashboard/background') + '?v=' + this.backgroundTime
-			if (window.OCA.Accessibility.theme === 'dark') {
-				return !isMobile ? prefixWithBaseUrl('flickr-148302424@N05-36591009215.jpg?v=1') : prefixWithBaseUrl('flickr-148302424@N05-36591009215-mobile.jpg?v=1')
+			if (this.background === 'default') {
+				if (window.OCA.Accessibility.theme === 'dark') {
+					return !isMobile ? prefixWithBaseUrl('flickr-148302424@N05-36591009215.jpg?v=1') : prefixWithBaseUrl('flickr-148302424@N05-36591009215-mobile.jpg?v=1')
+				}
+				return !isMobile ? prefixWithBaseUrl('flickr-paszczak000-8715851521.jpg?v=1') : prefixWithBaseUrl('flickr-paszczak000-8715851521-mobile.jpg?v=1')
+			} else if (this.background === 'custom') {
+				return generateUrl('/apps/dashboard/background') + '?v=' + this.backgroundTime
 			}
-			return !isMobile ? prefixWithBaseUrl('flickr-paszczak000-8715851521.jpg?v=1') : prefixWithBaseUrl('flickr-paszczak000-8715851521-mobile.jpg?v=1')
+			return prefixWithBaseUrl(this.background)
 		},
 		tooltip() {
 			if (!this.firstRun) {
@@ -254,8 +259,8 @@ export default {
 				this.firstRun = false
 			}, 1000)
 		},
-		updateBackground(date) {
-			this.backgroundTime = date
+		updateBackground(backgroundType) {
+			this.background = backgroundType
 		},
 	},
 }
diff --git a/apps/dashboard/src/components/BackgroundSettings.vue b/apps/dashboard/src/components/BackgroundSettings.vue
index 7645d8fb832a0d668b84f564bcc38a252b42f7c5..ad7898f8abec009ee39ddf32c97421ebd05e9da2 100644
--- a/apps/dashboard/src/components/BackgroundSettings.vue
+++ b/apps/dashboard/src/components/BackgroundSettings.vue
@@ -22,18 +22,25 @@
 
 <template>
 	<div class="background-selector">
-		<div v-if="loading">Loading</div>
-		<div v-for="background in shippedBackgrounds"
-			:key="background"
-			class="background"
-			@click="setUrl(background)">
-			<img :src="background">
+		<div class="background default"
+			:class="{ 'icon-loading': loading === 'default' }"
+			@click="setDefault()">
+			<div class="background--preview">
+				Default
+			</div>
 		</div>
 		<div class="background" @click="pickFile">
 			<a>
 				{{ t('dashboard', 'Pick an image from your files') }}
 			</a>
 		</div>
+		<div v-for="background in shippedBackgrounds"
+			:key="background.name"
+			class="background"
+			:class="{ 'icon-loading': loading === background.name }"
+			@click="setShipped(background.name)">
+			<div class="background--preview" :style="{ 'background-image': 'url(' + background.url + ')' }" />
+		</div>
 	</div>
 </template>
 
@@ -41,10 +48,23 @@
 import axios from '@nextcloud/axios'
 import { generateUrl, generateFilePath } from '@nextcloud/router'
 import { loadState } from '@nextcloud/initial-state'
+import isMobile from '../mixins/isMobile'
 
 const prefixWithBaseUrl = (url) => generateFilePath('dashboard', '', 'img/') + url
 const shippedBackgroundList = loadState('dashboard', 'shippedBackgrounds')
 
+const getBackgroundUrl = (background, time = 0) => {
+	if (background === 'default') {
+		if (window.OCA.Accessibility.theme === 'dark') {
+			return !isMobile ? prefixWithBaseUrl('flickr-148302424@N05-36591009215.jpg?v=1') : prefixWithBaseUrl('flickr-148302424@N05-36591009215-mobile.jpg?v=1')
+		}
+		return !isMobile ? prefixWithBaseUrl('flickr-paszczak000-8715851521.jpg?v=1') : prefixWithBaseUrl('flickr-paszczak000-8715851521-mobile.jpg?v=1')
+	} else if (background === 'custom') {
+		return generateUrl('/apps/dashboard/background') + '?v=' + time
+	}
+	return prefixWithBaseUrl(background)
+}
+
 export default {
 	name: 'BackgroundSettings',
 	data() {
@@ -56,36 +76,43 @@ export default {
 	computed: {
 		shippedBackgrounds() {
 			return shippedBackgroundList.map((item) => {
-				return prefixWithBaseUrl(item)
+				return {
+					name: item,
+					url: prefixWithBaseUrl(item),
+				}
 			})
 		},
 	},
 	methods: {
-		async update() {
+		async update(state) {
 			const date = Date.now()
-			this.backgroundImage = generateUrl('/apps/dashboard/background') + '?v=' + date
+			this.backgroundImage = getBackgroundUrl(state, date)
 			const image = new Image()
 			image.onload = () => {
-				this.$emit('updateBackground', date)
+				this.$emit('updateBackground', state)
 				this.loading = false
 			}
 			image.src = this.backgroundImage
 		},
-		setDefault() {
+		async setDefault() {
 			console.debug('SetDefault')
-			this.update()
+			await axios.post(generateUrl('/apps/dashboard/background'))
+			this.update('default')
+		},
+		async setShipped(shipped) {
+			this.loading = shipped
+			await axios.post(generateUrl('/apps/dashboard/background'), { shipped })
+			this.update(shipped)
 		},
 		async setUrl(url) {
 			this.loading = true
-			console.debug('SetUrl ' + url)
 			await axios.post(generateUrl('/apps/dashboard/background'), { url })
-			this.update()
+			this.update('custom')
 		},
 		async setFile(path) {
 			this.loading = true
-			console.debug('SetFile ' + path)
 			await axios.post(generateUrl('/apps/dashboard/background'), { path })
-			this.update()
+			this.update('custom')
 		},
 		pickFile() {
 			window.OC.dialogs.filepicker(t('dashboard', 'Insert from {productName}', { productName: OC.theme.name }), (path, type) => {
@@ -114,8 +141,11 @@ export default {
 				background-image: var(--color-background-dark);
 			}
 
-			& img {
+			&--preview {
 				width: 140px;
+				height: 90px;
+				background-size: cover;
+				background-position: center center;
 			}
 
 			&:hover {