commit 69aa0718b434d55de1ec67a225745f2ae180a0c6 Author: root Date: Wed Apr 3 15:47:12 2019 +0200 first commit diff --git a/Dockerfile b/Dockerfile new file mode 100755 index 0000000..f036cfd --- /dev/null +++ b/Dockerfile @@ -0,0 +1,9 @@ +FROM nginx:alpine +LABEL maintainer="Jeroen Pardon" + +RUN apk add nano + +RUN rm -rf /usr/share/nginx/html +COPY . /usr/share/nginx/html + +EXPOSE 80 \ No newline at end of file diff --git a/apps.json b/apps.json new file mode 100755 index 0000000..9186d2d --- /dev/null +++ b/apps.json @@ -0,0 +1,24 @@ +{ + "apps" : [ + {"name":"Bazarr","url":"subs.example.com","icon":"message-video"}, + {"name":"CloudCMD","url":"files.example.com","icon":"folder-multiple-outline"}, + {"name":"Cockpit","url":"cp.example.com","icon":"airplane"}, + {"name":"Feedbin","url":"rss.example.com","icon":"rss"}, + {"name":"Filestash","url":"cloud.example.com","icon":"package"}, + {"name":"Jackett","url":"jackett.example.com","icon":"tshirt-crew-outline"}, + {"name":"Lidarr","url":"music.example.com","icon":"music"}, + {"name":"Minio","url":"minio.example.com","icon":"server"}, + {"name":"Mylar","url":"comics.example.com","icon":"book-open-variant"}, + {"name":"Nextcloud","url":"cloud.example.com","icon":"weather-cloudy"}, + {"name":"Ombi","url":"request.example.com","icon":"file-find-outline"}, + {"name":"Pi-hole","url":"pihole.example.com","icon":"do-not-disturb"}, + {"name":"Plex","url":"play.example.com","icon":"plex"}, + {"name":"Portainer","url":"port1.example.com","icon":"docker"}, + {"name":"Radarr","url":"movies.example.com","icon":"filmstrip"}, + {"name":"Sonarr","url":"tv.example.com","icon":"television-box"}, + {"name":"Stackedit","url":"md.example.com","icon":"markdown"}, + {"name":"Transmission","url":"dl.example.com","icon":"progress-download"}, + {"name":"Ubooquity","url":"opds.example.com","icon":"library-shelves"}, + {"name":"Youtube-DL","url":"yt.example.com","icon":"youtube"} + ] +} \ No newline at end of file diff --git a/assets/css/styles.css b/assets/css/styles.css new file mode 100755 index 0000000..5ec96f6 --- /dev/null +++ b/assets/css/styles.css @@ -0,0 +1,548 @@ +html{ + box-sizing: border-box; + moz-box-sizing: border-box; + webkit-box-sizing: border-box; + webkit-text-size-adjust: none; +} + +html, +body{ + background-color: var(--color-background); + color: var(--color-text-pri); + font-family: -apple-system, BlinkMacSystemFont, Helvetica Neue, Roboto, sans-serif; + font-size: 14px; + font-weight: 400; + height: auto; + letter-spacing: -.012em; + margin: 0; + padding: 0; + webkit-font-smoothing: antialiased; + width: 100vw; +} + +*, +*:before, +*:after{ + box-sizing: inherit; + moz-box-sizing: inherit; + webkit-box-sizing: inherit; +} + +:root{ + module-spacing: 3vh; +} + + +/* TEXT STYLES */ + +h1, h2{ + font-weight: 300; + margin: 0; + padding: 0; + text-align: left; +} + +h2, h3, h4{ + text-transform: uppercase; +} + +h1{ + font-size: 4em; + font-weight: 700; + margin-bottom: 0.5em; +} + +h2{ + font-size: 16px; + height: 30px; + +} + +h3{ + font-size: 20px; + font-weight: 900; + height: 10px; +} + +h4{ + font-size: 1.1em; + font-weight: 400; + height: 10px; +} + +a{ + color: var(--color-text-pri); + text-decoration: none; +} + +a:hover{ + text-decoration: underline; + webkit-text-decoration-color: var(--color-text-acc); + webkit-text-decoration-skip: true; +} + +.icon{ + font-size: 2.5em; +} + + +/* FORMS */ + +input{ + background-color: transparent; + border: 0; + border-bottom: thin solid var(--color-text-acc); + color: var(--color-text-pri); + font-size: 0.8em; + height: 3.5em; + transition: all 0.4s ease; + width: 100%; +} + +input:focus{ + color-border: var(--color-text-pri); + outline: none; +} + +input:focus{ + opacity: 1; +} + + +/* TABLES */ + +table{ + border: thin solid #e4e4e4; + border-collapse: collapse; + border-spacing: 0; + font-size: 1em; + text-align: left; + width: 100%; +} + +table td:nth-of-type(2){ + padding-right: 5em; +} + +table td{ + border: thin solid #e4e4e4; + color: #333333; + font-size: 1em; + overflow: hidden; + padding: 10px 5px; + word-break: normal; +} + +table th{ + border: thin solid #e4e4e4; + color: #333333; + font-weight: bold; + padding: 10px 5px; +} + +table a{ + color: #333333; +} + + +/* ANIMATION */ + +.fade{ + opacity: 0; +} + +@keyframes fadeseq{ + 100% { + opacity: 1; + } +} + +.fade{ + opacity: 0; +} + +.fade{ + animation: fadeseq .3s forwards; +} + +.fade:nth-child(2){ + animation-delay: .4s; +} + + +/* LAYOUT */ + +#container{ + align-items: stretch; + display: grid; + grid-column-gap: 20px; + grid-row-gap: 3vh; + grid-template-columns: 1fr; + grid-template-rows: 8vh auto; + justify-items: stretch; + margin-left: auto; + margin-right: auto; + margin-top: 5vh; + width: 60%; +} + + + +/* SECTIONS */ + +#header{ + border-bottom: 0px solid var(--color-text-acc); + z-index: 1; +} + +#apps_loop{ + border-bottom: 0px solid var(--color-text-acc); + display: grid; + grid-column-gap: 0px; + grid-row-gap: 0px; + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-template-rows: 64px; + padding-bottom: var(--module-spacing); +} + +.apps_icon{ + height: 64px; + margin-right: 1em; + padding-top: 15px; +} + +.apps_icon span{ + font-size: 2.5em; + line-height: 3rem; +} + +.apps_item{ + display: flex; + flex-direction: row; + flex-wrap: wrap; + height: 64px; + margin: 0; +} + +.apps_text{ + display: flex; + flex-direction: column; + justify-content: center; +} + +.apps_text a{ + font-size: 1em; + font-weight: 500; + text-transform: uppercase; +} + +.apps_text span{ + color: var(--color-text-acc); + font-size: 0.8em; + text-transform: uppercase; +} + + +#links_loop{ + display: grid; + flex-wrap: nowrap; + grid-column-gap: 20px; + grid-row-gap: 0px; + grid-template-columns: 1fr 1fr 1fr 1fr; + grid-template-rows: auto; +} + +#links_item{ + line-height: 1.5rem; + margin-bottom: 2em; + webkit-font-smoothing: antialiased; +} + +#links_item h4{ + color: var(--color-text-acc); +} + +#links_item a{ + display: block; + line-height: 2; +} + + + + + + + + + + + + + + + +/* MODAL */ + + +#modal{ + bottom: 0; + left: 0; + opacity: 0; + pointer-events: none; + position: fixed; + right: 0; + top: 0; + transition: all 0.3s; + z-index: 20; +} + +#modal:target{ + opacity: 1; + pointer-events: auto; +} + +#modal>div{ + background-color: #ffffff; + box-shadow: 0 14px 28px rgba(0, 0, 0, 0.30), 0 15px 12px rgba(0, 0, 0, 0.25); + margin-left: auto; + margin-right: auto; + padding: 2em; + margin-top: 25vh; + width: 50%; + display: flex; + flex-direction: column; +} + +#modal h1{ + color: #333333; + font-size: 2em; +} + +#modal h2{ + margin-top:1.5em; +} + +#modal-header{ + display:flex; + justify-content: space-between; +} + +#modal-footer{ + display:flex; + font-size:2em; + justify-content: flex-start; +} + +#modal-footer a{ + margin-right:0.25em; +} + +.modal-close{ + color: #000000; + font-size: 1.5em; + text-align: center; + text-decoration: none; +} + +.modal-close:hover{ + color: #000; +} + +#modal_init a{ + bottom: 1vh; + color: var(--color-text-acc); + left: 1vw; + position: fixed; +} + +#modal_init a:hover{ + color: var(--color-text-pri); +} + +#modal-theme{ + border-bottom: 0px solid var(--color-text-acc); + display: flex; + flex-wrap: wrap; + margin-bottom: 2em; +} + +#providers{ + margin-bottom: 2em; +} + + +/* THEMING */ + +.theme-button{ + font-size: 0.8em; + margin: 2px; + width:128px; + line-height: 3em; + text-align: center; + text-transform: uppercase; +} + +.theme-blackboard{ + background-color: #000000; + border: 4px solid #5c5c5c; + color: #FFFDEA; +} + +.theme-gazette{ + background-color: #F2F7FF; + border: 4px solid #5c5c5c; + color: #000000; +} + +.theme-espresso{ + background-color: #21211F; + border: 4px solid #4E4E4E; + color: #D1B59A; +} + +.theme-cab{ + background-color: #FEED01; + border: 4px solid #424242; + color: #1F1F1F; +} + +.theme-cloud{ + background-color: #f1f2f0; + border: 4px solid #35342f; + color: #37bbe4; +} + +.theme-lime{ + background-color: #263238; + border: 4px solid #AABBC3; + color: #aeea00; +} + +.theme-passion{ + background-color: #f5f5f5; + border: 4px solid #8e24aa; + color: #12005e; +} + +.theme-blues{ + background-color: #2B2C56; + border: 4px solid #6677EB; + color: #EFF1FC; +} + +.theme-chalk{ + background-color: #263238; + border: 4px solid #FF869A; + color: #AABBC3; +} + +.theme-tron{ + background-color: #242B33; + border: 4px solid #6EE2FF; + color: #EFFBFF; +} + +.theme-paper{ + background-color: #F8F6F1; + border: 4px solid #F5E1A4; + color: #4C432E; +} + + +/* MEDIA QUERIES */ + +@media screen and (max-width: 1260px) +{ + #container + { + align-items: stretch; + display: grid; + grid-column-gap: 10px; + grid-row-gap: 0px; + grid-template-columns: 1fr; + grid-template-rows: 80px auto; + justify-items: stretch; + margin-bottom: 1vh; + margin-left: auto; + margin-right: auto; + width: 90%; + } + + #apps_loop{ + grid-template-columns: 1fr 1fr 1fr; + width: 100vw; + } + + #links_loop { + grid-template-columns: 1fr 1fr 1fr; + } + + #modal>div{ + margin-left: auto; + margin-right: auto; + margin-top: 25vh; + width: 90%; + } +} + +@media screen and (max-width: 667px) +{ + html{ + font-size: calc(16px + 6 * ((100vw - 320px) / 680)); + } + + #container{ + align-items: stretch; + display: grid; + grid-column-gap: 20px; + grid-row-gap: 0px; + grid-template-columns: 1fr; + grid-template-rows: 80px auto; + justify-items: stretch; + margin-bottom: 1vh; + width: 90%; + } + + h1{ + font-size: 4em; + height: auto; + margin-bottom: 0em; + } + + h2{ + font-size: 1em; + height: auto; + margin-bottom: 0em; + } + + h3{ + font-size: 1em; + } + + #apps_loop{ + grid-column-gap: 0px; + grid-row-gap: 0px; + grid-template-columns: 1fr 1fr; + width: 100vw; + } + + .apps_icon{ + height: 64px; + margin-right: 0.8em; + padding-top: 14px; + } + + .apps_icon span{ + font-size: 2em; + line-height: 2.5rem; + } + + #links_loop{ + display: grid; + flex-wrap: nowrap; + grid-column-gap: 20px; + grid-row-gap: 0px; + grid-template-columns: 1fr 1fr; + grid-template-rows: auto; + } +} \ No newline at end of file diff --git a/assets/js/data.js b/assets/js/data.js new file mode 100755 index 0000000..e89b2de --- /dev/null +++ b/assets/js/data.js @@ -0,0 +1,35 @@ +var data_links = "links.json"; + +$(document).ready(function(){ + $.getJSON(data_links, + function (data) { + var mysource = $('#links-template').html(); + var mytemplate = Handlebars.compile(mysource); + var myresult = mytemplate(data) + $('#links').html(myresult); + }); +}); + +var data_apps = "apps.json"; + +$(document).ready(function(){ + $.getJSON(data_apps, + function (data) { + var mysource = $('#apps-template').html(); + var mytemplate = Handlebars.compile(mysource); + var myresult = mytemplate(data) + $('#apps').html(myresult); + }); +}); + +var data_providers = "providers.json"; + +$(document).ready(function(){ + $.getJSON(data_providers, + function (data) { + var mysource = $('#providers-template').html(); + var mytemplate = Handlebars.compile(mysource); + var myresult = mytemplate(data) + $('#providers').html(myresult); + }); +}); \ No newline at end of file diff --git a/assets/js/script.js b/assets/js/script.js new file mode 100755 index 0000000..516498f --- /dev/null +++ b/assets/js/script.js @@ -0,0 +1,37 @@ +function date() { + let currentDate = new Date(); + let dateOptions = { + weekday: "long", + year: "numeric", + month: "long", + day: "numeric" + }; + let date = currentDate.toLocaleDateString("en-GB", dateOptions); + document.getElementById("header_date").innerHTML = date; +} + +function greet() { + let currentTime = new Date(); + let greet = Math.floor(currentTime.getHours() / 6); + switch (greet) { + case 0: + document.getElementById("header_greet").innerHTML = "Good night!"; + break; + case 1: + document.getElementById("header_greet").innerHTML = "Good morning!"; + break; + case 2: + document.getElementById("header_greet").innerHTML = "Good afternoon!"; + break; + case 3: + document.getElementById("header_greet").innerHTML = "Good evening!"; + break; + } +} + +function loadFunctions() { + date(); + greet(); +} + + diff --git a/assets/js/search.js b/assets/js/search.js new file mode 100755 index 0000000..14bc979 --- /dev/null +++ b/assets/js/search.js @@ -0,0 +1,122 @@ +var sindex = 0; +var cycle = false; + +function start() { + var query = getParameterByName('q'); + if (query) search(query.replaceAll("+", "%2B")); + + document.getElementById('keywords').focus(); + + window.setInterval(function () { + updatetime(); + }, 200); +} + +function handleKeyPress(e) { + var key = e.keyCode || e.which; + var text = document.getElementById("keywords").value.replaceAll("+", "%2B"); + var option = text.substr(1, text.indexOf(' ') - 1) || text.substr(1); + var subtext = text.substr(2 + option.length); + if (key == 13) { // Search functions + search(text); + } + if (key == 9) { // Tab Completion Functions + e.preventDefault(); + e.stopPropagation(); + if (text[0] === ';') { + switch (option) { + case 't': + var streamers = ['admiralbahroo', 'moonmoon_ow', 'witwix']; + if (!subtext || cycle) { + cycle = true; + if (sindex > streamers.length - 1) sindex = 0; + document.getElementById("keywords").value = ';t ' + streamers[sindex++]; + return; + } + for (var streamer of streamers) { + if (subtext === streamer.substr(0, subtext.length)) { + document.getElementById("keywords").value = ';t ' + streamer; + return; + } + } + break; + } + } + } + if(key == 32){ //Space to go to search + document.getElementById("keywords").focus(); + } + sindex = 0; + cycle = false; +} + +function search(text) { + var option = text.substr(1, text.indexOf(' ') - 1) || text.substr(1); + var subtext = text.substr(2 + option.length); + if (text[0] === '/') { + if (text.indexOf(' ') > -1) { + switch (option) { + case "am": + window.location = "https://www.allmusic.com/search/all/" + subtext; + break; + case "d": + window.location = "https://duckduckgo.com/?q=" + subtext; + break; + case "di": + window.location = "https://www.discogs.com/search/?q=" + subtext; + break; + case "i": + window.location = "https://www.imdb.com/find?q=" + subtext; + break; + case "m": + window.location = "https://www.themoviedb.org/search?query=" + subtext; + break; + case "r": + window.location = "https://www.reddit.com/search?q=" + subtext; + break; + case "q": + window.location = "https://www.qwant.com/?q=" + subtext; + break; + case "so": + window.location = "https://soundcloud.com/search?q=" + subtext; + break; + case "s": + window.location = "https://open.spotify.com/search/results/" + subtext; + break; + case "t": + window.location = "https://trakt.tv/search?query=" + subtext; + break; + case "tv": + window.location = "https://www.thetvdb.com/search?q=" + subtext; + break; + case "y": + window.location = "https://www.youtube.com/results?search_query=" + subtext; + break; + } + } else { + var option = text.substr(1); + switch (option) { + case "d": + window.location = "https://www.dukduckgo.com"; + break; + case "y": + window.location = "https://www.youtube.com"; + break; + case "r": + window.location = "https://reddit.com"; + break; + case "s": + window.location = "https://open.spotify.com"; + break; + } + } + } else { + window.location = "https://www.google.com/search?q=" + text; + } +} + + +String.prototype.replaceAll = function(search, replacement) { + var target = this; + return target.split(search).join(replacement); +}; \ No newline at end of file diff --git a/assets/js/themer.js b/assets/js/themer.js new file mode 100755 index 0000000..9c19380 --- /dev/null +++ b/assets/js/themer.js @@ -0,0 +1,139 @@ +const setValue = (property, value) => { + if (value) { + document.documentElement.style.setProperty(`--${property}`, value); + + const input = document.querySelector(`#${property}`); + if (input) { + value = value.replace('px', ''); + input.value = value; + } + } +}; + +const setValueFromLocalStorage = property => { + let value = localStorage.getItem(property); + setValue(property, value); +}; + +const setTheme = options => { + for (let option of Object.keys(options)) { + const property = option; + const value = options[option]; + + setValue(property, value); + localStorage.setItem(property, value); + } +} + +document.addEventListener('DOMContentLoaded', () => { + setValueFromLocalStorage('color-background'); + setValueFromLocalStorage('color-text-pri'); + setValueFromLocalStorage('color-text-acc'); +}); + +const dataThemeButtons = document.querySelectorAll('[data-theme]'); + +for (let i = 0; i < dataThemeButtons.length; i++) { + dataThemeButtons[i].addEventListener('click', () => { + const theme = dataThemeButtons[i].dataset.theme; + + switch (theme) { + case 'blackboard': + setTheme({ + 'color-background': '#1a1a1a', + 'color-text-pri': '#FFFDEA', + 'color-text-acc': '#5c5c5c' + }); + return; + + case 'gazette': + setTheme({ + 'color-background': '#F2F7FF', + 'color-text-pri': '#000000', + 'color-text-acc': '#5c5c5c' + }); + return; + + case 'espresso': + setTheme({ + 'color-background': '#21211F', + 'color-text-pri': '#D1B59A', + 'color-text-acc': '#4E4E4E' + }); + return; + + case 'cab': + setTheme({ + 'color-background': '#F6D305', + 'color-text-pri': '#1F1F1F', + 'color-text-acc': '#424242' + }); + return; + + case 'cloud': + setTheme({ + 'color-background': '#f1f2f0', + 'color-text-pri': '#35342f', + 'color-text-acc': '#37bbe4' + }); + return; + + case 'lime': + setTheme({ + 'color-background': '#263238', + 'color-text-pri': '#AABBC3', + 'color-text-acc': '#aeea00' + }); + return; + + case 'white': + setTheme({ + 'color-background': '#ffffff', + 'color-text-pri': '#222222', + 'color-text-acc': '#dddddd' + }); + return; + + case 'tron': + setTheme({ + 'color-background': '#242B33', + 'color-text-pri': '#EFFBFF', + 'color-text-acc': '#6EE2FF' + }); + return; + + case 'blues': + setTheme({ + 'color-background': '#2B2C56', + 'color-text-pri': '#EFF1FC', + 'color-text-acc': '#6677EB' + }); + return; + + case 'passion': + setTheme({ + 'color-background': '#f5f5f5', + 'color-text-pri': '#12005e', + 'color-text-acc': '#8e24aa' + }); + return; + + case 'chalk': + setTheme({ + 'color-background': '#263238', + 'color-text-pri': '#AABBC3', + 'color-text-acc': '#FF869A' + }); + return; + + case 'paper': + setTheme({ + 'color-background': '#F8F6F1', + 'color-text-pri': '#4C432E', + 'color-text-acc': '#AA9A73' + }); + return; + + } + }) +} \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100755 index 0000000..01ee37b --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,24 @@ +version: "3.5" +services: + + sui: + container_name: sui + restart: always + build: + context: ./ + environment: + - VIRTUAL_HOST=test.laserr.net + networks: + - nginx-proxy + - public + ports: + - 4000:80 + volumes: + - ./:/usr/share/nginx/html + +networks: + nginx-proxy: + external: true + public: + external: + name: public diff --git a/index.html b/index.html new file mode 100755 index 0000000..bfb8568 --- /dev/null +++ b/index.html @@ -0,0 +1,127 @@ + + + + SUI + + + + + + + + + + + + + + +
+ + + + + +
+ +
+ + +
+ + + + + + + + + + \ No newline at end of file diff --git a/links.json b/links.json new file mode 100755 index 0000000..c54ccaa --- /dev/null +++ b/links.json @@ -0,0 +1,140 @@ +{ + "bookmarks" : [ + { + "category": "Communicate", + "links": [ + { + "name": "Discord", + "url": "https://discordapp.com/" + }, + { + "name": "Gmail", + "url": "http://gmail.com" + }, + { + "name": "Slack", + "url": "https://slack.com/signin" + } + ] + }, + { + "category": "Cloud", + "links": [ + { + "name": "Box", + "url": "https://box.net" + }, + { + "name": "Dropbox", + "url": "https://dropbox.com" + }, + { + "name": "Drive", + "url": "https://drive.google.com" + } + ] + }, + { + "category": "Design", + "links": [ + { + "name": "Awwwards", + "url": "https://awwwards.com" + }, + { + "name": "Dribbble", + "url": "https://dribbble.com" + }, + { + "name": "Muz.li", + "url": "https://medium.muz.li/" + } + ] + }, + { + "category": "Dev", + "links": [ + { + "name": "Codepen", + "url": "https://codepen.io/" + }, + { + "name": "Devdocs", + "url": "https://devdocs.io" + }, + { + "name": "Devhints", + "url": "https://devhints.io" + } + ] + }, + { + "category": "Lifestyle", + "links": [ + { + "name": "Design Milk", + "url": "https://design-milk.com/category/interior-design/" + }, + { + "name": "Dwell", + "url": "https://www.dwell.com/" + }, + { + "name": "Freshome", + "url": "https://freshome.com/" + } + ] + }, + { + "category": "Media", + "links": [ + { + "name": "Spotify", + "url": "http://browse.spotify.com" + }, + { + "name": "Trakt", + "url": "http://trakt.tv" + }, + { + "name": "YouTube", + "url": "http://youtube.com/subscriptions" + } + ] + }, + { + "category": "Reading", + "links": [ + { + "name": "Instapaper", + "url": "https://www.instapaper.com/u" + }, + { + "name": "Medium", + "url": "http://medium.com" + }, + { + "name": "Reddit", + "url": "http://reddit.com" + } + ] + }, + { + "category": "Tech", + "links": [ + { + "name": "TheNextWeb", + "url": "https://thenextweb.com/" + }, + { + "name": "The Verge", + "url": "https://theverge.com/" + }, + { + "name": "MIT Technology Review", + "url": "https://www.technologyreview.com/" + } + ] + } + ] + } \ No newline at end of file diff --git a/providers.json b/providers.json new file mode 100755 index 0000000..8aa3305 --- /dev/null +++ b/providers.json @@ -0,0 +1,15 @@ +{ + "providers" : [ + {"name":"Allmusic","url":"https://www.allmusic.com/search/all/","prefix":"/a"}, + {"name":"Discogs","url":"https://www.discogs.com/search/?q=","prefix":"/di"}, + {"name":"Duck Duck Go","url":"https://duckduckgo.com/?q=","prefix":"/d"}, + {"name":"iMDB","url":"https://www.imdb.com/find?q=","prefix":"/i"}, + {"name":"TheMovieDB","url":"https://www.themoviedb.org/search?query=","prefix":"/m"}, + {"name":"Reddit","url":"https://www.reddit.com/search?q=","prefix":"/r"}, + {"name":"Qwant","url":"https://www.qwant.com/?q=","prefix":"/q"}, + {"name":"Soundcloud","url":"https://soundcloud.com/search?q=","prefix":"/so"}, + {"name":"Spotify","url":"https://open.spotify.com/search/results/","prefix":"/s"}, + {"name":"TheTVDB","url":"https://www.thetvdb.com/search?q=","prefix":"/tv"}, + {"name":"Trakt","url":"https://trakt.tv/search?query=","prefix":"/t"} + ] +} \ No newline at end of file