+
+
diff --git a/frontend/public/index.xml b/frontend/public/index.xml
new file mode 100644
index 0000000..2462bc7
--- /dev/null
+++ b/frontend/public/index.xml
@@ -0,0 +1,10 @@
+
+
+
+ Shockrah's Clips
+ https://clips.shockrah.xyz/
+ Recent content on Shockrah's Clips
+ Hugo -- gohugo.io
+ en-us
+
+
diff --git a/frontend/public/sitemap.xml b/frontend/public/sitemap.xml
new file mode 100644
index 0000000..f7f0f57
--- /dev/null
+++ b/frontend/public/sitemap.xml
@@ -0,0 +1,11 @@
+
+
+
+ https://clips.shockrah.xyz/categories/
+
+ https://clips.shockrah.xyz/
+
+ https://clips.shockrah.xyz/tags/
+
+
diff --git a/frontend/public/tags/index.xml b/frontend/public/tags/index.xml
new file mode 100644
index 0000000..d509e60
--- /dev/null
+++ b/frontend/public/tags/index.xml
@@ -0,0 +1,10 @@
+
+
+
+ Tags on Shockrah's Clips
+ https://clips.shockrah.xyz/tags/
+ Recent content in Tags on Shockrah's Clips
+ Hugo -- gohugo.io
+ en-us
+
+
diff --git a/frontend/static/favicon.png b/frontend/static/favicon.png
new file mode 100644
index 0000000..525b84e
Binary files /dev/null and b/frontend/static/favicon.png differ
diff --git a/frontend/themes/clippable/LICENSE b/frontend/themes/clippable/LICENSE
new file mode 100644
index 0000000..e4483e2
--- /dev/null
+++ b/frontend/themes/clippable/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2021 YOUR_NAME_HERE
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/frontend/themes/clippable/archetypes/default.md b/frontend/themes/clippable/archetypes/default.md
new file mode 100644
index 0000000..ac36e06
--- /dev/null
+++ b/frontend/themes/clippable/archetypes/default.md
@@ -0,0 +1,2 @@
++++
++++
diff --git a/frontend/themes/clippable/layouts/404.html b/frontend/themes/clippable/layouts/404.html
new file mode 100644
index 0000000..e69de29
diff --git a/frontend/themes/clippable/layouts/_default/baseof.html b/frontend/themes/clippable/layouts/_default/baseof.html
new file mode 100644
index 0000000..5f8e2ec
--- /dev/null
+++ b/frontend/themes/clippable/layouts/_default/baseof.html
@@ -0,0 +1,11 @@
+
+
+ {{- partial "head.html" . -}}
+
+ {{- partial "header.html" . -}}
+
+ {{- block "main" . }}{{- end }}
+
+ {{- partial "footer.html" . -}}
+
+
diff --git a/frontend/themes/clippable/layouts/_default/list.html b/frontend/themes/clippable/layouts/_default/list.html
new file mode 100644
index 0000000..e69de29
diff --git a/frontend/themes/clippable/layouts/_default/single.html b/frontend/themes/clippable/layouts/_default/single.html
new file mode 100644
index 0000000..e69de29
diff --git a/frontend/themes/clippable/layouts/index.html b/frontend/themes/clippable/layouts/index.html
new file mode 100644
index 0000000..a35a1c9
--- /dev/null
+++ b/frontend/themes/clippable/layouts/index.html
@@ -0,0 +1,14 @@
+
+
+{{- partial "head.html" . -}}
+
+
+
+
+
{{ .Title }}
+
+
+
+
+
+
diff --git a/frontend/themes/clippable/layouts/partials/footer.html b/frontend/themes/clippable/layouts/partials/footer.html
new file mode 100644
index 0000000..e69de29
diff --git a/frontend/themes/clippable/layouts/partials/head.html b/frontend/themes/clippable/layouts/partials/head.html
new file mode 100644
index 0000000..b097b45
--- /dev/null
+++ b/frontend/themes/clippable/layouts/partials/head.html
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+ {{ $title := print .Title }}
+ {{ if .IsHome }}{{ $title = .Site.Title}}{{end}}
+ {{ $title }}
+
+
+ {{ $url := .RelPermalink | absURL }}
+
+ {{ $desc := print .Description }}
+ {{ if .IsHome }}{{ $desc = .Params.Description }}{{end}}
+
+
+ {{ $ogvideo := "" }}
+ {{ if .Params.Video }}
+ {{ $ogvideo = .Params.Video }}
+
+
+
+ {{ else }}
+ {{ $ogimage := "/favicon.png" }}
+ {{ if .Params.Image }}
+ {{ $ogimage = .Params.Image }}
+ {{ end }}
+
+ {{ end }}
+
+
diff --git a/frontend/themes/clippable/layouts/partials/header.html b/frontend/themes/clippable/layouts/partials/header.html
new file mode 100644
index 0000000..e69de29
diff --git a/frontend/themes/clippable/static/css/style.css b/frontend/themes/clippable/static/css/style.css
new file mode 100644
index 0000000..9831678
--- /dev/null
+++ b/frontend/themes/clippable/static/css/style.css
@@ -0,0 +1,42 @@
+html, body, div, tag {
+ margin: 0;
+ padding: 0;
+ border: 0;
+ font-size: 100%;
+ vertical-align: baseline;
+ background: #212121;
+ text-align: center;
+}
+
+* {
+ box-sizing: border-box;
+}
+
+.content {
+ margin: 0 auto;
+ padding: 0 2em;
+ line-height: 1.6em;
+ color: whitesmoke;
+}
+.video-gallery {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+.video-block {
+ padding: 1em;
+ width: 400px;
+ line-height: 1em;
+ margin-right: 1em;
+ margin-bottom: 1em;
+ background: #191818;
+ border-radius: 1em;
+}
+
+.pure-form {
+ text-align: center;
+}
+.pure-img {
+ border-radius: 0.5em;
+}
diff --git a/frontend/themes/clippable/static/js/index.js b/frontend/themes/clippable/static/js/index.js
new file mode 100644
index 0000000..ed9bba5
--- /dev/null
+++ b/frontend/themes/clippable/static/js/index.js
@@ -0,0 +1,42 @@
+"use strict";
+class Category {
+ constructor(raw) {
+ this.name = raw['name'];
+ this.thumbnail_b64 = raw['thumbnail'];
+ }
+ as_div_str() {
+ let container = document.createElement('div');
+ container.className = 'video-block';
+ let title = document.createElement('h2');
+ title.innerText = this.name;
+ let nail = document.createElement('img');
+ nail.className = 'pure-img';
+ if (!(this.thumbnail_b64 == null || this.thumbnail_b64.length == 0)) {
+ nail.setAttribute('src', `data:image/jpg;base64,${this.thumbnail_b64}`);
+ }
+ container.appendChild(title);
+ container.appendChild(nail);
+ document.getElementById('main-container').appendChild(container);
+ return container;
+ }
+}
+function ready_handler(e) {
+ // Only let this make a get request once we're ready on the page
+ if (document.readyState != 'complete') {
+ return e;
+ }
+ // All we do here is basically make a get request to /api/categories
+ const endpoint = 'http://localhost/api/categories';
+ let xml = new XMLHttpRequest();
+ xml.open('GET', endpoint, false); // sync request
+ xml.send(null); // nothing required for stuff
+ if (xml.getResponseHeader('Content-Type') == 'application/json') {
+ let raw = JSON.parse(xml.responseText);
+ for (const cat_raw of raw['categories']) {
+ let cat = new Category(cat_raw);
+ cat.as_div_str();
+ }
+ }
+ return e;
+}
+document.addEventListener('readystatechange', ready_handler);
diff --git a/frontend/themes/clippable/theme.toml b/frontend/themes/clippable/theme.toml
new file mode 100644
index 0000000..d090c46
--- /dev/null
+++ b/frontend/themes/clippable/theme.toml
@@ -0,0 +1,21 @@
+# theme.toml template for a Hugo theme
+# See https://github.com/gohugoio/hugoThemes#themetoml for an example
+
+name = "Clippable"
+license = "MIT"
+licenselink = "https://github.com/yourname/yourtheme/blob/master/LICENSE"
+description = ""
+homepage = "http://example.com/"
+tags = []
+features = []
+min_version = "0.41.0"
+
+[author]
+ name = ""
+ homepage = ""
+
+# If porting an existing theme
+[original]
+ name = ""
+ homepage = ""
+ repo = ""
diff --git a/frontend/ts/index.ts b/frontend/ts/index.ts
new file mode 100644
index 0000000..dd06fb1
--- /dev/null
+++ b/frontend/ts/index.ts
@@ -0,0 +1,51 @@
+class Category {
+ name: string
+ thumbnail_b64: string|null
+ constructor(raw: any) {
+ this.name = raw['name']
+ this.thumbnail_b64 = raw['thumbnail']
+ }
+
+ public as_div_str() {
+ let container = document.createElement('div')
+ container.className = 'video-block'
+
+ let title = document.createElement('h2')
+ title.innerText = this.name
+
+ let nail = document.createElement('img')
+ nail.className = 'pure-img'
+ if(!(this.thumbnail_b64 == null || this.thumbnail_b64.length == 0)) {
+ nail.setAttribute('src', `data:image/jpg;base64,${this.thumbnail_b64}`)
+ }
+
+ container.appendChild(title)
+ container.appendChild(nail)
+
+ document.getElementById('main-container').appendChild(container)
+
+ return container
+ }
+}
+
+function ready_handler(e?: Event) : Event {
+ // Only let this make a get request once we're ready on the page
+ if(document.readyState != 'complete') { return e }
+
+ // All we do here is basically make a get request to /api/categories
+ const endpoint = 'http://localhost/api/categories'
+ let xml = new XMLHttpRequest()
+
+ xml.open('GET', endpoint, false) // sync request
+ xml.send(null) // nothing required for stuff
+ if(xml.getResponseHeader('Content-Type') == 'application/json') {
+ let raw = JSON.parse(xml.responseText)
+ for(const cat_raw of raw['categories']) {
+ let cat = new Category(cat_raw)
+ cat.as_div_str()
+ }
+ }
+ return e
+}
+
+document.addEventListener('readystatechange', ready_handler)
diff --git a/frontend/ts/package.json b/frontend/ts/package.json
new file mode 100644
index 0000000..0d78012
--- /dev/null
+++ b/frontend/ts/package.json
@@ -0,0 +1,16 @@
+{
+ "name": "ts",
+ "version": "1.0.0",
+ "description": "Frontend scripts built out for clippable's frontend",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "build": "tsc"
+ },
+ "repository": {
+ "type": "git",
+ "url": "gitlab.com/shockrah/clippable.git"
+ },
+ "author": "shockrah",
+ "license": "GPL-3.0"
+}
diff --git a/frontend/ts/tsconfig.json b/frontend/ts/tsconfig.json
new file mode 100644
index 0000000..f4d497f
--- /dev/null
+++ b/frontend/ts/tsconfig.json
@@ -0,0 +1,27 @@
+{
+ "compilerOptions": {
+ "target": "es6",
+ "module": "commonjs",
+ "outDir": "../themes/clippable/static/js/",
+ "importHelpers": true,
+ /* Strict Type-Checking Options */
+ "strict": true,
+ "strictNullChecks": false,
+ "strictFunctionTypes": true,
+ "noImplicitThis": true,
+ "alwaysStrict": true,
+
+ /* Additional Checks */
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "noImplicitReturns": true,
+ "noFallthroughCasesInSwitch": true,
+ /*"noUncheckedIndexedAccess": true, */
+ /*"noPropertyAccessFromIndexSignature": true, */
+
+ /* Module Resolution Options */
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "forceConsistentCasingInFileNames": true,
+ }
+}