summaryrefslogtreecommitdiff
path: root/src/templates
diff options
context:
space:
mode:
Diffstat (limited to 'src/templates')
-rw-r--r--src/templates/404.html38
-rw-r--r--src/templates/admin/blog.html37
-rw-r--r--src/templates/admin/blog_create.html32
-rw-r--r--src/templates/admin/blog_edit.html42
-rw-r--r--src/templates/admin/index.html11
-rw-r--r--src/templates/admin/login.html36
-rw-r--r--src/templates/base.html84
-rw-r--r--src/templates/blog/index.html27
-rw-r--r--src/templates/blog/post.html89
-rw-r--r--src/templates/clocks.html56
-rw-r--r--src/templates/index.html66
-rw-r--r--src/templates/projects.html96
12 files changed, 614 insertions, 0 deletions
diff --git a/src/templates/404.html b/src/templates/404.html
new file mode 100644
index 0000000..b7b0961
--- /dev/null
+++ b/src/templates/404.html
@@ -0,0 +1,38 @@
+{% extends "base.html" %}
+
+{% block head %}
+{{ super() }}
+
+<style>
+#main {
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+ align-items: center;
+ justify-content: center;
+}
+
+span {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ text-align: center;
+ max-width: 600px;
+}
+</style>
+{% endblock %}
+
+{% block content %}
+<img src="/static/assets/404.jpg" alt="http.cat for 404" height="300" />
+
+<span id="text">
+ <h1>I'm sorry I let you down...</h1>
+
+ {% if request.path == "/femboys" %}
+ <p>no bitches?</p>
+ {% else %}
+ <p>{{ request.path }} not found on the server! mayhaps you misspelt the url? (it happens to the best of us)</p>
+ {% endif %}
+</span>
+{% endblock %}
diff --git a/src/templates/admin/blog.html b/src/templates/admin/blog.html
new file mode 100644
index 0000000..8cb1433
--- /dev/null
+++ b/src/templates/admin/blog.html
@@ -0,0 +1,37 @@
+{% extends "base.html" %}
+
+{% block head %}
+{{ super() }}
+
+<style>
+#main {
+ gap: 12px;
+}
+
+#create-new {
+ background-color: white;
+ color: black;
+ border: 1px white solid;
+}
+
+a.container {
+ color: inherit;
+}
+</style>
+{% endblock %}
+
+{% block content %}
+
+<a id="create-new" href="/admin/blog/create">create new post</a>
+
+{% for post in posts|sort(attribute="id", reverse=True) %}
+
+<a class="container" href="/admin/blog/{{ post.id }}">
+ <p>id: {{ post.id }}</p>
+ <h2>{{ post.title }}</h2>
+ <p>{{ post.description or "" }}</p>
+</a>
+
+{% endfor %}
+
+{% endblock %}
diff --git a/src/templates/admin/blog_create.html b/src/templates/admin/blog_create.html
new file mode 100644
index 0000000..ac4740b
--- /dev/null
+++ b/src/templates/admin/blog_create.html
@@ -0,0 +1,32 @@
+{% extends "base.html" %}
+
+{% block head %}
+{{ super() }}
+
+<link rel="stylesheet" href="/static/stylesheets/admin_blog.css">
+{% endblock %}
+
+{% block content %}
+
+<h1>create a post!</h1>
+
+<form class="flex-col" method="post">
+ <div class="flex-col" style="margin-bottom: 12px;">
+ <label for="title">title:</label>
+ <input type="text" name="title" />
+
+ <label for="description">description:</label>
+ <input type="text" name="description" />
+ </div>
+
+ <textarea placeholder="edit here" name="text"></textarea>
+
+ <div class="flex-row" style="margin: 12px 0; gap: 6px;">
+ <input type="checkbox" name="public" />
+ <label for="public">make public</label>
+ </div>
+
+ <input type="submit" value="create" />
+</form>
+
+{% endblock %}
diff --git a/src/templates/admin/blog_edit.html b/src/templates/admin/blog_edit.html
new file mode 100644
index 0000000..99c3d9c
--- /dev/null
+++ b/src/templates/admin/blog_edit.html
@@ -0,0 +1,42 @@
+{% extends "base.html" %}
+
+{% block head %}
+{{ super() }}
+
+<link rel="stylesheet" href="/static/stylesheets/admin_blog.css">
+{% endblock %}
+
+{% block content %}
+
+<h1>edit a post!</h1>
+
+<button id="delete-post">delete</button>
+
+<form class="flex-col" method="post">
+ <div class="flex-col" style="margin-bottom: 12px;">
+ <label for="title">title:</label>
+ <input type="text" name="title" value="{{ post.title }}" />
+
+ <label for="description">description:</label>
+ <input type="text" name="description" value="{{ post.description or '' }}" />
+ </div>
+
+ <textarea placeholder="edit here" name="text">{{ post.original }}</textarea>
+
+ <div class="flex-row" style="margin: 12px 0; gap: 6px;">
+ <input type="checkbox" name="public" {{ "checked" if post.public else "" }} />
+ <label for="public">make public</label>
+ </div>
+
+ <input type="submit" value="edit" />
+</form>
+
+<script>
+document.getElementById("delete-post").onclick = async (e) => {
+ origin = window.location.origin
+ await fetch(`${origin}/admin/blog/{{ post.id }}`, { method: "DELETE" });
+ window.location.href = `${origin}/admin/blog`;
+};
+</script>
+
+{% endblock %}
diff --git a/src/templates/admin/index.html b/src/templates/admin/index.html
new file mode 100644
index 0000000..11e414d
--- /dev/null
+++ b/src/templates/admin/index.html
@@ -0,0 +1,11 @@
+{% extends "base.html" %}
+
+{% block content %}
+
+<h1>welcome to admin mode, me!</h1>
+
+<p>safety button to sign out:</p>
+
+<a href="/admin/logout">here</a>
+
+{% endblock %}
diff --git a/src/templates/admin/login.html b/src/templates/admin/login.html
new file mode 100644
index 0000000..e37e046
--- /dev/null
+++ b/src/templates/admin/login.html
@@ -0,0 +1,36 @@
+{% extends "base.html" %}
+
+{% block head %}
+
+{{ super() }}
+
+<script src="/static/js/htmx.min.js"></script>
+
+<script>
+htmx.config.responseHandling = [
+ {code: "204", swap: false},
+ {code: "3..", swap: false},
+ {code: "[45]..", swap: true, error: false},
+ {code: "...", swap: false},
+];
+</script>
+
+<style>
+#error-msg p {
+ color: red;
+ max-width: 400px;
+ text-align: center;
+}
+</style>
+{% endblock %}
+
+{% block content %}
+<form hx-post="/admin/login" hx-swap="innerHTML" hx-target="#error-msg">
+ <label for="password">Password:</label>
+ <input type="password" name="password" />
+
+ <input type="submit" value="Submit" />
+
+ <div id="error-msg"></div>
+</form>
+{% endblock %}
diff --git a/src/templates/base.html b/src/templates/base.html
new file mode 100644
index 0000000..935ab5e
--- /dev/null
+++ b/src/templates/base.html
@@ -0,0 +1,84 @@
+{% macro navbutton(path, name=None) -%}
+<a class="label" {{ "active" if label_active(path) else "" }} href="{{ path }}">{{ name or path }}</a>
+{%- endmacro %}
+
+{% set adminmode = request.path.startswith("/admin") %}
+
+<!DOCTYPE html>
+<html>
+<head>
+ {% block head %}
+ <title>Emma | {{ title }}</title>
+
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+
+ <meta name="og:title" content="Emma | {{ title }}">
+ <meta name="og:description" content="{{ description }}">
+ <meta name="og:type" content="website">
+
+ <link rel="preconnect" href="https://fonts.googleapis.com">
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
+ <link href="https://fonts.googleapis.com/css2?family=Noto+Sans+Mono:wght@100..900&display=swap" rel="stylesheet">
+
+ <link rel="stylesheet" href="/static/stylesheets/base.css">
+
+ {% if adminmode %}
+ <style>
+ #admin-text {
+ color: red;
+ position: absolute;
+ top: 0;
+ right: 1rem;
+ }
+ </style>
+ {% endif %}
+
+ {% endblock %}
+</head>
+<body>
+ <nav>
+ <div id="nav-padding"></div>
+ <div id="nav-inner">
+ {% if adminmode %}
+ {{ navbutton("/admin/", "home") }}
+ {{ navbutton("/admin/blog", "blog") }}
+ {% else %}
+ {{ navbutton("/", "/home") }}
+ {{ navbutton("/projects") }}
+ {{ navbutton("/blog") }}
+ {{ navbutton("/clocks") }}
+ {% endif %}
+ </div>
+ <div id="nav-padding"></div>
+ </nav>
+
+ <div id="main">
+ {% block content %}
+ {% endblock %}
+
+ {% if not adminmode %}
+ <div id="buttons" style="margin-top: 12px;">
+ <a href="https://88x31.kate.pet">
+ <img class="button" src="/static/assets/buttons/0_88x31.kate.pet.png" />
+ </a>
+
+ <img class="button" src="/static/assets/buttons/flag-bi.png" alt="taken from kate.pet" />
+ <img class="button" src="/static/assets/buttons/flag-trans.png" alt="taken from kate.pet" />
+ <img class="button" src="/static/assets/buttons/lastfm-01.png" alt="taken from kate.pet" />
+ <img class="button" src="/static/assets/buttons/hackerpowered.gif" alt="taken from kate.pet" />
+
+ <a href="https://kernel.org">
+ <img class="button" src="/static/assets/buttons/xeniatrans_now.gif" alt="taken from kate.pet" />
+ </a>
+
+ <img class="button" src="/static/assets/buttons/python.png" alt="made by yours truly" />
+ </div>
+ {% endif %}
+ </div>
+
+ {% if adminmode %}
+ <p id="admin-text">(admin)</p>
+ {% endif %}
+</body>
+</html>
diff --git a/src/templates/blog/index.html b/src/templates/blog/index.html
new file mode 100644
index 0000000..a0aee24
--- /dev/null
+++ b/src/templates/blog/index.html
@@ -0,0 +1,27 @@
+{% extends "base.html" %}
+
+{% block head %}
+{{ super() }}
+
+<link rel="stylesheet" href="/static/stylesheets/blog.css">
+{% endblock %}
+
+{% block content %}
+
+<h1>blog</h1>
+
+<div id="posts">
+ {% for post in posts|sort(attribute="created_at", reverse=True) %}
+ <a class="container post" href="/blog/{{ post.id }}">
+ <h2>{{ post.title }}</h2>
+ <p>{{ post.description or "" }}</p>
+ <p class="created-at">posted {{ format_ts(post.created_at) }}</p>
+ </a>
+ {% endfor %}
+
+ {% if posts|length == 0 %}
+ <p>huh, I guess nothing has been posted yet.</p>
+ {% endif %}
+</div>
+
+{% endblock %}
diff --git a/src/templates/blog/post.html b/src/templates/blog/post.html
new file mode 100644
index 0000000..92c48a2
--- /dev/null
+++ b/src/templates/blog/post.html
@@ -0,0 +1,89 @@
+{% extends "base.html" %}
+
+{% block head %}
+{{ super() }}
+
+<style>
+ article {
+ width: 600px;
+ text-align: left;
+ }
+
+ header {
+ padding: 14px;
+ background-color: rgba(255, 255, 255, 0.6);
+ border-bottom: 2px solid black;
+ }
+
+ textarea {
+ resize: none;
+ width: 250px;
+ height: 90px;
+ }
+
+ #comments {
+ background-color: rgba(255, 255, 255, 0.6);
+ padding: 12px 20px;
+ width: 400px;
+ }
+
+ .comment {
+ border-bottom: 1px solid black;
+ }
+
+ .comment:last-child {
+ border-bottom: none;
+ }
+
+ .created-at {
+ font-size: 10px;
+ color: #333;
+ }
+</style>
+
+<script src="/static/js/htmx.min.js"></script>
+{% endblock %}
+
+{% block content %}
+
+<article>
+ <header>
+ <h1>{{ post.title }}</h1>
+
+ {% if post.description %}
+ <p>{{ post.description }}</p>
+ {% endif %}
+
+ <p>posted {{ post.created_at.strftime("%a %d %b %Y at %H:%M:%S") }}</p>
+ </header>
+
+ {{ post.text|safe }}
+</article>
+
+<h3>comments</h3>
+
+<form
+ hx-post="/blog/{{ post.id.hex }}/comments"
+ hx-target="#comments"
+ hx-on::after-request="if(event.detail.successful) this.reset()"
+ class="flex-col"
+ style="gap: 6px; margin-bottom: 12px;"
+>
+ <span class="flex-col">
+ <input type="text" name="author" placeholder="author" />
+ </span>
+
+ <span class="flex-col">
+ <textarea placeholder="text" name="text"></textarea>
+ </span>
+
+ <input type="submit" value="create" />
+</form>
+
+<div
+ id="comments"
+ hx-get="/blog/{{ post.id.hex }}/comments"
+ hx-trigger="revealed, newPost from:body"
+></div>
+
+{% endblock %}
diff --git a/src/templates/clocks.html b/src/templates/clocks.html
new file mode 100644
index 0000000..5e81d0d
--- /dev/null
+++ b/src/templates/clocks.html
@@ -0,0 +1,56 @@
+{% extends "base.html" %}
+
+{% block head %}
+
+{{ super() }}
+
+<style>
+span {
+ margin-top: 12px;
+}
+
+h4 {
+ margin: 0;
+ font-size: 16px;
+}
+
+.clock {
+ display: flex;
+ flex-direction: row;
+}
+
+.clock p::after {
+ margin: 0 6px;
+ content: ":";
+}
+
+.clock p:last-child::after {
+ content: none;
+}
+</style>
+
+{% endblock %}
+
+{% block content %}
+
+<span>
+ <h4>🏳️‍⚧️:</h4>
+ <!-- formerly set to 1719561600000 -->
+ <div class="clock" x-start-time="1714546800000">
+ <p id="d">00</p>
+ <p id="h">00</p>
+ <p id="m">00</p>
+ <p id="s">00</p>
+ </div>
+
+ <h4>the BEGINNING (of the unix timestamp):</h4>
+ <div class="clock" x-start-time="0">
+ <p id="d">00</p>
+ <p id="h">00</p>
+ <p id="m">00</p>
+ <p id="s">00</p>
+ </div>
+</span>
+
+<script lang="js" src="/static/js/clocks.js"></script>
+{% endblock %}
diff --git a/src/templates/index.html b/src/templates/index.html
new file mode 100644
index 0000000..27c1616
--- /dev/null
+++ b/src/templates/index.html
@@ -0,0 +1,66 @@
+{% extends "base.html" %}
+
+{% block head %}
+{{ super() }}
+
+<link rel="stylesheet" href="/static/stylesheets/index.css">
+
+{% endblock %}
+
+{% block content %}
+
+<div id="top" class="container">
+ <img id="pfp" src="/static/assets/pfps/1.jpg" height="200" />
+
+ <span>
+ <h1>Hai there! I'm Emma</h1>
+ <p>thanks for stopping by on my little website!</p>
+
+ <p>
+ I'm a full stack developer that tends to focus on random
+ projects for fun rather than full works.
+ </p>
+
+ <p>
+ currently, I have a good chunk of my code hosted on either
+ github or codeberg, and I aim to migrate to my own self-hosted
+ git server.
+ </p>
+
+ <span id="profile-links" class="flex-row">
+ <a href="https://github.com/EmmmaTech">github</a>
+ |
+ <a href="https://codeberg.org/EmmaTech">codeberg</a>
+ |
+ <a href="https://bsky.app/profile/did:plc:twprdsv3r6bvbkjlqyftrrf7">bluesky</a>
+ </span>
+ </span>
+</div>
+
+<div class="two-section">
+ <div id="qas" class="container">
+ <span>
+ <p><b>Woah, where's the background from? :o</b></p>
+ <p>
+ the background comes from a wallpaper used in early builds
+ of windows xp known as <a href="https://windowswallpaper.miraheze.org/wiki/Professional">professional/watercolor</a>.
+ </p>
+ </span>
+
+ <span>
+ <p><b>What about your profile picture?</b></p>
+ <p>
+ the profile picture is made by me, and it's a combination of a
+ discrete trans wallpaper and fanart of konata I found on <a href="https://www.pixiv.net/en/artworks/1068449">pixiv</a>.
+ </p>
+ </span>
+ </div>
+
+ <div class="container" style="padding: 20px;">
+ <h3>random image of the day</h3>
+
+ <img src="/static/assets/pfps/2.jpg" width="225" />
+ </div>
+</div>
+
+{% endblock %}
diff --git a/src/templates/projects.html b/src/templates/projects.html
new file mode 100644
index 0000000..d00b544
--- /dev/null
+++ b/src/templates/projects.html
@@ -0,0 +1,96 @@
+{% extends "base.html" %}
+
+{% block head %}
+{{ super() }}
+
+<link rel="stylesheet" href="/static/stylesheets/projects.css">
+
+{% endblock %}
+
+{% block content %}
+
+<h1>projects</h1>
+
+<div class="flex-col" style="gap: 12px;">
+ <div class="project container">
+ <span class="project-head">
+ <h2>soteria</h2>
+
+ <span class="project-labels">
+ <p>typescript</p>
+ <p>sveltekit</p>
+ <p>elysia</p>
+ <p>twitter</p>
+ </span>
+
+ <span class="project-links">
+ <a href="https://codeberg.org/soteria">codeberg</a>
+ <a href="https://soteria.social">website</a>
+ </span>
+ </span>
+
+ <div class="project-separator"></div>
+
+ <p>
+ twitter-like microblogging social media platform created by me and two other friends.
+ <br>
+ currently undergoing major rewrites in the backend and frontend, so the provided website
+ is not functional for the time being.
+ </p>
+ </div>
+
+ <div class="project container">
+ <span class="project-head">
+ <h2>arke</h2>
+
+ <span class="project-labels">
+ <p>python</p>
+ <p>discord</p>
+ <p>library</p>
+ <p>low-level</p>
+ </span>
+
+ <span class="project-links">
+ <a href="https://codeberg.org/EmmaTech/arke">codeberg</a>
+ </span>
+ </span>
+
+ <div class="project-separator"></div>
+
+ <p>
+ low-level, low abstractions library made to dip my toes into the python discord
+ library space.
+ <br>
+ highly inspired by a related project called <a href="https://github.com/nextsnake/nextcore">nextcore</a>,
+ arke implements the discord rest api & ws gateway without providing simple to use models to
+ represent discord's data types.
+ </p>
+ </div>
+
+ <div class="project container">
+ <span class="project-head">
+ <h2>tiny-http-server</h2>
+
+ <span class="project-labels">
+ <p>c</p>
+ <p>bsd sockets</p>
+ <p>http</p>
+ <p>library</p>
+ </span>
+
+ <span class="project-links">
+ <a href="https://github.com/EmmmaTech/tiny-http-server">github</a>
+ </span>
+ </span>
+
+ <div class="project-separator"></div>
+
+ <p>
+ basic and tiny http/1.1 server, using the stdlib and bsd sockets interface. it
+ features basic tls support via openssl, and allows file serving from an arbitrary directory and
+ programmable routes.
+ </p>
+ </div>
+</div>
+
+{% endblock %}