Browse Source

first commit

root 6 years ago
commit
69aa0718b4
11 changed files with 1220 additions and 0 deletions
  1. 9 0
      Dockerfile
  2. 24 0
      apps.json
  3. 548 0
      assets/css/styles.css
  4. 35 0
      assets/js/data.js
  5. 37 0
      assets/js/script.js
  6. 122 0
      assets/js/search.js
  7. 139 0
      assets/js/themer.js
  8. 24 0
      docker-compose.yml
  9. 127 0
      index.html
  10. 140 0
      links.json
  11. 15 0
      providers.json

+ 9 - 0
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

+ 24 - 0
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"}
+    ]
+}

+ 548 - 0
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;
+	}
+}

+ 35 - 0
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);
+  });
+});

+ 37 - 0
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();
+}
+
+

+ 122 - 0
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);
+};

+ 139 - 0
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;
+
+        }
+    })
+}

+ 24 - 0
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

+ 127 - 0
index.html

@@ -0,0 +1,127 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>SUI</title>
+    <meta charset="utf-8">
+    <meta http-equiv="Default-Style" content="">
+    <meta content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport" />
+    <link type="text/css" rel="stylesheet" href="/assets/css/styles.css"  media="screen,projection"/>
+    <link href="https://fonts.googleapis.com/css?family=Roboto:400,500,700,900" rel="stylesheet">
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.1.1/handlebars.min.js"></script>
+    <script src="https://code.iconify.design/1/1.0.0-rc7/iconify.min.js"></script>
+</head>
+
+<body onload="loadFunctions()">
+    
+    <section id="modal">
+        <div>
+            <header id="modal-header">
+                <h1>Options</h1>
+                <a href="#" title="Close" class="modal-close">
+                    <span class="iconify" data-icon="mdi-close"></span>
+                </a>
+            </header>
+
+            <h2>Color themes</h2>
+
+            <div id="modal-theme">
+                <button data-theme="blackboard" class="theme-button theme-blackboard">Blackboard</button>
+                <button data-theme="gazette" class="theme-button theme-gazette">Gazette</button>
+                <button data-theme="espresso" class="theme-button theme-espresso">Espresso</button>
+                <button data-theme="cab" class="theme-button theme-cab">Cab</button>
+                <button data-theme="cloud" class="theme-button theme-cloud">Cloud</button>
+                <button data-theme="lime" class="theme-button theme-lime">Lime</button>
+                <button data-theme="passion" class="theme-button theme-passion">Passion</button>
+                <button data-theme="blues" class="theme-button theme-blues">Blues</button>
+                <button data-theme="chalk" class="theme-button theme-chalk">Chalk</button>
+                <button data-theme="tron" class="theme-button theme-tron">Tron</button>
+                <button data-theme="paper" class="theme-button theme-paper">Paper</button>
+            </div>
+
+            <h2>Search options</h2>
+
+            <section id="providers">
+                <script type="text/handlebars-template" id="providers-template">
+                    <table>
+                        <tr>
+                            <th>Website</th>
+                            <th>Prefix</th>
+                        </tr>
+                        {{#providers}}
+                        <tr>
+                            <td><a href="{{url}}">{{name}}</a></td>
+                            <td>{{prefix}}</td>
+                        </tr>
+                        {{/providers}}
+                    </table>
+                </script>
+            </section>
+
+            <header id="modal-footer">
+                <a href="https://github.com/jeroenpardon/"><span class="iconify" data-icon="mdi-github-box"></span></a>
+                <a href="https://materialdesignicons.com/"><span class="iconify" data-icon="mdi-material-design"></a></span>
+            </header>
+        </div>
+    </section>    
+
+    <main id="container" class="fade">
+
+        <section id="search">
+            <input name="keywords" type="text" id="keywords" size="50" spellcheck="false" autofocus="true" onkeydown="handleKeyPress(event)">
+        </section>
+            
+        <section id="header">
+            <h2 id="header_date"></h2>
+            <h1 id="header_greet"></h1>
+        </section>
+
+        <section id="apps">
+            <script type="text/handlebars-template" id="apps-template">
+            <h3>Applications</h3>
+            <div id="apps_loop">
+                {{#apps}}
+                    <div class="apps_item">
+                        <div class="apps_icon">
+                            <span class="iconify icon" data-icon="mdi-{{icon}}"></span>
+                        </div>
+                        <div class="apps_text">
+                            <a href="https://{{url}}">{{name}}</a>
+                            <span>{{url}}</span>
+                        </div>
+                    </div>
+                {{/apps}}                         
+            </div>
+            </script>
+        </section>
+
+         <section id="links">
+            <script type="text/handlebars-template" id="links-template">
+            <h3>Bookmarks</h3>
+            <div id="links_loop">
+                {{#bookmarks}}
+                    <div id="links_item">
+                        <h4>{{category}}</h4>
+                        {{#links}}
+                            <a href="{{url}}" class="theme_color-border theme_text-select">{{name}}</a>
+                        {{/links}}
+                    </div>
+                {{/bookmarks}}
+            </div>    
+            </script>
+        </section>
+    </main>
+
+    <div id="modal_init">
+        <a class="btn" href="#modal">
+            <span class="iconify icon" data-icon="mdi-xbox-controller-menu"></span>
+        </a>
+    </div>
+
+    <script src="/assets/js/data.js" type="text/javascript"></script>
+    <script src="/assets/js/script.js" type="text/javascript"></script>
+    <script src="/assets/js/themer.js" type="text/javascript"></script>
+    <script src="/assets/js/search.js" type="text/javascript"></script>
+    
+</body>
+</html>

+ 140 - 0
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/"
+                  }
+                ]
+              }
+            ]
+        }

+ 15 - 0
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"}
+    ]
+}