A Chrome extension that analyses a terms & conditions page, summarises the risks in plain English, and helps you write to your federal MP about them.
The extension talks only to a small backend proxy. The backend holds the Claude and OpenAustralia API keys server-side, so no secrets ship with the extension — safe for public distribution.
Chrome extension ──► Backend proxy ──► Claude API
(popup.js) (server/server.js) OpenAustralia API
.
├── manifest.json Extension manifest (MV3)
├── popup.html / popup.js / styles.css Extension UI + logic
├── background.js Service worker: context menu → open popup
└── server/ Backend proxy (deploy this separately)
├── server.js
├── electorates.js Postcode → federal electorate table
├── package.json
└── .env.example
The backend exposes three endpoints (plus GET /health):
| Method | Path | Request | Response |
|---|---|---|---|
| POST | /analyse |
{ "url": "https://…" } |
analysis JSON { company, summary, risks[] } |
| POST | /letter |
{ "analysis": {…}, "mp": {…} } |
{ "letter": "…" } |
| GET | /mp-lookup |
?postcode=3000 |
{ name, electorate, email } |
Protections:
ALLOWED_ORIGINS (your extension ID) may call it.Copy server/.env.example to server/.env and fill in real values:
| Variable | Required | Description |
|---|---|---|
CLAUDE_API_KEY |
✅ | Anthropic key from https://console.anthropic.com/ |
OPENAUSTRALIA_API_KEY |
✅ | Key from https://www.openaustralia.org.au/api/key |
ALLOWED_ORIGINS |
✅ | Comma-separated allowed origins, e.g. chrome-extension://<your-extension-id> |
PORT |
❌ | Defaults to 3000 (most hosts inject their own) |
CLAUDE_MODEL |
❌ | Defaults to claude-sonnet-4-6 |
RATE_LIMIT_WINDOW_MS |
❌ | Rate-limit window in ms (default 900000 = 15 min) |
RATE_LIMIT_MAX |
❌ | Max requests/IP/window overall (default 60) |
CLAUDE_RATE_LIMIT_MAX |
❌ | Max requests/IP/window to /analyse + /letter (default 20) |
Find your extension ID at
chrome://extensionswith Developer mode on. For an unpacked dev build the ID is random per machine; pin it by adding akeytomanifest.json, or just add both dev and prod IDs toALLOWED_ORIGINS.
cd server
cp .env.example .env # then edit .env with your keys
npm install
npm run dev # or: npm start
The server listens on http://localhost:3000. Quick check:
curl http://localhost:3000/health # → {"ok":true}
curl "http://localhost:3000/mp-lookup?postcode=3000"
To point the extension at your local server, edit popup.js:
// const BACKEND_URL = "https://your-api.yourdomain.com";
const BACKEND_URL = "http://localhost:3000";
…and add http://localhost:3000/* to host_permissions in manifest.json
while developing.
Any Node host works. The app reads PORT from the environment and needs the
env vars above. Recommended zero-config options:
server/.CLAUDE_API_KEY, OPENAUSTRALIA_API_KEY,
ALLOWED_ORIGINS).npm start. It injects PORT automatically.https://your-app.up.railway.app).server • Build: npm install • Start: npm start.https://your-app.onrender.com URL.cd server && fly launch (accept Node defaults; don’t deploy yet).fly secrets set CLAUDE_API_KEY=… OPENAUSTRALIA_API_KEY=… ALLOWED_ORIGINS=…fly deploy → copy the https://your-app.fly.dev URL.popup.js:
const BACKEND_URL = "https://your-app.up.railway.app";
/*) in manifest.json → host_permissions:
"host_permissions": ["https://your-app.up.railway.app/*"]
ALLOWED_ORIGINS on the host to your extension’s
chrome-extension://<id> origin.chrome://extensions, enable Developer mode.server/.env..env and config.js are git-ignored.config.js held real keys. Even though it was never committed, if
those keys were ever used in a shared/distributed build, rotate them:
regenerate the Claude key in the Anthropic console and request a fresh
OpenAustralia key.