Update:Docs page

This commit is contained in:
advplyr 2022-05-05 18:13:06 -05:00
parent 0f64c39e2d
commit 6ec83f12a1
13 changed files with 708 additions and 331 deletions

View file

@ -0,0 +1,35 @@
<template>
<div id="intro" class="py-10 md:py-40">
<div class="flex md:-ml-8 mb-8">
<div>
<span class="material-icons text-error text-2xl">priority_high</span>
</div>
<p class="pl-2 text-sm md:text-lg">Server v2.0.0 and higher is not backwards compatible with older mobile app versions! Make sure you are using server v2.0.0 and up with mobile apps v0.9.41-beta and up.</p>
</div>
<div class="flex md:-ml-8 mb-8">
<div>
<span class="material-icons text-success text-2xl">priority_high</span>
</div>
<p class="pl-2 text-sm md:text-lg">
Help needed writing documentation! This website is on <a href="https://github.com/advplyr/audiobookshelf-web" target="_blank" class="text-blue-500 underline">github</a>. Join the <a href="https://github.com/advplyr/audiobookshelf/discussions" target="_blank" class="text-blue-500 underline">discussion</a>,
<a href="https://github.com/advplyr/audiobookshelf/issues" target="_blank" class="text-blue-500 underline">report an issue</a> or contact me directly at <a href="mailto:advplyr@protonmail.com" class="text-blue-500 underline">advplyr@protonmail.com</a>.
</p>
</div>
<p class="px-2 text-sm md:text-lg">
Audiobookshelf works best when you have an organized directory structure like shown below. This is because information is taken from your folder names. This includes the author name, series name, book title, publish year, volume number, and subtitle. However, you can enable scanner settings to prefer using your audio file ID3 tags or an OPF file over using folder names.
</p>
</div>
</template>
<script>
export default {
data() {
return {}
},
computed: {},
methods: {},
mounted() {}
}
</script>

View file

@ -0,0 +1,29 @@
<template>
<div id="book-additional-metadata" class="py-10 md:py-20">
<h1 class="text-xl md:text-3xl mb-4 md:-ml-8">
<nuxt-link to="#book-additional-metadata"><span class="material-icons text-lg md:text-xl text-gray-400 hover:text-white cursor-pointer mr-2">tag</span></nuxt-link
>Additional Metadata Files
</h1>
<p class="my-4">If you have a file named <span class="bg-white bg-opacity-10 text-gray-100 rounded-md p-1 font-mono">desc.txt</span> in the library item folder it will be used as the description.</p>
<p class="my-4">If you have a file named <span class="bg-white bg-opacity-10 text-gray-100 rounded-md p-1 font-mono">reader.txt</span> in the library item folder it will be used as the narrator.</p>
<p class="mt-4">If you have an <a href="https://docs.fileformat.com/ebook/opf/" target="_blank" class="text-blue-500 hover:text-blue-300 underline">OPF file</a> with extension <span class="bg-white bg-opacity-10 text-gray-100 rounded-md p-1 font-mono">.opf</span> in the library item folder it will be parsed.<br />Details extracted from OPF:</p>
<div v-for="(key, index) in opfKeys" :key="key" class="inline-block">
<span class="bg-white bg-opacity-10 text-gray-100 rounded-md px-1 py-0.5 font-mono">{{ key }}</span
><span v-if="index < opfKeys.length - 1">,&nbsp;</span>
</div>
</div>
</template>
<script>
export default {
data() {
return {
opfKeys: ['title', 'author', 'narrator', 'publishYear', 'publisher', 'isbn', 'description', 'genres', 'language', 'series', 'volumeNumber']
}
},
computed: {},
methods: {},
mounted() {}
}
</script>

View file

@ -0,0 +1,94 @@
<template>
<div id="book-audio-metadata" class="py-10 md:py-20">
<h1 class="text-xl md:text-3xl mb-4 md:-ml-8">
<nuxt-link to="#book-audio-metadata"><span class="material-icons text-lg md:text-xl text-gray-400 hover:text-white cursor-pointer mr-2">tag</span></nuxt-link
>Audio File Metadata
</h1>
<p class="mb-4 text-sm md:text-base">Audiobookshelf uses the ID3 metadata tags in audio files to populate data.</p>
<div class="flex -ml-8 mb-4">
<div>
<span class="material-icons text-warning text-2xl">priority_high</span>
</div>
<p class="pl-2 text-sm md:text-base">Data parsed from the folder structure and filenames takes priority over ID3 tags unless you have enabled the scanner setting "Prefer Audio Metadata".</p>
</div>
<p class="mb-4 text-sm md:text-base">Metadata on audio files will be mapped as follows (second tag after "/" is a fallback):</p>
<table>
<tbody>
<tr class="bg-white bg-opacity-10 text-sm text-left font-semibold">
<th>ID3 Tag <span class="text-gray-300 font-normal text-xs">&nbsp;(case-insensitive)</span></th>
<th>Audiobookshelf Data</th>
</tr>
<tr>
<td>artist / album-artist</td>
<td>Author</td>
</tr>
<tr>
<td>album / title</td>
<td>Title</td>
</tr>
<tr>
<td>subtitle</td>
<td>Subtitle</td>
</tr>
<tr>
<td>publisher</td>
<td>Publisher</td>
</tr>
<tr>
<td>year</td>
<td>Publish Year</td>
</tr>
<tr>
<td>composer</td>
<td>Narrator</td>
</tr>
<tr>
<td>description</td>
<td>Description</td>
</tr>
<tr>
<td>genre</td>
<td>Genres <span class="text-sm text-warning">*</span></td>
</tr>
<tr>
<td>series</td>
<td>Series</td>
</tr>
<tr>
<td>series-part</td>
<td>Volume Number</td>
</tr>
<tr>
<td>language / lang</td>
<td>Language</td>
</tr>
<tr>
<td>isbn</td>
<td>ISBN</td>
</tr>
<tr>
<td>asin</td>
<td>ASIN</td>
</tr>
</tbody>
</table>
<p class="text-sm pt-2"><span class="text-sm text-warning">*</span> Genre meta tag can include multiple genres separated by "/", "//", or ";". e.g. "Science Fiction/Fiction/Fantasy"</p>
<p class="my-4">Embedded cover art will be extracted and used only if there are no images in the book folder.</p>
</div>
</template>
<script>
export default {
data() {
return {}
},
computed: {},
methods: {},
mounted() {}
}
</script>

View file

@ -0,0 +1,44 @@
<template>
<div id="book-tracks" class="py-10 md:py-20">
<h1 class="text-xl md:text-3xl mb-4 md:-ml-8">
<nuxt-link to="#book-tracks"><span class="material-icons text-lg md:text-xl text-gray-400 hover:text-white cursor-pointer mr-2">tag</span></nuxt-link
>Audio Tracks
</h1>
<p class="text-sm md:text-base">An audiobook contains tracks. Tracks are audio files assigned a track number. <br />The track number is parsed from the audio filename and from the ID3 tags of the audio file.<br />Audiobooks that are made up of multiple discs or cd's will be ordered first by disc number then by track number.</p>
<table class="my-4">
<tbody>
<tr class="bg-white bg-opacity-10 text-sm text-left font-semibold">
<th>Key</th>
<th>ID3 Tags <span class="text-gray-300 font-normal text-xs">&nbsp;(case-insensitive)</span></th>
<th class="hidden md:block">Audio Filename</th>
</tr>
<tr>
<td>TrackNumber</td>
<td>track, trck, trk</td>
<td class="hidden md:block">First number after removing title, publish year, series, author, disc number</td>
</tr>
<tr>
<td>DiscNumber</td>
<td>discnumber, disc, disk, tpos</td>
<td class="hidden md:block">Number following "Disc" or "CD" (example: "Atlas Shrugged CD 01 - 1.mp3")</td>
</tr>
</tbody>
</table>
<p class="mb-2">The scanner will choose the more accurate track/disc number between the filename and ID3 tag numbers.</p>
<p>Tracks can be manually ordered and enabled/disabled by pressing the "Manage Tracks" button on the audiobook page.</p>
</div>
</template>
<script>
export default {
data() {
return {}
},
computed: {},
methods: {},
mounted() {}
}
</script>

View file

@ -0,0 +1,48 @@
<template>
<div id="book-author-folder" class="py-10 md:py-20">
<h1 class="text-xl md:text-3xl mb-4 md:-ml-8">
<nuxt-link to="#book-author-folder"><span class="material-icons text-lg text-gray-400 hover:text-white cursor-pointer mr-2">tag</span></nuxt-link
>Author Folder Naming
</h1>
<p class="mb-4 text-sm md:text-base">Supports "Last, First" author naming as well as multiple authors separated by "," or "&".<br /><br />Valid author folder names:</p>
<div class="p-4 border border-opacity-10 bg-primary bg-opacity-20 font-mono">
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Ichiro Kishimi</p>
</div>
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Kishimi, Ichiro</p>
</div>
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Ichiro Kishimi, Fumitake Koga</p>
</div>
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Kishimi, Ichiro, Koga, Fumitake</p>
</div>
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Ichiro Kishimi & Fumitake Koga</p>
</div>
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Kishimi, Ichiro & Koga, Fumitake</p>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {}
},
computed: {},
methods: {},
mounted() {}
}
</script>

View file

@ -0,0 +1,120 @@
<template>
<div id="book-structure" class="py-10 md:py-20">
<h1 class="text-xl md:text-3xl mb-4 md:-ml-8">
<nuxt-link to="#book-structure"><span class="material-icons text-lg md:text-xl text-gray-400 hover:text-white cursor-pointer mr-2">tag</span></nuxt-link
>Book Directory Structure
</h1>
<p class="mb-4 text-sm md:text-base">Here is an example supported directory structure</p>
<div class="p-4 border border-opacity-10 bg-primary bg-opacity-20 font-mono">
<div class="flex py-1 max-w-2xl">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Terry Goodkind</p>
<div class="hidden md:block flex-grow" />
<span class="hidden md:block text-white text-opacity-50 pl-4">&lt;-- Author</span>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;</span>
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Sword of Truth</p>
<div class="hidden md:block flex-grow" />
<span class="hidden md:block text-white text-opacity-50 pl-4">&lt;-- Series</span>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;&nbsp;-&nbsp;</span>
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Vol 1 - 1994 - Wizards First Rule</p>
<div class="hidden md:block flex-grow" />
<span class="hidden md:block text-white text-opacity-50 pl-4">&lt;-- Title&nbsp;</span>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;&nbsp;-&nbsp;&nbsp;-&nbsp;</span>
<span class="material-icons">audiotrack</span>
<p class="pl-2">Audio Track 1.mp3</p>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;&nbsp;-&nbsp;&nbsp;-&nbsp;</span>
<span class="material-icons">audiotrack</span>
<p class="pl-2">Audio Track 2.mp3</p>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;&nbsp;-&nbsp;&nbsp;-&nbsp;</span>
<span class="material-icons">crop_original</span>
<p class="pl-2">Cover.jpg</p>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;&nbsp;-&nbsp;</span>
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Vol 2 - 1995 - Stone of Tears</p>
<div class="hidden md:block flex-grow" />
<span class="hidden md:block text-white text-opacity-50 pl-4">&lt;-- Title&nbsp;</span>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;&nbsp;-&nbsp;&nbsp;-&nbsp;</span>
<span class="material-icons">audiotrack</span>
<p class="pl-2">Audiobook.m4b</p>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;</span>
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Heart of Black Ice - Sister of Darkness</p>
<div class="hidden md:block flex-grow" />
<span class="hidden md:block text-white text-opacity-50 pl-4">&lt;-- Title&nbsp;</span>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;&nbsp;-&nbsp;</span>
<span class="material-icons">audiotrack</span>
<p class="pl-2">Audio File.m4a</p>
</div>
<div class="flex py-1 max-w-2xl">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Steven Levy</p>
<div class="hidden md:block flex-grow" />
<span class="hidden md:block text-white text-opacity-50 pl-4">&lt;-- Author</span>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;</span>
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Hackers - Heroes of the Computer Revolution</p>
<div class="hidden md:block flex-grow" />
<span class="hidden md:block text-white text-opacity-50 pl-4">&lt;-- Title&nbsp;</span>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;&nbsp;-&nbsp;</span>
<span class="material-icons">audiotrack</span>
<p class="pl-2">Audio File.m4a</p>
</div>
<div class="flex py-1 max-w-2xl">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">1945 - Animal Farm</p>
<div class="hidden md:block flex-grow" />
<span class="hidden md:block text-white text-opacity-50 pl-4">&lt;-- Title&nbsp;</span>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;</span>
<span class="material-icons">audiotrack</span>
<p class="pl-2">Audiobook.mp3</p>
</div>
<div class="flex py-1 max-w-2xl">
<span class="material-icons">audiotrack</span>
<p class="pl-2">Animal Farm.m4b</p>
<div class="hidden md:block flex-grow" />
<span class="hidden md:block text-white text-opacity-50 pl-4">&lt;-- Title<span class="text-warning">*</span></span>
</div>
</div>
<p class="my-4 text-sm md:text-base"><span class="text-warning">*</span> Audio files in the root of the folder will each be treated as audiobooks.</p>
</div>
</template>
<script>
export default {
data() {
return {}
},
computed: {},
methods: {},
mounted() {}
}
</script>

View file

@ -0,0 +1,67 @@
<template>
<div id="book-title-folder" class="py-10 md:py-20">
<h1 class="text-xl md:text-3xl mb-4 md:-ml-8">
<nuxt-link to="#book-title-folder"><span class="material-icons text-lg md:text-xl text-gray-400 hover:text-white cursor-pointer mr-2">tag</span></nuxt-link
>Title Folder Naming
</h1>
<p class="mb-4">In addition to the book title, the title folder can include the publish year, volume number, and the subtitle.</p>
<p class="mb-4">Here are a bunch of ways the same book could be named:</p>
<div class="p-4 border border-opacity-10 bg-primary bg-opacity-20 font-mono">
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Wizards First Rule</p>
</div>
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">1994 - Wizards First Rule</p>
</div>
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Wizards First Rule - A Really Good Subtitle</p>
</div>
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">1994 - Book 1 - Wizards First Rule</p>
</div>
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Vol 1 - 1994 - Wizards First Rule</p>
</div>
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">1994 - Wizards First Rule - Volume 1</p>
</div>
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Vol. 1 - 1994 - Wizards First Rule - A Really Good Subtitle</p>
</div>
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">(1994) - Wizards First Rule - A Really Good Subtitle</p>
</div>
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">1 - Wizards First Rule</p>
</div>
</div>
<ul class="list-outside md:list-inside px-6 md:px-0 list-disc my-4 text-sm md:text-base">
<li class="py-1"><strong class="underline">Subtitle: </strong>Parsing out subtitles into a separate field is optional and must be enabled in settings. Subtitle must be separated by " - ".</li>
<li class="py-1"><strong class="underline">Volume Number: </strong>The volume number can be the first number in the folder name separated by " - " (see last example) OR anywhere in the folder name if "Vol", "Book", or "Volume" is before the number. Case insensitive & decimals supported.</li>
<li class="py-1"><strong class="underline">Publish Year: </strong>The publish year must be the first part of the name OR directly after a volume number, and separated by " - " on both sides.</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {}
},
computed: {},
methods: {},
mounted() {}
}
</script>

View file

@ -0,0 +1,56 @@
<template>
<div id="podcast-structure" class="py-10 md:py-20">
<h1 class="text-xl md:text-3xl mb-4 md:-ml-8">
<nuxt-link to="#podcast-structure"><span class="material-icons text-lg md:text-xl text-gray-400 hover:text-white cursor-pointer mr-2">tag</span></nuxt-link
>Podcast Directory Structure
</h1>
<p class="mb-4 text-sm md:text-base">Here is an example supported directory structure</p>
<div class="p-4 border border-opacity-10 bg-primary bg-opacity-20 font-mono">
<div class="flex py-1 max-w-2xl">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Lex Fridman Podcast</p>
<div class="hidden md:block flex-grow" />
<span class="hidden md:block text-white text-opacity-50 pl-4">&lt;-- Title&nbsp;</span>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;</span>
<span class="material-icons">audiotrack</span>
<p class="pl-2">#219 Donald Knuth.mp3</p>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;</span>
<span class="material-icons">audiotrack</span>
<p class="pl-2">#252 Elon Musk.mp3</p>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;</span>
<span class="material-icons">crop_original</span>
<p class="pl-2">Cover.jpg</p>
</div>
<div class="flex py-1 max-w-2xl">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Self-Hosted</p>
<div class="hidden md:block flex-grow" />
<span class="hidden md:block text-white text-opacity-50 pl-4">&lt;-- Title&nbsp;</span>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;</span>
<span class="material-icons">audiotrack</span>
<p class="pl-2">#69 - Get Off My Lawn.mp3</p>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {}
},
computed: {},
methods: {},
mounted() {}
}
</script>

View file

@ -0,0 +1,19 @@
<template>
<nuxt-link :to="`/docs${hash}`" class="px-4 py-1.5 text-sm font-semibold block mr-6" :class="{ 'bg-white bg-opacity-10 rounded-r-full text-yellow-400': selected, 'text-gray-300 hover:text-white': !selected }">{{ text }}</nuxt-link>
</template>
<script>
export default {
props: {
hash: String,
text: String,
selected: Boolean
},
data() {
return {}
},
computed: {},
methods: {},
mounted() {}
}
</script>

View file

@ -26,7 +26,7 @@
<a :href="discordUrl" class="mx-2 hidden md:block"> <a :href="discordUrl" class="mx-2 hidden md:block">
<img src="/discord.svg" class="h-5 md:h-7 hover:scale-110 transform duration-100" /> <img src="/discord.svg" class="h-5 md:h-7 hover:scale-110 transform duration-100" />
</a> </a>
<a :href="dockerHubUrl" class="mx-2"> <a :href="dockerHubUrl" class="mx-2 hidden md:block">
<img src="/docker.svg" class="h-8 hover:scale-110 transform duration-100" /> <img src="/docker.svg" class="h-8 hover:scale-110 transform duration-100" />
</a> </a>
<a :href="githubUrl"> <a :href="githubUrl">

145
layouts/docs.vue Normal file
View file

@ -0,0 +1,145 @@
<template>
<div class="w-screen h-screen max-w-full max-h-screen text-white bg-gradient overflow-hidden">
<div id="sidebar" class="hidden md:block fixed top-0 left-0 h-full bg-primary border-r border-white border-opacity-25">
<div class="flex justify-center items-center py-4 mb-6">
<nuxt-link to="/" class="h-12 w-12 -ml-4">
<img src="/Logo48.png" class="h-full w-full" />
</nuxt-link>
<nuxt-link to="/" class="text-2xl pl-2 sm:pl-4 font-book hover:underline">audiobookshelf</nuxt-link>
</div>
<sidebar-nav-item v-for="item in introItems" :key="item.hash" :hash="item.hash" :text="item.text" :selected="currentHash === item.hash" />
<p class="px-4 py-1 text-xs font-bold text-white uppercase mt-6 mb-1">Books</p>
<sidebar-nav-item v-for="item in bookItems" :key="item.hash" :hash="item.hash" :text="item.text" :selected="currentHash === item.hash" />
<p class="px-4 py-1 text-xs font-bold text-white uppercase mt-6 mb-1">Podcasts</p>
<sidebar-nav-item v-for="item in podcastItems" :key="item.hash" :hash="item.hash" :text="item.text" :selected="currentHash === item.hash" />
</div>
<div id="docs-content" class="overflow-y-auto max-w-full overflow-x-hidden">
<Nuxt />
</div>
</div>
</template>
<script>
export default {
data() {
return {
lastScrollTop: 0,
introItems: [
{
hash: '#intro',
text: 'Introduction'
}
],
bookItems: [
{
hash: '#book-structure',
text: 'Directory Structure'
},
{
hash: '#book-author-folder',
text: 'Author Folder Naming'
},
{
hash: '#book-title-folder',
text: 'Title Folder Naming'
},
{
hash: '#book-audio-metadata',
text: 'Audio Metadata'
},
{
hash: '#book-additional-metadata',
text: 'Additional Metadata'
},
{
hash: '#book-tracks',
text: 'Audio Tracks'
}
],
podcastItems: [
{
hash: '#podcast-structure',
text: 'Directory Structure'
}
],
currentHash: null
}
},
computed: {},
watch: {
$route(newVal, oldVal) {
console.log('Route updated', newVal, oldVal)
},
'$route.hash'(newVal) {
console.log('Update hash', newVal)
if (newVal) {
this.scrollTo(newVal)
this.currentHash = newVal
}
}
},
methods: {
scrollTo(hashtag) {
location.href = hashtag
},
onScroll(evt) {
// const scrollingUp = evt.target.scrollTop - this.lastScrollTop < 0
// this.lastScrollTop = evt.target.scrollTop
const allItems = this.introItems.concat(this.bookItems).concat(this.podcastItems)
var closestItem = null
for (let i = 0; i < allItems.length; i++) {
const item = allItems[i]
var div = document.querySelector(item.hash)
var box = div.getBoundingClientRect()
if (box.top > 0 && box.top < 100) {
closestItem = item
break
}
}
if (closestItem && closestItem.hash !== this.currentHash) {
history.pushState({}, '', closestItem.hash)
this.currentHash = closestItem.hash
}
}
},
mounted() {
window['docs-content'].addEventListener('scroll', this.onScroll)
if (this.$route.hash) {
this.scrollTo(this.$route.hash)
this.currentHash = this.$route.hash
}
},
beforeDestroy() {
window['docs-content'].removeEventListener('scroll', this.onScroll)
}
}
</script>
<style>
:root {
--sidebar-width: 280px;
}
#sidebar {
width: var(--sidebar-width);
}
#docs-content {
margin-left: var(--sidebar-width);
height: 100vh;
}
@media (max-width: 767px) {
#docs-content {
margin-left: 0px;
height: 100vh;
}
}
</style>

View file

@ -49,7 +49,7 @@ export default {
], ],
link: [ link: [
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }, { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' },
{ rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Fira+Mono&family=Ubuntu+Mono&family=Open+Sans:wght@400;600&family=Gentium+Book+Basic&family=Material+Icons' } { rel: 'stylesheet', href: 'https://fonts.googleapis.com/css2?family=Ubuntu+Mono&family=Open+Sans:wght@400;600;700&family=Gentium+Book+Basic&family=Material+Icons' }
], ],
script: [ script: [
{ {

View file

@ -1,344 +1,64 @@
<template> <template>
<div class="w-full max-w-5xl mx-auto px-2 py-8"> <div class="w-full max-w-5xl mx-auto px-2 py-8">
<div class="flex -ml-8 mb-8"> <div class="flex items-center py-1">
<div> <nuxt-link to="/" class="h-8 w-8 md:hidden mx-1.5">
<span class="material-icons text-error text-2xl">priority_high</span> <img src="/favicon.ico" class="h-full w-full" />
</div> </nuxt-link>
<p class="pl-2 text-base md:text-lg">Server v2.0.0 and higher is not backwards compatible with older mobile app versions! Make sure you are using server v2.0.0 and up with mobile apps v0.9.41-beta and up.</p>
<a :href="discordUrl" class="mx-2 hidden md:block">
<img src="/discord.svg" class="h-5 md:h-7 hover:scale-110 transform duration-100" />
</a>
<a :href="dockerHubUrl" class="mx-2 hidden md:block">
<img src="/docker.svg" class="h-8 hover:scale-110 transform duration-100" />
</a>
<a :href="githubUrl" class="hidden md:block">
<img src="/github.svg" class="h-7 hover:scale-110 transform duration-100 mx-1 sm:mx-2" />
</a>
<a :href="playStoreUrl" class="hidden lg:block">
<img src="/GetGooglePlayStore.png" class="h-7 ml-2" />
</a>
<a :href="appStoreUrl" class="hidden lg:block">
<img src="/AppleAppStoreDark.svg" class="h-7 ml-2" />
</a>
<div class="flex-grow" />
<nuxt-link to="/install" class="text-base md:text-lg font-semibold text-gray-200 hover:text-white hover:underline mx-1.5 md:mx-4">Install</nuxt-link>
<nuxt-link to="/support" class="text-base md:text-lg font-semibold text-gray-200 hover:text-white hover:underline mx-1.5 md:mx-4">Support</nuxt-link>
<nuxt-link to="/showcase" class="text-base md:text-lg font-semibold text-gray-200 hover:text-white hover:underline mx-1.5 md:mx-4">Showcase</nuxt-link>
</div> </div>
<div class="flex -ml-8 mb-8"> <docs-introduction />
<div>
<span class="material-icons text-success text-2xl">priority_high</span>
</div>
<p class="pl-2 text-base md:text-lg">
Help needed writing documentation! This website is on <a href="https://github.com/advplyr/audiobookshelf-web" target="_blank" class="text-blue-500 underline">github</a>. Join the <a href="https://github.com/advplyr/audiobookshelf/discussions" target="_blank" class="text-blue-500 underline">discussion</a>,
<a href="https://github.com/advplyr/audiobookshelf/issues" target="_blank" class="text-blue-500 underline">report an issue</a> or contact me directly at <a href="mailto:advplyr@protonmail.com" class="text-blue-500 underline">advplyr@protonmail.com</a>.
</p>
</div>
<div class="flex -ml-8">
<div>
<span class="material-icons text-warning text-2xl">priority_high</span>
</div>
<p class="pl-2 text-base md:text-lg">
Audiobookshelf works best when you have an organized directory structure like shown below. This is because information is taken from your folder names. This includes the author name, series name, book title, publish year, volume number, and subtitle. However, you can enable scanner settings to prefer using your audio file ID3 tags or an OPF file over using folder names.
</p>
</div>
<div class="w-full bg-white bg-opacity-20 h-px my-8" /> <div class="w-full bg-white bg-opacity-20 h-px my-8" />
<h1 id="structure" class="text-3xl mb-4 -ml-8"> <docs-book-directory-structure />
<nuxt-link to="#structure"><span class="material-icons text-xl text-gray-400 hover:text-white cursor-pointer mr-2">tag</span></nuxt-link
>Directory Structure
</h1>
<p class="mb-4 text-sm md:text-base">Here is an example supported directory structure</p>
<div class="p-4 border border-opacity-10 bg-primary bg-opacity-20 font-mono">
<div class="flex py-1 max-w-2xl">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Terry Goodkind</p>
<div class="hidden md:block flex-grow" />
<span class="hidden md:block text-white text-opacity-50 pl-4">&lt;-- Author</span>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;</span>
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Sword of Truth</p>
<div class="hidden md:block flex-grow" />
<span class="hidden md:block text-white text-opacity-50 pl-4">&lt;-- Series</span>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;&nbsp;-&nbsp;</span>
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Vol 1 - 1994 - Wizards First Rule</p>
<div class="hidden md:block flex-grow" />
<span class="hidden md:block text-white text-opacity-50 pl-4">&lt;-- Title&nbsp;</span>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;&nbsp;-&nbsp;&nbsp;-&nbsp;</span>
<span class="material-icons">audiotrack</span>
<p class="pl-2">Audio Track 1.mp3</p>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;&nbsp;-&nbsp;&nbsp;-&nbsp;</span>
<span class="material-icons">audiotrack</span>
<p class="pl-2">Audio Track 2.mp3</p>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;&nbsp;-&nbsp;&nbsp;-&nbsp;</span>
<span class="material-icons">crop_original</span>
<p class="pl-2">Cover.jpg</p>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;&nbsp;-&nbsp;</span>
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Vol 2 - 1995 - Stone of Tears</p>
<div class="hidden md:block flex-grow" />
<span class="hidden md:block text-white text-opacity-50 pl-4">&lt;-- Title&nbsp;</span>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;&nbsp;-&nbsp;&nbsp;-&nbsp;</span>
<span class="material-icons">audiotrack</span>
<p class="pl-2">Audiobook.m4b</p>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;</span>
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Heart of Black Ice - Sister of Darkness</p>
<div class="hidden md:block flex-grow" />
<span class="hidden md:block text-white text-opacity-50 pl-4">&lt;-- Title&nbsp;</span>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;&nbsp;-&nbsp;</span>
<span class="material-icons">audiotrack</span>
<p class="pl-2">Audio File.m4a</p>
</div>
<div class="flex py-1 max-w-2xl">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Steven Levy</p>
<div class="hidden md:block flex-grow" />
<span class="hidden md:block text-white text-opacity-50 pl-4">&lt;-- Author</span>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;</span>
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Hackers - Heroes of the Computer Revolution</p>
<div class="hidden md:block flex-grow" />
<span class="hidden md:block text-white text-opacity-50 pl-4">&lt;-- Title&nbsp;</span>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;&nbsp;-&nbsp;</span>
<span class="material-icons">audiotrack</span>
<p class="pl-2">Audio File.m4a</p>
</div>
<div class="flex py-1 max-w-2xl">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">1945 - Animal Farm</p>
<div class="hidden md:block flex-grow" />
<span class="hidden md:block text-white text-opacity-50 pl-4">&lt;-- Title&nbsp;</span>
</div>
<div class="flex py-1 max-w-2xl">
<span class="text-white text-opacity-25">&nbsp;-&nbsp;</span>
<span class="material-icons">audiotrack</span>
<p class="pl-2">Audiobook.mp3</p>
</div>
</div>
<p class="my-4 text-sm md:text-base">Files must always be in a directory with the book title. <span class="text-error">Files in the root directory are ignored.</span><br />The title directory can be in the root directory, an author directory, or a series directory.</p>
<div class="w-full bg-white bg-opacity-20 h-px my-8" /> <div class="w-full bg-white bg-opacity-20 h-px my-8" />
<h1 id="author-naming" class="text-3xl mb-4 -ml-8"> <docs-book-author-folder-naming />
<nuxt-link to="#author-naming"><span class="material-icons text-lg text-gray-400 hover:text-white cursor-pointer mr-2">tag</span></nuxt-link
>Author Folder Naming Convention
</h1>
<p class="mb-4">Supports "Last, First" author naming as well as multiple authors separated by "," or "&".<br /><br />Valid author folder names:</p>
<div class="p-4 border border-opacity-10 bg-primary bg-opacity-20 font-mono">
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Ichiro Kishimi</p>
</div>
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Kishimi, Ichiro</p>
</div>
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Ichiro Kishimi, Fumitake Koga</p>
</div>
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Kishimi, Ichiro, Koga, Fumitake</p>
</div>
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Ichiro Kishimi & Fumitake Koga</p>
</div>
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Kishimi, Ichiro & Koga, Fumitake</p>
</div>
</div>
<div class="w-full bg-white bg-opacity-20 h-px my-8" /> <div class="w-full bg-white bg-opacity-20 h-px my-8" />
<h1 id="naming" class="text-3xl mb-4 -ml-8"> <docs-book-title-folder-naming />
<nuxt-link to="#naming"><span class="material-icons text-xl text-gray-400 hover:text-white cursor-pointer mr-2">tag</span></nuxt-link
>Title Folder Naming Convention
</h1>
<p class="mb-4">In addition to the book title, the title folder can include the publish year, volume number, and the subtitle.</p>
<p class="mb-4">Here are a bunch of ways the same book could be named:</p>
<div class="p-4 border border-opacity-10 bg-primary bg-opacity-20 font-mono">
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Wizards First Rule</p>
</div>
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">1994 - Wizards First Rule</p>
</div>
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Wizards First Rule - A Really Good Subtitle</p>
</div>
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">1994 - Book 1 - Wizards First Rule</p>
</div>
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Vol 1 - 1994 - Wizards First Rule</p>
</div>
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">1994 - Wizards First Rule - Volume 1</p>
</div>
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">Vol. 1 - 1994 - Wizards First Rule - A Really Good Subtitle</p>
</div>
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">(1994) - Wizards First Rule - A Really Good Subtitle</p>
</div>
<div class="flex py-1">
<img src="/folder.svg" class="h-6" />
<p class="pl-2">1 - Wizards First Rule</p>
</div>
</div>
<ul class="list-outside md:list-inside px-6 md:px-0 list-disc my-4 text-sm md:text-base">
<li class="py-1"><strong class="underline">Subtitle: </strong>Parsing out subtitles into a separate field is optional and must be enabled in settings. Subtitle must be separated by " - ".</li>
<li class="py-1"><strong class="underline">Volume Number: </strong>The volume number can be the first number in the folder name separated by " - " (see last example) OR anywhere in the folder name if "Vol", "Book", or "Volume" is before the number. Case insensitive & decimals supported.</li>
<li class="py-1"><strong class="underline">Publish Year: </strong>The publish year must be the first part of the name OR directly after a volume number, and separated by " - " on both sides.</li>
</ul>
<div class="w-full bg-white bg-opacity-20 h-px my-8" /> <div class="w-full bg-white bg-opacity-20 h-px my-8" />
<h1 id="metadata" class="text-3xl mb-4 -ml-8"> <docs-book-audio-metadata />
<nuxt-link to="#metadata"><span class="material-icons text-xl text-gray-400 hover:text-white cursor-pointer mr-2">tag</span></nuxt-link
>Audio File Metadata
</h1>
<p class="mb-4">Audiobookshelf uses the ID3 metadata tags in audio files to populate data.</p>
<div class="flex -ml-8 mb-4">
<div>
<span class="material-icons text-warning text-2xl">priority_high</span>
</div>
<p class="pl-2 text-base">Data parsed from the folder structure and filenames takes priority over ID3 tags unless you have enabled the scanner setting "Prefer Audio Metadata".</p>
</div>
<p class="mb-4">Metadata on audio files will be mapped as follows (second tag after "/" is a fallback):</p>
<table>
<tr class="bg-white bg-opacity-10 text-sm text-left font-semibold">
<th>ID3 Tag <span class="text-gray-300 font-normal text-xs">&nbsp;(case-insensitive)</span></th>
<th>Audiobookshelf Data</th>
</tr>
<tr>
<td>artist / album-artist</td>
<td>Author</td>
</tr>
<tr>
<td>album / title</td>
<td>Title</td>
</tr>
<tr>
<td>subtitle</td>
<td>Subtitle</td>
</tr>
<tr>
<td>publisher</td>
<td>Publisher</td>
</tr>
<tr>
<td>year</td>
<td>Publish Year</td>
</tr>
<tr>
<td>composer</td>
<td>Narrator</td>
</tr>
<tr>
<td>description</td>
<td>Description</td>
</tr>
<tr>
<td>genre</td>
<td>Genres <span class="text-sm text-warning">*</span></td>
</tr>
<tr>
<td>series</td>
<td>Series</td>
</tr>
<tr>
<td>series-part</td>
<td>Volume Number</td>
</tr>
<tr>
<td>language / lang</td>
<td>Language</td>
</tr>
<tr>
<td>isbn</td>
<td>ISBN</td>
</tr>
<tr>
<td>asin</td>
<td>ASIN</td>
</tr>
</table>
<p class="text-sm pt-2"><span class="text-sm text-warning">*</span> Genre meta tag can include multiple genres separated by "/", "//", or ";". e.g. "Science Fiction/Fiction/Fantasy"</p>
<p class="my-4">Embedded cover art will be extracted and used only if there are no images in the book folder.</p>
<p class="my-4">If you have a file named <span class="bg-white bg-opacity-10 text-gray-100 rounded-md p-1 font-mono">desc.txt</span> in the audiobook folder it will be used as the description.</p>
<p class="my-4">If you have a file named <span class="bg-white bg-opacity-10 text-gray-100 rounded-md p-1 font-mono">reader.txt</span> in the audiobook folder it will be used as the narrator.</p>
<p class="mt-4">If you have an <a href="https://docs.fileformat.com/ebook/opf/" target="_blank" class="text-blue-500 hover:text-blue-300 underline">OPF file</a> with extension <span class="bg-white bg-opacity-10 text-gray-100 rounded-md p-1 font-mono">.opf</span> in the audiobook folder it will be parsed.<br />Details extracted from OPF:</p>
<div v-for="(key, index) in opfKeys" :key="key" class="inline-block">
<span class="bg-white bg-opacity-10 text-gray-100 rounded-md px-1 py-0.5 font-mono">{{ key }}</span
>{{ index < opfKeys.length - 1 ? ', ' : '' }}
</div>
<div class="w-full bg-white bg-opacity-20 h-px my-8" /> <div class="w-full bg-white bg-opacity-20 h-px my-8" />
<h1 id="tracks" class="text-3xl mb-4 -ml-8"> <docs-book-additional-metadata-files />
<nuxt-link to="#tracks"><span class="material-icons text-xl text-gray-400 hover:text-white cursor-pointer mr-2">tag</span></nuxt-link
>Audio Tracks
</h1>
An audiobook contains tracks. Tracks are audio files assigned a track number. <br />The track number is parsed from the audio filename and from the ID3 tags of the audio file.<br />Audiobooks that are made up of multiple discs or cd's will be ordered first by disc number then by track number.
<table class="my-4">
<tr class="bg-white bg-opacity-10 text-sm text-left font-semibold">
<th>Key</th>
<th>ID3 Tags <span class="text-gray-300 font-normal text-xs">&nbsp;(case-insensitive)</span></th>
<th>Audio Filename</th>
</tr>
<tr>
<td>TrackNumber</td>
<td>track, trck, trk</td>
<td>First number after removing title, publish year, series, author, disc number</td>
</tr>
<tr>
<td>DiscNumber</td>
<td>discnumber, disc, disk, tpos</td>
<td>Number following "Disc" or "CD" (example: "Atlas Shrugged CD 01 - 1.mp3")</td>
</tr>
</table>
<p class="mb-2">The scanner will choose the more accurate track/disc number between the filename and ID3 tag numbers.</p>
<p>Tracks can be manually ordered and enabled/disabled by pressing the "Manage Tracks" button on the audiobook page.</p>
<div class="w-full bg-white bg-opacity-20 h-px my-8" /> <div class="w-full bg-white bg-opacity-20 h-px my-8" />
<h1 id="abmetadata" class="text-3xl mb-4 -ml-8"> <docs-book-audio-tracks />
<div class="w-full bg-white bg-opacity-20 h-px my-8" />
<docs-podcast-directory-structure />
<!-- <h1 id="abmetadata" class="text-3xl mb-4 -ml-8">
<nuxt-link to="#abmetadata"><span class="material-icons text-xl text-gray-400 hover:text-white cursor-pointer mr-2">tag</span></nuxt-link <nuxt-link to="#abmetadata"><span class="material-icons text-xl text-gray-400 hover:text-white cursor-pointer mr-2">tag</span></nuxt-link
>abmetadata file >abmetadata file
</h1> </h1>
@ -348,29 +68,29 @@
<span class="material-icons text-success text-2xl">priority_high</span> <span class="material-icons text-success text-2xl">priority_high</span>
</div> </div>
<p class="pl-2 text-base md:text-lg">This is the start of setting up a better standard around persisting audiobook metadata and is likely to change, so if you have suggestions around audiobook metadata please join the discord or start a github discussion. The abmetadata file format is based on ffmetadata.</p> <p class="pl-2 text-base md:text-lg">This is the start of setting up a better standard around persisting audiobook metadata and is likely to change, so if you have suggestions around audiobook metadata please join the discord or start a github discussion. The abmetadata file format is based on ffmetadata.</p>
<!-- <p class="pl-2 text-base md:text-lg">
Help needed writing documentation! This website is on <a href="https://github.com/advplyr/audiobookshelf-web" target="_blank" class="text-blue-500 underline">github</a>. Join the <a href="https://github.com/advplyr/audiobookshelf/discussions" target="_blank" class="text-blue-500 underline">discussion</a>,
<a href="https://github.com/advplyr/audiobookshelf/issues" target="_blank" class="text-blue-500 underline">report an issue</a> or contact me directly at <a href="mailto:advplyr@protonmail.com" class="text-blue-500 underline">advplyr@protonmail.com</a>.
</p> -->
</div> </div>
<p class="mb-4 text-sm md:text-base"> <p class="mb-4 text-sm md:text-base">
As of v1.7.1 audiobookshelf creates a file named <span class="bg-white bg-opacity-10 text-gray-100 rounded-md p-1 font-mono">metadata.abs</span> for each library item. By default, the file will be saved in <span class="bg-white bg-opacity-10 text-gray-100 rounded-md p-1 font-mono">/metadata/items/</span> folders, but can be stored in the same folder as your book/podcast by enabling the server setting. As of v1.7.1 audiobookshelf creates a file named <span class="bg-white bg-opacity-10 text-gray-100 rounded-md p-1 font-mono">metadata.abs</span> for each library item. By default, the file will be saved in <span class="bg-white bg-opacity-10 text-gray-100 rounded-md p-1 font-mono">/metadata/items/</span> folders, but can be stored in the same folder as your book/podcast by enabling the
server setting.
</p> </p>
<p class="mb-4 text-sm md:text-base">If this file is in your library item folders it will serve as the source of truth for your metadata details and overwrite them. If you have enabled the server settings to prefer OPF or prefer audio ID3 metadata, then those will take precedence during scans.</p> <p class="mb-4 text-sm md:text-base">If this file is in your library item folders it will serve as the source of truth for your metadata details and overwrite them. If you have enabled the server settings to prefer OPF or prefer audio ID3 metadata, then those will take precedence during scans.</p> -->
<!-- <p class="mb-4 text-sm md:text-base">Here is a demo of <span class="bg-white bg-opacity-10 text-gray-100 rounded-md p-1 font-mono">metadata.abs</span> getting updated after saving details from the web app, then showing the metadata file get updated manually within the book folder and those changes getting pulled in after pressing "Re-Scan".</p> --> <!-- <div class="w-full bg-white bg-opacity-20 h-px my-8" /> -->
<div class="w-full bg-white bg-opacity-20 h-px my-8" />
</div> </div>
</template> </template>
<script> <script>
export default { export default {
layout: 'docs',
data() { data() {
return { return {
opfKeys: ['title', 'author', 'narrator', 'publishYear', 'publisher', 'isbn', 'description', 'genres', 'language', 'series', 'volumeNumber'] appStoreUrl: 'https://testflight.apple.com/join/wiic7QIW',
dockerHubUrl: 'https://hub.docker.com/r/advplyr/audiobookshelf',
playStoreUrl: 'https://play.google.com/store/apps/details?id=com.audiobookshelf.app',
githubUrl: 'https://github.com/advplyr/audiobookshelf',
discordUrl: 'https://discord.gg/pJsjuNCKRq'
} }
}, },
computed: {}, computed: {},