WebEcho is a lightweight Chrome extension for leaving templated messages on web pages.
Install from Chrome Web Store:
https://chromewebstore.google.com/detail/webecho/poegnlaodjbcmclencdgnphpnbghicfo
It takes the familiar "shared notes on the world" idea and applies it to the web:
- messages are created from preset templates instead of free-form text
- messages are anchored to a point on the page and move with the page as you scroll
- reactions are emoji-based and counted individually
- the extension can fetch messages from multiple servers at once
- templates, UI language, and panel theme are configurable
- the backend is written in Rust and stores data through KiteSQL ORM
The current version is intentionally small, but already usable.
- Chrome Manifest V3 extension
- Right-click to leave a message at a page position
- Template picker with search
- Slot picker with search
- Local template configuration in TOML
- Chinese and English UI
- Template i18n following the selected language
- Multi-server message fetching with random selection under a page limit
- Per-emoji reactions with one reaction per user
- Page-level enable / disable from the context menu
- Theme switching from the extension settings
- Anonymous device identity based on a locally generated key pair
- Rust backend with rate limiting, request logging, and a small admin dashboard
.
├── extension/ Chrome extension
├── server/ Rust backend
├── dist/ Packaged builds
└── Makefile
Run the schema migration explicitly first:
make migrateIf you want a backup before the migration and backups are enabled in server/config.toml:
make migrate-backupThen start the server:
make runBy default the server listens on:
http://127.0.0.1:8787
Open:
chrome://extensions/
Then:
- Enable Developer mode
- Click
Load unpacked - Select the
extension/directory
- Open a normal web page
- Click the WebEcho toolbar icon to open the popup
- Open settings if you want to change theme, language, server list, or visible count
- Right-click anywhere on the page
- Choose the WebEcho context menu entry
- Pick a template and its slot values
- Publish the message
If you want to build a shareable demo package with a baked-in default server list:
make package-extension SERVER_URLS='https://echo.example.com'This creates:
dist/webecho-extension-v<version>/
dist/webecho-extension-v<version>.zip
dist/webecho-extension-v<version>.crx
dist/webecho-extension.pem
If you do not pass SERVER_URLS, the packaged extension keeps the default value from extension/default-config.json.
Notes:
- the unpacked directory is the most reliable option for demo sharing
.zipis convenient for sending to friends, who can unzip and load it unpacked.crxis also generated when Chrome or Chromium is available locally.pemkeeps the extension ID stable across future.crxbuilds
To install it on another machine:
- Send the directory or zip to your friend
- Unzip it if needed
- Open
chrome://extensions/ - Enable Developer mode
- Click
Load unpacked - Select
dist/webecho-extension-v0.1.0/
If you want to try the .crx, keep in mind that Chrome may restrict self-hosted .crx installation depending on platform and browser policy.
The default server list is stored in:
extension/default-config.json
Current default:
{
"serverUrls": ["http://127.0.0.1:8787"]
}The backend config is stored in:
server/config.toml
It currently covers:
- bind address
- database path
- template path
- logging
- admin access
- storage privacy secret
- rate limiting
Templates are defined in:
server/templates.toml
Templates support:
- localized labels
- searchable template names
- slot-based phrase composition
- optional ending emoji
Message text is not randomly generated on page load. What is random is the selection of which stored messages are fetched and rendered from the backend.
The backend exposes a minimal admin page for observing anonymous behavior data.
Default URL:
http://127.0.0.1:8787/admin?token=web-echo-admin
The admin token comes from server/config.toml:
[admin]
enabled = true
access_token = "web-echo-admin"The at-rest privacy secret also comes from server/config.toml:
[privacy]
storage_secret = "change-me-storage-secret"Change it before using WebEcho outside local demo environments.
The dashboard currently shows:
- total anonymous users
- total messages
- total reactions
- total tracked behavior events
- recent activity
- top pages
- top templates
WebEcho is designed to stay fairly lightweight:
- users do not create traditional accounts
- the extension generates a local key pair and uses it as anonymous identity
- messages are constrained by templates rather than arbitrary text input
- page URLs and message payloads are encrypted before being written to the database
- page matching uses a stable derived lookup key instead of storing raw page URLs in queryable form
- passive page loads are no longer persisted as behavior analytics events
- analytics do not persist raw IPs in the behavior event table
- rate limiting still uses IPs in memory on the server side
This is still a demo project, so if you plan to run it publicly, you should review the privacy model and service terms yourself before wider release.
- Rust
- Axum
- KiteSQL ORM
- RocksDB via KiteSQL storage
- Chrome Extension Manifest V3
make run
make stop
make restart
make status
make check
make fmt
make package-extension SERVER_URLS='https://echo.example.com'WebEcho uses KiteSQL ORM to keep the backend small and direct:
- simple model definitions
- lightweight local storage flow
- enough structure for messages, sessions, reactions, and behavior events
That fits this project well: a small Rust service with a compact data model and minimal ceremony.
WebEcho is already in a solid demo state:
- the extension can be loaded and used locally
- the server can be started with one command
- templates are editable
- reactions, i18n, theming, multi-server fetching, and admin analytics are in place
It is not yet intended as a polished public production deployment.
See LICENSE.