Skip to content

Commit 8545624

Browse files
Thomas StrombergThomas Stromberg
authored andcommitted
optimize README for audience
1 parent 19c59c2 commit 8545624

File tree

1 file changed

+16
-70
lines changed

1 file changed

+16
-70
lines changed

README.md

Lines changed: 16 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -6,94 +6,40 @@
66

77
Email notifications for ADVRider threads. Built for Cloud Run, written in Go.
88

9-
ADVRider's built-in notifications only email you once after your last visit to that thread. This keeps the party going by emailing every new post until you unsubscribe.
9+
ADVRider's built-in notifications only email you once after your last visit. This keeps the conversation going by emailing every new post until you unsubscribe.
1010

11-
## What it does
11+
## How it works
1212

13-
Subscribe to ADVRider forum threads and get emails when new posts appear. That's it.
13+
Subscribe to any ADVRider thread and get emails when new posts appear.
1414

15-
- Adaptive polling (5min to 4hr based on thread activity)
16-
- Multiple threads per email address
17-
- Handles login-required forums gracefully (reports 403, doesn't crash)
18-
- Exponential backoff with retry on transient failures
19-
- Local dev mode with mocked email
15+
**Respectful polling:** Adaptive intervals from 5 minutes (active threads) to 4 hours (quiet threads) using exponential backoff. Each thread is scraped once per cycle regardless of subscriber count, minimizing server load.
2016

21-
## Running it
17+
**User limits:** Maximum 20 threads per email address. Notifications batch up to 10 posts to prevent spam.
2218

23-
**Local (filesystem + mock email):**
24-
```bash
25-
go run .
26-
```
19+
**Security:** Rate limited to 5 requests/second per IP. Token-based subscription management. Thread verification before subscription. Email content sanitized to prevent XSS and phishing.
2720

28-
Visit http://localhost:8080 and subscribe to a thread.
21+
**Email quality:** Dark mode support, WCAG AA compliant, clickable post anchors linking directly to specific posts.
22+
23+
## Running locally
2924

30-
**Cloud Run (GCS + Brevo):**
3125
```bash
32-
export STORAGE_BUCKET=your-bucket-name
33-
export BASE_URL=https://your-service.run.app
34-
export BREVO_API_KEY=your-api-key
35-
ko apply -f service.yaml
26+
go run .
3627
```
3728

38-
Requires a service account with Cloud Storage access and a Brevo API key.
29+
Visit http://localhost:8080 and subscribe to a thread.
3930

4031
## Architecture
4132

4233
```
43-
/ Homepage (subscribe form)
44-
/subscribe POST: Create subscription (verifies thread exists first)
34+
/ Subscribe form
35+
/subscribe Create subscription (verifies thread exists)
4536
/manage?token=... View/delete subscriptions
46-
/pollz POST: Trigger immediate poll (no auth, rate limited by IP)
47-
```
48-
49-
Storage is either local filesystem (`./data`) or GCS (`STORAGE_BUCKET`).
50-
51-
Email via Brevo API. Auto-detects mock mode when `BREVO_API_KEY` is not set.
52-
53-
Each thread is scraped once per poll cycle regardless of subscriber count. Polling interval calculated per-thread using exponential backoff: `5min × 2^(hours_since_post / 3)`, capped at 4 hours.
54-
55-
## Security
56-
57-
- Rate limiting: 5 subscriptions/hour per IP
58-
- Token-based subscription management (64-char random, constant-time comparison)
59-
- Thread limit: 20 per user (prevents resource exhaustion)
60-
- Email limit: 10 posts per notification (prevents abuse)
61-
- CSP, X-Frame-Options, X-Content-Type-Options headers
62-
- Thread verification before subscription (validates URL is actually an ADVRider thread)
63-
64-
## Environment Variables
65-
66-
| Variable | Required | Description |
67-
|----------|----------|-------------|
68-
| `STORAGE_BUCKET` | Cloud only | GCS bucket for subscription data |
69-
| `BASE_URL` | Cloud only | Public URL (for manage links in emails) |
70-
| `BREVO_API_KEY` | Cloud only | Brevo API key for sending emails |
71-
| `SALT` | Required | Secret salt for token generation (set in GSM or env) |
72-
| `PORT` | Optional | HTTP port (default: 8080) |
73-
| `LOCAL_STORAGE` | Optional | Local storage path (default: ./data) |
74-
| `MAIL_FROM` | Optional | From email address (defaults to postmaster@domain) |
75-
| `MAIL_NAME` | Optional | From name (default: ADVRider Notifier) |
76-
77-
## Development
78-
79-
```bash
80-
make build # Build binary
81-
make test # Run tests
82-
make lint # golangci-lint
83-
make deploy # Deploy to Cloud Run via ko
37+
/pollz Trigger poll (rate limited)
8438
```
8539

86-
Tests use real ADVRider HTML parsing (no mocks for scraper). Exponential backoff algorithm is tested for correctness across all activity levels.
87-
88-
## Email Templates
89-
90-
Dark mode support via `prefers-color-scheme`. WCAG AA compliant. Post numbers are clickable anchors to specific posts on specific pages.
91-
92-
Footer links: "View thread" (goes to last page + last post anchor) and "Manage" (token-authenticated subscription management).
93-
94-
## Why Go?
40+
Storage: Local filesystem (`./data`) or GCS. Email via Brevo API (auto-mocks when `BREVO_API_KEY` not set).
9541

96-
Fast cold starts on Cloud Run, trivial deploys with ko, stdlib has everything we need. No npm, no containers, no Dockerfile.
42+
Polling interval: `5min × 2^(hours_since_post / 3)`, capped at 4 hours.
9743

9844
## License
9945

0 commit comments

Comments
 (0)