A Kestra-orchestrated developer alert platform that aggregates opportunities from multiple sources, filters them using LLM, and sends notifications via Telegram and Email.
┌─────────────────────────────────────────────────────────────────┐
│ DevAlert Architecture │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Frontend │ │ Kestra │ │ Telegram │ │
│ │ (React) │◄──►│ (Port 8080) │◄──►│ Bot API │ │
│ │ (Port 5173) │ │ │ │ │ │
│ └──────────────┘ └──────┬───────┘ └──────────────┘ │
│ │ │
│ ┌────────────────────┼────────────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Source 1 │ │ Source 2 │ │ Source N │ │
│ │ (GitHub) │ │ (MLH) │ │ (GSOC) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │ │
│ └────────────────────┼────────────────────┘ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ Aggregator │ │
│ └────────┬────────┘ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ LLM Filter │ │
│ │ (Scoring) │ │
│ └────────┬────────┘ │
│ ▼ │
│ ┌─────────────────┐ │
│ │ Notifier │ │
│ │ (Telegram/ │ │
│ │ Gmail) │ │
│ └─────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
- Docker and Docker Compose
- Node.js 18+ and npm
- Telegram Bot Token (get from @BotFather)
- (Optional) Gmail credentials for email notifications
-
Start Kestra:
docker compose up -d
-
Configure Secrets in Kestra UI (http://localhost:8080):
- Go to Settings > Secrets
- Add the following secrets:
TELEGRAM_BOT_TOKEN: Your Telegram bot tokenTELEGRAM_CHAT_ID: Your Telegram chat IDGMAIL_PASSWORD: Your Gmail app password (if using email)
-
Configure Environment Variables (optional):
GMAIL_USERNAME: Your Gmail addressGMAIL_TO: Recipient email address
-
Start Frontend:
cd frontend npm install npm run dev -
Access:
- Frontend: http://localhost:5173
- Kestra UI: http://localhost:8080
The main flow that coordinates all data fetching, filtering, and notifications.
Schedule: Every 6 hours (cron: 0 */6 * * *)
Tasks:
run_all_sources- Fetches data from all 6 sources in parallelaggregate_all_items- Combines all items into a single listfilter_items- Filters items based on scoring threshold (default: 40)route_notifications- Sends notifications if items pass filteringset_last_run- Records last execution timestamp
Error Handling: Logs failure details on any error
Individual source flows for modular data fetching:
| Flow | Description | Source URL |
|---|---|---|
source_github |
GitHub good-first-issue labels | api.github.com |
source_hackathons |
MLH hackathons | api.mlh.io |
source_gsoc |
Google Summer of Code RSS | opensource.googleblog.com |
source_coral |
Coral Project bounties | api.coralproject.net |
source_hn |
Hacker News jobs | hn.algolia.com |
source_wemakedevs |
WeMakeDevs opportunities | wemakedevs.org |
Each source flow:
- Has built-in fallback data when APIs are unavailable
- Returns standardized item format
- Includes error handling with logging
| Flow | Namespace | Description |
|---|---|---|
notify_telegram |
devalert.notify | Sends Telegram notifications |
notify_gmail |
devalert.notify | Sends email notifications |
The frontend communicates with Kestra via these API endpoints:
GET /api/v1/flows- List all flowsGET /api/v1/flows/{namespace}/{flowId}- Get flow detailsPOST /api/v1/executions/{namespace}/{flowId}- Trigger flow executionGET /api/v1/executions- List executionsGET /api/v1/executions/{executionId}- Get execution detailsGET /api/v1/executions/{executionId}/logs- Get execution logs
services:
kestra:
image: kestra/kestra:v0.22.43
ports:
- "8080:8080"
volumes:
- kestra-data:/app/storage
- ./kestra/flows:/app/flows
environment:
KESTRA_QUEUE_TYPE: memory
KESTRA_REPOSITORY_TYPE: memory
KESTRA_STORAGE_TYPE: localscore_threshold: Minimum score for items to pass filter (default: 40)
Store sensitive data in Kestra secrets:
TELEGRAM_BOT_TOKEN: Bot token from @BotFatherTELEGRAM_CHAT_ID: Target chat IDGMAIL_PASSWORD: App-specific password for Gmail
devalert/
├── docker-compose.yml # Kestra container setup
├── kestra-config.yml # Kestra configuration
├── kestra/
│ ├── flows/ # Flow YAML files
│ │ ├── 00_master_orchestrator.yml
│ │ ├── source_github.yml
│ │ ├── source_hackathons.yml
│ │ ├── source_gsoc.yml
│ │ ├── source_coral.yml
│ │ ├── source_hn.yml
│ │ ├── source_wemakedevs.yml
│ │ └── notify_telegram.yml
│ └── templates/ # Notification templates
├── frontend/ # React application
│ ├── src/
│ │ ├── components/ # UI components
│ │ ├── hooks/ # Custom React hooks
│ │ ├── utils/ # Utility functions
│ │ └── styles/ # CSS files
│ └── package.json
└── README.md
- Create a new flow file in
kestra/flows/source_<name>.yml - Follow the pattern of existing source flows
- Return items with these fields:
id: Unique identifiertitle: Item titlelink: URL to itemdate: Date stringdescription: Short descriptionsource_type: Type categorysource_name: Source display name
- Import the flow to Kestra
The filter_items task in master_orchestrator uses a simple scoring algorithm. To integrate with an actual LLM:
- Add LLM API credentials as secrets
- Modify the
filter_itemstask to call your LLM provider - Use the LLM response to score/filter items
-
401 Unauthorized on API calls
- Ensure Kestra is running properly
- Check that basic-auth is disabled in configuration
-
Telegram 401 error
- Verify bot token is correct
- Ensure bot has been started in the target chat
-
Network errors in source flows
- Source flows include fallback data for resilience
- Check container network connectivity
-
JSON parse errors
- Flows use proper try/except handling
- Fallback data ensures execution continues
View execution logs in Kestra UI:
- Go to the execution detail page
- Click on the task to see its logs
- Use the log viewer for debugging
MIT License