The campaign donate flow opens HDSendBitcoinDialog with a prefilled bitcoin:bc1q…?sp=sp1… URI. BitcoinRecipientInput auto-opens its dropdown so the donor picks between the on-chain address and the silent-payment code — privacy vs. compatibility, the explicit choice the picker was designed around (92608f14). In practice the donor's eye lands on the amount presets first. Tapping $100 counts as an outside click, dismisses the popover, and leaves `recipient` null. The Send button is disabled (correctly — no destination resolved), the input still shows the prefilled URI, and nothing on screen tells the donor what's missing. They eventually discover that re-tapping the recipient input reopens the dropdown. Add a small amber hint with a warning icon directly beneath the recipient input whenever the input has parseable candidates but no selection AND the popover is closed. The whole hint is a button that reopens the popover and refocuses the input on tap, so the recovery takes one click instead of a guessing game. Gate the hint on a new `hasOpenedForQuery` flag that flips true the first time the popover opens for the current query and resets when the query clears. That keeps the hint from flashing for one paint frame between mount and the auto-open effect on prefilled inputs. Regression-of:92608f14
Agora
Power to the people.
Agora is a Nostr client focused on community ownership, expressive identity, and censorship resistance. This repository (agora-3) is the Agora-branded app built from the Ditto codebase.
What This Repo Is
- Agora product identity (name, theme, assets, native IDs)
- Ditto-derived implementation with broad Nostr feature coverage
- Configurable deployment defaults via
agora.json
Features
- Community-first social client: notes, articles, comments, reposts, reactions, and rich event rendering
- Theming system: built-in presets + custom color/font/background themes that can be shared as events
- Lightning support: zaps with Nostr Wallet Connect and WebLN
- Private messaging: NIP-04 and NIP-17 direct messages
- Mobile app shell: Capacitor-powered Android/iOS wrappers
- Self-hostable: static web build + configurable relay and upload infrastructure
Getting Started
Prerequisites
- Node.js 22+
- npm 10.9.4+
Development
git clone https://gitlab.com/soapbox-pub/agora-3.git
cd agora-3
npm install
npm run dev
Development server: http://localhost:8080
Docker Getting Started
Use Docker Compose when you want the nginx reverse-proxy stack (necessary if you want decryptable media in messages - kind 15s of NIP 17):
git clone https://gitlab.com/soapbox-pub/agora-3.git
cd agora-3
cp .env.example .env
docker compose up --build
Proxy URL: http://localhost:8083
This starts:
viteservice on the internal Docker network (vite:8080)webservice (nginx) on host port8082, proxying to Vite with websocket support
Stop stack:
docker compose down
Production-style container build:
docker compose -f docker-compose.prod.yml up --build
Build
npm run build
Build output: dist/
Validate
npm test
This runs type-checking, linting, unit tests, and production build checks.
Configuration
Build-time config is read from agora.json (gitignored by default so each deployment can provide its own values).
{
"theme": "dark",
"relayMetadata": {
"relays": [
{ "url": "wss://relay.ditto.pub", "read": true, "write": true },
{ "url": "wss://relay.primal.net", "read": true, "write": true },
{ "url": "wss://relay.damus.io", "read": true, "write": true }
]
},
"blossomServers": [
"https://blossom.ditto.pub",
"https://blossom.primal.net/"
]
}
Configuration priority (highest first):
- User settings (local storage)
- Build config (
agora.json) - Hardcoded app defaults
Use a custom config path:
CONFIG_FILE=./my-config.json npm run build
Deployment
Agora builds to static files and can be deployed to any static host.
- GitLab/GitHub Pages
- Netlify/Vercel
- VPS or any web server with SPA routing fallback
For Android:
npm run build
npx cap sync
npx cap open android
Tech Stack
| Layer | Technology |
|---|---|
| Framework | React 18 |
| Build | Vite |
| Language | TypeScript |
| Styling | TailwindCSS 3 + shadcn/ui |
| Routing | React Router |
| Data | TanStack Query |
| Nostr | Nostrify + nostr-tools |
| Mobile | Capacitor |
| Testing | Vitest + React Testing Library |
Contributing
Read CONTRIBUTING.md before opening a merge request.