review-the-tcs

Rewrite the T&Cs

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

Repository layout

.
├── 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

Endpoints

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:


Backend setup

Environment variables

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://extensions with Developer mode on. For an unpacked dev build the ID is random per machine; pin it by adding a key to manifest.json, or just add both dev and prod IDs to ALLOWED_ORIGINS.

Run locally

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.


Deploying the backend

Any Node host works. The app reads PORT from the environment and needs the env vars above. Recommended zero-config options:

Railway

  1. Create a new project → Deploy from GitHub repo.
  2. Set the root directory to server/.
  3. Add the environment variables (CLAUDE_API_KEY, OPENAUSTRALIA_API_KEY, ALLOWED_ORIGINS).
  4. Railway detects Node and runs npm start. It injects PORT automatically.
  5. Copy the generated public URL (e.g. https://your-app.up.railway.app).

Render

  1. New → Web Service, connect the repo.
  2. Root Directory: serverBuild: npm installStart: npm start.
  3. Add the environment variables.
  4. Deploy and copy the https://your-app.onrender.com URL.

Fly.io

  1. cd server && fly launch (accept Node defaults; don’t deploy yet).
  2. fly secrets set CLAUDE_API_KEY=… OPENAUSTRALIA_API_KEY=… ALLOWED_ORIGINS=…
  3. fly deploy → copy the https://your-app.fly.dev URL.

After deploying

  1. Put the deployed URL in popup.js:
    const BACKEND_URL = "https://your-app.up.railway.app";
    
  2. Put the same URL (with /*) in manifest.jsonhost_permissions:
    "host_permissions": ["https://your-app.up.railway.app/*"]
    
  3. Set ALLOWED_ORIGINS on the host to your extension’s chrome-extension://<id> origin.

Loading the extension

  1. Go to chrome://extensions, enable Developer mode.
  2. Load unpacked → select this project’s root folder.
  3. Right-click any link to a T&C page → Review the T&Cs.

Security notes