From 175582914d17ff837a6a8529fdd72a994d6319b3 Mon Sep 17 00:00:00 2001
From: Derick Phan
Date: Wed, 25 Mar 2026 23:21:02 -0700
Subject: [PATCH] Add /about landing page with slow web philosophy
Shows instance stats, destination hash for subscribing, and explains
the slow web movement and how TinyWeb works. Destination hash is
stored in settings on startup so the about page can display it.
Co-Authored-By: Claude Opus 4.6
---
app.py | 3 ++-
handlers.py | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 58 insertions(+), 2 deletions(-)
diff --git a/app.py b/app.py
index 9233911..7d17007 100644
--- a/app.py
+++ b/app.py
@@ -4,7 +4,7 @@ import threading
import RNS
from http.server import HTTPServer
-from db import init_db
+from db import init_db, set_setting
from handlers import dispatch_request
from gateway import GatewayState, GatewayHandler, GATEWAY_PORT
@@ -55,6 +55,7 @@ def main():
)
destination.announce()
+ set_setting("dest_hash", destination.hash.hex())
start_gateway(reticulum)
print(f"TinyWeb running!")
diff --git a/handlers.py b/handlers.py
index 42944a5..2c0ec07 100644
--- a/handlers.py
+++ b/handlers.py
@@ -196,7 +196,8 @@ def handle_search(query):
f' | browse'
f' | tags'
f' | subscriptions'
- f' | customize
'
+ f' | customize'
+ f' | about'
f'
{result_html}{trusted_html}{remote_html}'
)
@@ -412,6 +413,58 @@ def handle_style_submit(body):
return handle_style_form("Saved.")
+def handle_about():
+ name = get_site_name()
+ dest_hash = get_setting("dest_hash")
+ sharing = get_setting("sharing_enabled", "0") == "1"
+ db = get_db()
+ page_count = db.execute("SELECT count(*) FROM pages").fetchone()[0]
+ tag_count = db.execute("SELECT count(*) FROM tags").fetchone()[0]
+ sub_count = db.execute("SELECT count(*) FROM subscriptions").fetchone()[0]
+ db.close()
+
+ sharing_html = (
+ 'This instance shares its index publicly. Subscribe to join the network.
'
+ if sharing else
+ 'This instance is private.
'
+ )
+
+ hash_html = ""
+ if dest_hash:
+ hash_html = (
+ f'subscribe
'
+ f'To subscribe to this instance, add this destination hash in your TinyWeb:
'
+ f'{esc(dest_hash)}'
+ )
+
+ return _respond(
+ f'{esc(name)}
'
+ f'A personal search engine, built for the slow web.
'
+ f'TinyWeb is about taking back the internet. No algorithms, no ads, no tracking. '
+ f'Just human-curated pages shared freely across a mesh network.
'
+ f''
+ f'- {page_count} page(s) indexed
'
+ f'- {tag_count} tag(s)
'
+ f'- {sub_count} subscription(s)
'
+ f'
'
+ f'{sharing_html}'
+ f'{hash_html}'
+ f'what is the slow web?
'
+ f'The slow web is a movement for intentionality over speed, '
+ f'human curation over algorithmic feeds, privacy over surveillance, '
+ f'and community over corporations. Every page in this index was saved by a person '
+ f'because they found it valuable — not because an algorithm told them to click.
'
+ f'how it works
'
+ f''
+ f'- Save pages you find valuable with the bookmarklet or /add
'
+ f'- Search your personal index — queries never leave your machine
'
+ f'- Subscribe to friends over Reticulum — encrypted, decentralized, works without the internet
'
+ f'- Tag and organize your collection into curated lists
'
+ f'
'
+ f'search | browse | tags
'
+ )
+
+
def handle_tags():
db = get_db()
rows = db.execute(
@@ -774,6 +827,8 @@ def dispatch_request(data):
return handle_bookmark(query)
elif path == "/style":
return handle_style_form()
+ elif path == "/about":
+ return handle_about()
elif path == "/export":
return handle_export()
elif path == "/import":