Development
Information for developers contributing to or building on NotifyHero/ntfy.
Architecture
NotifyHero is based on ntfy, which consists of:
- Server - Go binary that handles HTTP/WebSocket connections
- Web App - React SPA embedded in the server
- Android App - Kotlin native app
- iOS App - Swift native app
- CLI - Command-line interface (same binary as server)
Building from Source
Server
# Clone
git clone https://github.com/binwiederhier/ntfy.git
cd ntfy
# Build
make build
# Run
./ntfy serve
Web App
cd web
npm install
npm start # Development server
npm run build # Production build
Android App
- Open
android/in Android Studio - Build using Gradle
iOS App
- Open
ios/in Xcode - Build for your target device
API Development
Test Endpoints
# Health check
curl https://app.notifyhero.com/v1/health
# Send test message
curl -d "Test" https://app.notifyhero.com/test-topic
# Subscribe (JSON stream)
curl https://app.notifyhero.com/test-topic/json
Response Formats
All endpoints support multiple formats:
/topic/json- Newline-delimited JSON/topic/sse- Server-sent events/topic/raw- Plain text/topic/ws- WebSocket
Error Handling
Errors return JSON with structure:
{
"code": 40001,
"http": 400,
"error": "invalid request"
}
Contributing
Guidelines
- Fork the repository
- Create a feature branch
- Make your changes
- Write/update tests
- Submit a pull request
Code Style
- Go: Follow standard Go conventions
- JavaScript: ESLint configuration provided
- Commit messages: Conventional commits preferred
Testing
# Run tests
make test
# Run specific tests
go test ./server/...
Custom Integrations
Publishing
import requests
def notify(topic, message, **kwargs):
headers = {}
if 'title' in kwargs:
headers['Title'] = kwargs['title']
if 'priority' in kwargs:
headers['Priority'] = str(kwargs['priority'])
if 'tags' in kwargs:
headers['Tags'] = ','.join(kwargs['tags'])
response = requests.post(
f'https://app.notifyhero.com/{topic}',
data=message.encode('utf-8'),
headers=headers
)
return response.status_code == 200
Subscribing
import requests
import json
def subscribe(topic, callback):
response = requests.get(
f'https://app.notifyhero.com/{topic}/json',
stream=True
)
for line in response.iter_lines():
if line:
message = json.loads(line)
callback(message)