From 1900be4c0ec5e89831f0740fc465b0525f7d8c30 Mon Sep 17 00:00:00 2001 From: Dave Jansen Date: Mon, 7 Jul 2025 17:29:34 +0900 Subject: [PATCH] Add custom homepage template --- example.env | 5 +- snikket_web/__init__.py | 9 +- snikket_web/scss/home.scss | 194 ++++++++++++++++++++++++++++++++ snikket_web/static/img/tofu.svg | 52 +++++++++ snikket_web/templates/home.html | 54 +++++++++ 5 files changed, 310 insertions(+), 4 deletions(-) create mode 100644 snikket_web/scss/home.scss create mode 100644 snikket_web/static/img/tofu.svg create mode 100644 snikket_web/templates/home.html 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+xmlOpenclipart 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") %} + {{ site_name }} + {% 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 %}