Commit graph

93 commits

Author SHA1 Message Date
blankie
8679e0faca added Docker setup docs 2026-06-05 05:29:36 +00:00
blankie
176337344c squashed a bunch of workflow build bugs 2026-06-05 05:29:36 +00:00
blankie
3230bee0ce added bulk ops + orphaned tag cleanup
- Bulk delete and retag from browse page with checkboxes
- Select all / deselect all toggle
- Delete confirmation shows count of selected pages
- Auto-cleanup orphaned tags on delete, edit, and bulk actions
2026-06-05 05:29:36 +00:00
blankie
af3bbc33fd privacy pass: degoogle, CSP, referrer
- Replace Google Fonts with system font stacks across all themes
- Add Referrer-Policy, X-Content-Type-Options, X-Frame-Options, CSP headers
- Add rel="noreferrer noopener" on all outbound links
- Add no-referrer and dns-prefetch-control meta tags to all themes
- Clean tracking params on outbound links from trusted/remote sources
- Remove Google domains from CSP whitelists
2026-06-05 05:29:36 +00:00
blankie
b2db40f3d3 added kodama2 theme
Adds pagination, meta, and success message styles, plus input
selectors for new form fields (edit page, manual entry, transport node).
2026-06-05 05:29:36 +00:00
blankie
eabc86013a disabled semantic search by default 2026-06-05 05:29:36 +00:00
blankie
4e33ca8e88 added PyInstaller builds, AGPLv3, transport config
- Add pyinstaller.spec and GitHub/Forgejo CI workflows for cross-platform builds
- Add AGPLv3 license
- Move data storage to ~/.tinyweb/
- Add --version and --port CLI flags
- Add transport node selection in /style (smart regeneration preserves Reticulum config)
- Add discover more nodes link to rmap.world
2026-06-05 05:29:36 +00:00
blankie
ebe213f61a tightened up the add form spacing 2026-06-05 05:29:36 +00:00
blankie
9bdb68043b swapped to radio toggle for URL vs hash 2026-06-05 05:29:36 +00:00
blankie
def91353f5 added dropdown to switch add/subscribe 2026-06-05 05:29:36 +00:00
blankie
b3ff66fba9 added reticulum hash option to add page 2026-06-05 05:29:36 +00:00
blankie
b7433c6640 added manual URL entry 2026-06-05 05:29:35 +00:00
blankie
1c2266eaef made semantic search optional, use meta snippets
- Add semantic_search setting to toggle AI-powered search on/off
- Skip embedding generation, hybrid search, and model preloading when disabled
- Use site owner's meta description as snippet instead of heuristic extraction
- Remove _generate_summary() and snippet() - no more generated snippets
- Show reranker/reindex controls grayed out when semantic search is off
- AI dependencies (onnxruntime, hnswlib, etc.) are now fully optional
2026-06-05 05:29:35 +00:00
blankie
c521d0ceb6 improved snippet extraction (heuristic)
- Case-insensitive meta description extraction (fixes sites like Lemmy
  with capitalized "Description" meta name)
- Strip aside and noscript tags for cleaner body text
- Extract paragraph text separately for better sentence quality
- Prefer sentences mentioning the site name, then first quality
  paragraph, then title as fallback
- Skip meta descriptions under 20 chars (e.g. just "Lemmy")
- Remove embedding/centroid dependency from summary generation
2026-06-05 05:29:35 +00:00
blankie
bb94dc4cea stripped noscript tags from pages
Lemmy and other JS-heavy sites include noscript fallback text like
"Javascript is disabled" that pollutes the stored body text and
generated snippets/summaries.
2026-06-05 05:29:35 +00:00
blankie
b3d7fd80de fixed reindex, preserved summaries
Previously reindex skipped pages that already had chunks, leaving stale
embeddings in place. It also overwrote good meta description summaries
with auto-generated ones. Now it clears all chunks first so everything
is re-embedded, and only generates summaries for pages missing one.
2026-06-05 05:29:35 +00:00
blankie
c6ceefaa44 added junimo theme, bumped browse to 50 2026-06-05 05:29:35 +00:00
blankie
cc8f936488 added hybrid semantic search with reranking
Implements a three-stage search pipeline:
1. BM25 keyword search via FTS5 with column weights
2. Semantic search via Snowflake arctic-embed-s bi-encoder + HNSW index
3. Optional cross-encoder reranking (on by default, toggleable in settings)

Top 20 results are reranked for precision, next 10 appended from RRF
for coverage, giving 30 total results across 3 pages.

- New embeddings.py with ONNX Runtime inference, text chunking, HNSW
  index management, RRF fusion, and cross-encoder reranking
- Meta description extraction for authentic page snippets with centroid
  extractive fallback
- Stopword filtering in FTS5 queries to avoid overly strict matching
- /reindex page for batch embedding of existing pages
- Semantic embedding of remote pages during subscription sync
- ~125MB dependency footprint (onnxruntime, tokenizers, hnswlib, numpy)
- Models: 34MB bi-encoder + 22MB cross-encoder (downloaded on first use)
2026-06-05 05:29:35 +00:00
blankie
3b8bda1af5 fixed navbar disappearing on save
Browser textarea submissions convert \n to \r\n, causing the template
comparison against DEFAULT_TEMPLATE to always fail. This saved the bare
skeleton as a custom template, overriding the default navbar.
2026-06-05 05:29:35 +00:00
blankie
3452a770d9 redesigned subscriptions with card layout
Replace cramped table layout with card-based design that works
better in narrow viewports and across different themes.
2026-06-05 05:29:35 +00:00
blankie
275e223ce0 disabled share_instance for reliable announces
With share_instance = Yes, announces weren't being sent over TCP
in Docker environments. Setting it to No ensures each TinyWeb
instance manages its own Reticulum interfaces directly.
2026-06-05 05:29:35 +00:00
blankie
2e21a7deb5 added delay before announce for TCP readiness
The announce was firing before the TCP transport connection was fully
established, causing Docker instances to never announce over the mesh.
2026-06-05 05:29:35 +00:00
blankie
761c5e6dab added default transport node
New TinyWeb instances now auto-connect to rnode.bre.land:4242
so users get internet mesh connectivity out of the box without any
manual Reticulum configuration. Env var overrides still supported.
2026-06-05 05:29:35 +00:00
blankie
98a80695a0 added entrypoint for Reticulum in Docker
Replaces static CMD with an entrypoint that generates RNS config from
environment variables (RNS_TCP_HOST/PORT), enabling TCP transport for
environments without LAN auto-discovery (e.g. Docker on macOS).
2026-06-05 05:29:35 +00:00
blankie
d70933bff2 added Dockerfile + compose setup 2026-06-05 05:29:35 +00:00
blankie
3ea860347d enabled WAL mode, pooling, pagination
WAL + pooling:
- Enable WAL journal mode for concurrent read/write support
- Add connection pool (size 4) with return_db() to reuse connections
  instead of opening/closing on every request

Pagination:
- Search results, /pages, and /tags/<name> now paginate at 50 per page
- Prev/next navigation links appear when results exceed one page

Delta sync:
- Pages table gains last_modified timestamp, set on insert/update
- /api/sites accepts ?since= param to return only changed pages
- Subscription sync uses last_sync timestamp for incremental fetches
- Remote pages upserted instead of delete-all/re-insert
- Full sync includes all_urls list for detecting remote deletions
2026-06-05 05:29:35 +00:00
blankie
521e8a942d normalized URLs to prevent dupes
clean_url() now canonicalizes: http→https, strips www., removes
trailing slashes, drops default ports, and sorts query params.
Prevents the same page from being indexed multiple times under
different URL variations.
2026-06-05 05:29:35 +00:00
blankie
bc729076bb wrote README with setup + architecture 2026-06-05 05:29:35 +00:00
blankie
429ba8654e fixed index_url page_id mismatch
lastrowid returns 0 when ON CONFLICT DO UPDATE fires on an existing
row, causing links to not be cleaned up or associated correctly on
re-index. Now fetches the actual row ID with a SELECT after upsert.
Also adds try/finally for connection safety.
2026-06-05 05:29:35 +00:00
blankie
a9c6cdf94e fixed SSRF bypass, tightened error handling
- SSRF: disable automatic redirects, manually follow up to 5 hops with
  IP re-validation at each step to prevent redirect-to-localhost bypass
- Identity file: enforce 0600 permissions on tinyweb_identity at load
  and creation to prevent other users from reading the private key
- Error messages: replace raw exception strings with generic messages
  to avoid leaking internal paths/hostnames to the UI
- DB connections: wrap all get_db() usage in try/finally to guarantee
  close() even when handlers throw mid-operation
2026-06-05 05:29:35 +00:00
blankie
39f5e9c8a1 added bookmark auth, CSP, per-session CSRF
- Bookmark endpoint now requires a secret token (stored in settings)
- Style reset moved from GET to POST with CSRF protection
- Open redirect prevention in _redirect() helper
- Import capped at 100 URLs to prevent abuse
- page_tags cleaned up on delete + PRAGMA foreign_keys enabled
- CSP, X-Frame-Options, X-Content-Type-Options on all responses
- CSRF tokens now per-session via double-submit cookie pattern
- Tag names URL-decoded for special characters
- Gateway forwards cookies in request data
2026-06-05 05:29:35 +00:00
blankie
ff22d988cb hardened CSRF, SSRF, FTS5
- CSRF: Generate random token at startup, include as hidden field in
  all 11 POST forms, validate at top of POST dispatch (returns 403)
- SSRF: Block private/internal IP ranges (127/8, 10/8, 172.16/12,
  192.168/16, 169.254/16, ::1, fc00::/7) by resolving hostname before
  fetch. Remove verify=False from requests.get().
- DELETE: Change /delete/<id> from GET (instant delete) to GET
  (confirmation page) + POST (actual delete) to prevent accidental
  deletion from prefetchers/crawlers.
- FTS5: Wrap search input in double quotes to neutralize FTS5
  operators (AND, OR, NOT, *, column:). Add try/except fallback.
2026-06-05 05:29:35 +00:00
blankie
77b52b9809 created themes folder with kodama template
Save the custom kodama template to themes/kodama.html so it's
version-controlled as a file rather than only living in the database.
Stop tracking index.db since it's runtime data, not source code.
2026-06-05 05:29:35 +00:00
blankie
ad21648d5b added custom template editor, cleaned up UI
- Replace CSS-only customization with full HTML template editing
- Users edit the entire page wrapper with {{content}} placeholder
- Add /style?reset escape hatch to recover from broken templates
- Move nav links to template, remove redundant nav from search page
- Delete remote pages when unsubscribing from an instance
2026-06-05 05:29:35 +00:00
blankie
437584b09d fixed stale tag count on about page
Count tags from page_tags instead of the tags table, which retains
orphaned rows when tags are removed from pages.
2026-06-05 05:29:35 +00:00
blankie
b76731eb60 bound to 0.0.0.0 for remote access 2026-06-05 05:29:35 +00:00
blankie
1daf29af9a added an about page with slow-web pitch
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.
2026-06-05 05:29:35 +00:00
blankie
99a4e84ee1 stripped tracking params, added tags
URLs are cleaned of tracking parameters (utm_*, fbclid, gclid, etc.)
before indexing. Tags can be added when saving or editing pages,
browsed at /tags, and are included in search results. Tags are shared
via /api/sites and preserved when syncing/importing from subscriptions.
2026-06-05 05:29:35 +00:00
blankie
e545203a87 single-command startup
app.py now auto-starts the gateway HTTP server in a daemon thread,
so users only need `python app.py` to get everything running. The
gateway calls dispatch_request directly when co-located (local mode)
instead of trying to establish an RNS link to itself. Bookmarklet
hardcoded to localhost:8080. gateway.py still works standalone for
connecting to remote instances.
2026-06-05 05:29:35 +00:00
blankie
8ae26a5597 wired up mesh subscriptions + search
- Subscriptions now use Reticulum destination hashes instead of HTTP URLs
- All subscription syncing happens over encrypted RNS links (rns_client.py)
- Add remote_pages table for synced content from subscriptions
- Search results now include pages from synced subscriptions, grouped by source
- Remove HTTP dependency from subscription handlers
2026-06-05 05:29:35 +00:00
blankie
3e5cafb7f7 ported everything to Reticulum mesh
Replace HTTP server with Reticulum-native architecture. The server
now speaks only Reticulum, with a client-side gateway providing
browser access by translating HTTP to/from RNS requests.

- Extract db layer (db.py), templates (templates.py), handlers (handlers.py)
- app.py is now the RNS server with persistent identity and destination
- gateway.py bridges HTTP on localhost:8080 to RNS link requests
- Add rns dependency, add .gitignore
2026-06-05 05:29:35 +00:00
blankie
ecc48547d1 bound to 0.0.0.0, dynamic Host header
Makes the server accessible from other devices on the network
instead of only localhost. The bookmarklet now uses the Host header
from the request so it works regardless of how the server is accessed.
2026-06-05 05:29:35 +00:00
blankie
2c69a10f0e first commit 2026-06-05 05:22:37 +00:00