···2233_Write in the margins of the web_
4455-A web comments layer built on [AT Protocol](https://atproto.com) that lets you annotate any URL on the internet.
55+A web annotation layer built on [AT Protocol](https://atproto.com) that lets you annotate, highlight, and bookmark any URL on the internet.
6677## Project Structure
88···1313│ ├── annotation.json
1414│ ├── bookmark.json
1515│ ├── collection.json
1616-│ └── collectionItem.json
1717-│ └── highlight.json
1818-│ └── like.json
1919-│ └── reply.json
1616+│ ├── collectionItem.json
1717+│ ├── highlight.json
1818+│ ├── like.json
1919+│ ├── reply.json
2020+│ ├── apikey.json
2121+│ ├── preferences.json
2222+│ └── profile.json
2023├── backend/ # Go API server
2124│ ├── cmd/server/
2225│ └── internal/
2323-├── web/ # React web app
2626+├── web/ # Astro SSR + React web app
2427│ └── src/
2525-└── extension/ # Browser extension
2626- ├── popup/
2727- ├── content/
2828- └── background/
2828+├── extension/ # Browser extension (WXT)
2929+│ └── src/
3030+└── avatar/ # Cloudflare Worker for avatar proxying
2931```
30323133## Getting Started
32343333-### Backend
3535+### Docker (Recommended)
3636+3737+Run the full stack with Docker:
34383539```bash
3636-cd backend
3737-go mod tidy
3838-go run ./cmd/server
4040+docker compose up -d --build
3941```
40424141-Server runs on http://localhost:8080
4343+This builds both the Go backend and the Astro frontend into a single container. The Astro SSR server handles all frontend routing, static assets, and OG image generation, while the Go backend serves the API internally.
42444343-### Docker (Recommended)
4545+### Development
44464545-Run the full stack (Backend + Postgres) with Docker:
4747+#### Backend
46484749```bash
4848-docker compose up -d --build
5050+cd backend
5151+go mod tidy
5252+go run ./cmd/server
4953```
50545151-### Web App
5555+API server runs on http://localhost:8081
5656+5757+#### Web App
52585359```bash
5460cd web
···5662npm run dev
5763```
58645959-App runs on http://localhost:3000
6565+Dev server runs on http://localhost:4321 and proxies API requests to the backend.
60666161-### Browser Extension
6767+#### Browser Extension
62686363-#### Chrome
6969+Built with [WXT](https://wxt.dev):
64706565-1. Open Chrome → `chrome://extensions`
6666-2. Enable "Developer mode"
6767-3. Click "Load unpacked"
6868-4. Select the `extension/` folder
7171+```bash
7272+cd extension
7373+npm install
7474+npm run dev # Chrome dev mode
7575+npm run dev:firefox # Firefox dev mode
7676+```
7777+7878+## Architecture
69797070-#### Firefox
8080+In production, a single Docker container runs both services:
71817272-1. Open Firefox → `about:debugging`
7373-2. Click "This Firefox"
7474-3. Click "Load Temporary Add-on"
7575-4. Select the `manifest.firefox.json` file in the `extension/` folder
8282+- **Astro SSR** (port 8080, public) — serves the web app, handles SSR for OG meta tags, generates dynamic OG images via satori, and proxies API/auth requests to the backend.
8383+- **Go API** (port 8081, internal) — handles all API endpoints, OAuth, firehose ingestion, and data storage.
76847785## Domain
78867979-**Domain**: `margin.at`
8787+**Domain**: `margin.at`
8088**Lexicon Namespace**: `at.margin.*`
81898290## Tech Stack
83918484-- **Backend**: Go + Chi + SQLite / PostgreSQL
8585-- **Frontend**: React 18 + Vite
8686-- **Extension**: Manifest v3
9292+- **Backend**: Go + Chi + SQLite
9393+- **Frontend**: Astro 5 (SSR) + React 19 + Tailwind CSS
9494+- **OG Images**: satori + @resvg/resvg-js
9595+- **Extension**: WXT + React + Tailwind CSS
8796- **Protocol**: AT Protocol (Bluesky)
88978998## License