diff --git a/example.env b/example.env
index 53205b3..914d25b 100644
--- a/example.env
+++ b/example.env
@@ -37,7 +37,6 @@ SNIKKET_WEB_DOMAIN='localhost'
#
#SNIKKET_WEB_SITE_NAME
-
# OPTIONAL SETTINGS
# =================
@@ -48,3 +47,7 @@ SNIKKET_WEB_DOMAIN='localhost'
# not re-transferred.
#
#SNIKKET_WEB_AVATAR_CACHE_TTL=1800
+
+# Your XMPP account name and email address, to be shown on
+# the homepage.
+#SNIKKET_WEB_ADMIN_CONTACT=""
diff --git a/snikket_web/__init__.py b/snikket_web/__init__.py
index 7c5fe91..efd578a 100644
--- a/snikket_web/__init__.py
+++ b/snikket_web/__init__.py
@@ -177,6 +177,7 @@ class AppConfig:
abuse_email = environ.var("")
security_email = environ.var("")
+ admin_contact = environ.var("")
_UPPER_CASE = "".join(map(chr, range(ord("A"), ord("Z")+1)))
@@ -215,6 +216,8 @@ def create_app() -> quart.Quart:
app.config["SESSION_COOKIE_SECURE"] = True
app.config["SESSION_COOKIE_SAMESITE"] = "Lax"
+ app.config["ADMIN_CONTACT"] = config.admin_contact
+
app.context_processor(proc)
app.register_error_handler(
aiohttp.ClientConnectorError,
@@ -230,11 +233,11 @@ def create_app() -> quart.Quart:
)
@app.route("/")
- async def index() -> werkzeug.Response:
+ async def index() -> typing.Union[str, werkzeug.Response]:
if infra.client.has_session:
- return redirect(url_for('user.index'))
+ return redirect(url_for("user.index"))
- return redirect(url_for('main.login'))
+ return await render_template("home.html")
@app.route("/site.webmanifest")
def site_manifest() -> quart.Response:
diff --git a/snikket_web/scss/home.scss b/snikket_web/scss/home.scss
new file mode 100644
index 0000000..df453fb
--- /dev/null
+++ b/snikket_web/scss/home.scss
@@ -0,0 +1,194 @@
+/*
+ * Reset
+ */
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+p,
+ul,
+li,
+img,
+figure,
+figcaption,
+table,
+td,
+tr,
+thead,
+tbody,
+details,
+summary {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+}
+
+:root {
+ /* Text related colors */
+ --copy: #444444;
+ --copy-darker: #242424;
+ --copy-darker-2: #121212;
+ --copy-lighter: #6b6b6b;
+ --copy-lighter-2: #c4c4c4;
+ --hyperlink: #155bca;
+
+ /* Background related colors */
+ --bg: #fffaef;
+
+ /*
+ * Colors
+ */
+ --primary-color: #ff94a1;
+ --primary-color-half-light: #ffc6c8;
+ --secondary-color: #97aa9b;
+ --secondary-color-half-light: #e5e6d9;
+ --secondary-color-light: #cbd2c4;
+}
+
+html,
+body {
+ margin: 0;
+ padding: 0;
+ font-size: 18px;
+}
+
+body {
+ display: flex;
+ flex-direction: column;
+ min-height: 100vh;
+ justify-content: center;
+ align-items: center;
+ font-family: Verdana, sans-serif;
+ text-align: left;
+ word-wrap: break-word;
+ overflow-wrap: break-word;
+ background-color: var(--bg);
+ line-height: 1.5rem;
+}
+
+article,
+section,
+header,
+footer {
+ a {
+ --transition-property: inherit;
+ --color: var(--copy);
+ --hover-color: var(--primary-color);
+ --hover-thickness: 0.2rem;
+ --text-decoration: underline;
+ --text-decoration-color: var(--color);
+
+ color: var(--color);
+ text-decoration: none;
+
+ &[href]:not([aria-disabled="true"], [aria-current="page"]) {
+ text-decoration: var(--text-decoration);
+ text-decoration-line: var(--text-decoration);
+ text-decoration-color: var(--text-decoration-color);
+ text-decoration-thickness: 1px;
+ text-decoration-skip-ink: none;
+ transition-property:
+ text-decoration-thickness, text-decoration-color,
+ var(--transition-property);
+ transition-duration: var(--transition-duration);
+ transition-timing-function: var(--transition-timing-function);
+
+ &:hover,
+ &:active,
+ &:focus {
+ text-decoration-color: var(--hover-color);
+ text-decoration-thickness: var(--hover-thickness);
+ }
+ }
+
+ &[rel~="external"]:not(:has(img))::after {
+ display: inline-block;
+ content: "";
+ width: 12px;
+ height: 12px;
+ line-height: inherit;
+ vertical-align: middle;
+ background: var(--color);
+ mask-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMiIgaGVpZ2h0PSIxMiIgdmlld0JveD0iMCAwIDEyIDEyIj4KICAJPHBhdGggZmlsbD0iIzAwMDAwMCIgZD0iTTYgMWg1djVMOC44NiAzLjg1IDQuNyA4IDQgNy4zbDQuMTUtNC4xNnpNMiAzaDJ2MUgydjZoNlY4aDF2MmExIDEgMCAwIDEtMSAxSDJhMSAxIDAgMCAxLTEtMVY0YTEgMSAwIDAgMSAxLTEiLz4KPC9zdmc+");
+ margin-left: 0.2em;
+ }
+ }
+
+ h1,
+ h2,
+ h3,
+ h4,
+ h5,
+ h6 {
+ > a {
+ color: var(--copy);
+ }
+ }
+}
+
+main.home {
+ padding: 2rem;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 1.5rem;
+ max-width: 450px;
+
+ > header {
+ > img {
+ width: 250px;
+ margin-bottom: 0.3rem;
+ }
+
+ > h1 {
+ text-align: center;
+ font-size: 3rem;
+ line-height: 3rem;
+ font-weight: 600;
+ }
+ }
+
+ > section {
+ text-align: center;
+
+ > p {
+ margin-bottom: 1.25rem;
+ text-wrap: balance;
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+ }
+ }
+
+ > footer {
+ > nav {
+ display: flex;
+ flex-direction: row;
+ align-items: stretch;
+ gap: 1rem;
+
+ > a {
+ flex: 1 1 50%;
+ padding: 0.5rem 0.7rem;
+ border-radius: 0.2rem 0.5rem;
+
+ &[href]:not([aria-disabled="true"], [aria-current="page"]) {
+ transition-property:
+ background-color, text-decoration-thickness, text-decoration-color;
+
+ &:hover {
+ background-color: var(--secondary-color-half-light);
+ }
+ }
+
+ &[aria-current="page"] {
+ font-weight: 600;
+ background-color: var(--primary-color);
+ }
+ }
+ }
+ }
+}
diff --git a/snikket_web/static/img/tofu.svg b/snikket_web/static/img/tofu.svg
new file mode 100644
index 0000000..7652814
--- /dev/null
+++ b/snikket_web/static/img/tofu.svg
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+image/svg+xml Openclipart
diff --git a/snikket_web/templates/home.html b/snikket_web/templates/home.html
new file mode 100644
index 0000000..b97278f
--- /dev/null
+++ b/snikket_web/templates/home.html
@@ -0,0 +1,54 @@
+{% extends "base.html" %}
+
+{% block head_lead %}
+
{{ config["SITE_NAME"] }}
+{% endblock %}
+
+{% block style %}
+
+{% endblock %}
+
+{% block body %}
+
+
+ {% trans site_name=config["SITE_NAME"], logo_url=url_for("static", filename="img/tofu.svg") %}
+
+ {% endtrans %}
+ {{ config["SITE_NAME"] }}
+
+
+
+
+
+
+
+ {% trans site_name=config["SITE_NAME"], about_page=url_for('main.about') %}
+ {{ site_name }} is an XMPP (Jabber) server hosted by
+ Dave Jansen
+ using open-source software from the Snikket project .
+ {% endtrans %}
+
+ {%- if config["ADMIN_CONTACT"] -%}
+
+ {% trans admin_contact=config["ADMIN_CONTACT"] %}
+ To reach out, send a message to {{ admin_contact }} or
+ via email .
+ {% endtrans %}
+
+ {%- endif -%}
+
+
+
+
+
+{% endblock %}