Thank you for your interest in contributing to World Monitor! This project thrives on community contributions — whether it's code, data sources, documentation, or bug reports.
- Architecture Overview
- Getting Started
- Development Setup
- How to Contribute
- Pull Request Process
- AI-Assisted Development
- Coding Standards
- Working with Sebuf (RPC Framework)
- Adding Data Sources
- Adding RSS Feeds
- Reporting Bugs
- Feature Requests
- Code of Conduct
World Monitor is a real-time OSINT dashboard built with Vanilla TypeScript (no UI framework), MapLibre GL + deck.gl for map rendering, and a custom Proto-first RPC framework called Sebuf for all API communication.
| Technology | Purpose |
|---|---|
| TypeScript | All code — frontend, edge functions, and handlers |
| Vite | Build tool and dev server |
| Sebuf | Proto-first HTTP RPC framework for typed API contracts |
| Protobuf / Buf | Service and message definitions across 17 domains |
| MapLibre GL | Base map rendering (tiles, globe mode, camera) |
| deck.gl | WebGL overlay layers (scatterplot, geojson, arcs, heatmaps) |
| d3 | Charts, sparklines, and data visualization |
| Vercel Edge Functions | Serverless API gateway |
| Tauri v2 | Desktop app (Windows, macOS, Linux) |
| Convex | Minimal backend (beta interest registration only) |
| Playwright | End-to-end and visual regression testing |
The codebase produces three app variants from the same source, each targeting a different audience:
| Variant | Command | Focus |
|---|---|---|
full |
npm run dev |
Geopolitics, military, conflicts, infrastructure |
tech |
npm run dev:tech |
Startups, AI/ML, cloud, cybersecurity |
finance |
npm run dev:finance |
Markets, trading, central banks, commodities |
Variants share all code but differ in default panels, map layers, and RSS feeds. Variant configs live in src/config/variants/.
| Directory | Purpose |
|---|---|
src/components/ |
UI components — Panel subclasses, map, modals (~50 panels) |
src/services/ |
Data fetching modules — sebuf client wrappers, AI, signal analysis |
src/config/ |
Static data and variant configs (feeds, geo, military, pipelines, ports) |
src/generated/ |
Auto-generated sebuf client + server stubs (do not edit by hand) |
src/types/ |
TypeScript type definitions |
src/locales/ |
i18n JSON files (14 languages) |
src/workers/ |
Web Workers for analysis |
server/ |
Sebuf handler implementations for all 17 domain services |
api/ |
Vercel Edge Functions (sebuf gateway + legacy endpoints) |
proto/ |
Protobuf service and message definitions |
data/ |
Static JSON datasets |
docs/ |
Documentation + generated OpenAPI specs |
src-tauri/ |
Tauri v2 Rust app + Node.js sidecar for desktop builds |
e2e/ |
Playwright end-to-end tests |
scripts/ |
Build and packaging scripts |
- Fork the repository on GitHub
- Clone your fork locally:
git clone https://github.com/<your-username>/worldmonitor.git cd worldmonitor
- Create a branch for your work:
git checkout -b feature/your-feature-name
# Install everything (buf CLI, sebuf plugins, npm deps, Playwright browsers)
make install
# Start the development server (full variant, default)
npm run dev
# Start other variants
npm run dev:tech
npm run dev:finance
# Run type checking
npm run typecheck
# Run tests
npm run test:data # Data integrity tests
npm run test:e2e # Playwright end-to-end tests
# Production build (per variant)
npm run build # full
npm run build:tech
npm run build:financeThe dev server runs at http://localhost:3000. Run make help to see all available make targets.
For full functionality, copy .env.example to .env.local and fill in the API keys you need. The app runs without any API keys — external data sources will simply be unavailable.
See API Dependencies for the full list.
- Bug fixes — found something broken? Fix it!
- New data layers — add new geospatial data sources to the map
- RSS feeds — expand our 100+ feed collection with quality sources
- UI/UX improvements — make the dashboard more intuitive
- Performance optimizations — faster loading, better caching
- Documentation — improve docs, add examples, fix typos
- Accessibility — make the dashboard usable by everyone
- Internationalization — help make World Monitor available in more languages
- Tests — add unit or integration tests
- New data layers (see Adding Data Sources)
- Feed quality improvements and new RSS sources
- Mobile responsiveness improvements
- Performance optimizations for the map rendering pipeline
- Better anomaly detection algorithms
- Update documentation if your change affects the public API or user-facing behavior
- Run type checking before submitting:
npm run typecheck - Test your changes locally with at least the
fullvariant, and any other variant your change affects - Keep PRs focused — one feature or fix per pull request
- Write a clear description explaining what your PR does and why
- Link related issues if applicable
Use a descriptive title that summarizes the change:
feat: add earthquake magnitude filtering to map layerfix: resolve RSS feed timeout for Al Jazeeradocs: update API dependencies sectionperf: optimize marker clustering at low zoom levelsrefactor: extract threat classifier into separate module
- All PRs require review from a maintainer before merging
- Maintainers may request changes — this is normal and collaborative
- Once approved, a maintainer will merge your PR
We fully embrace AI-assisted development. Many of our own PRs are labeled with the LLM that helped produce them (e.g., claude, codex, cursor), and contributors are welcome to use any AI tools they find helpful.
That said, all code is held to the same quality bar regardless of how it was written. AI-generated code will be reviewed with the same scrutiny as human-written code. Contributors are responsible for understanding and being able to explain every line they submit. Blindly pasting LLM output without review is discouraged — treat AI as a collaborator, not a replacement for your own judgement.
- Use TypeScript for all new code
- Avoid
anytypes — use proper typing orunknownwith type guards - Export interfaces/types for public APIs
- Use meaningful variable and function names
- Follow the existing code style in the repository
- Use
constby default,letwhen reassignment is needed - Prefer functional patterns (map, filter, reduce) over imperative loops
- Keep functions focused — one responsibility per function
- Add JSDoc comments for exported functions and complex logic
- Static layer/geo data and variant configs go in
src/config/ - Sebuf handler implementations go in
server/worldmonitor/{domain}/v1/ - Edge function gateway and legacy endpoints go in
api/ - UI components (panels, map, modals) go in
src/components/ - Service modules (data fetching, client wrappers) go in
src/services/ - Proto definitions go in
proto/worldmonitor/{domain}/v1/
Sebuf is the project's custom Proto-first HTTP RPC framework — a lightweight alternative to gRPC-Web. All API communication between client and server uses Sebuf.
- Proto definitions in
proto/worldmonitor/{domain}/v1/define services and messages - Code generation (
make generate) produces:- TypeScript clients in
src/generated/client/(e.g.,MarketServiceClient) - Server route factories in
src/generated/server/(e.g.,createMarketServiceRoutes)
- TypeScript clients in
- Handlers in
server/worldmonitor/{domain}/v1/handler.tsimplement the service interface - Gateway in
api/[domain]/v1/[rpc].tsregisters all handlers and routes requests - Clients in
src/services/{domain}/index.tswrap the generated client for app use
- Add the method to the
.protoservice definition - Run
make generateto regenerate client/server stubs - Implement the handler method in the domain's
handler.ts - The client stub is auto-generated — use it from
src/services/{domain}/
Use make lint to lint proto files and make breaking to check for breaking changes against main.
- Time fields: Use
int64(Unix epoch milliseconds), notgoogle.protobuf.Timestamp - int64 encoding: Apply
[(sebuf.http.int64_encoding) = INT64_ENCODING_NUMBER]on time fields so TypeScript receivesnumberinstead ofstring - HTTP annotations: Every RPC method needs
option (sebuf.http.config) = { path: "...", method: POST }
Run make install to install everything automatically, or install individually:
make install-buf # Install buf CLI (requires Go)
make install-plugins # Install sebuf protoc-gen plugins (requires Go)To add a new data layer to the map:
- Define the data source — identify the API or dataset you want to integrate
- Add the proto service (if the data needs a backend proxy) — define messages and RPC methods in
proto/worldmonitor/{domain}/v1/ - Generate stubs — run
make generate - Implement the handler in
server/worldmonitor/{domain}/v1/ - Register the handler in
api/[domain]/v1/[rpc].tsandvite.config.ts(for local dev) - Create the service module in
src/services/{domain}/wrapping the generated client - Add the layer config and implement the map renderer following existing layer patterns
- Add to layer toggles — make it toggleable in the UI
- Document the source — add it to
docs/DOCUMENTATION.md
For endpoints that deal with non-JSON payloads (XML feeds, binary data, HTML embeds), you can add a standalone Edge Function in api/ instead of Sebuf. For anything returning JSON, prefer Sebuf — the typed contracts are always worth it.
- Must be freely accessible (no paid-only APIs for core functionality)
- Must have a permissive license or be public government data
- Should update at least daily for real-time relevance
- Must include geographic coordinates or be geo-locatable
To add new RSS feeds:
- Verify the feed is reliable and actively maintained
- Assign a source tier (1-4) based on editorial reliability
- Flag any state affiliation or propaganda risk
- Categorize the feed (geopolitics, defense, energy, tech, etc.)
- Test that the feed parses correctly through the RSS proxy
When filing a bug report, please include:
- Description — clear description of the issue
- Steps to reproduce — how to trigger the bug
- Expected behavior — what should happen
- Actual behavior — what actually happens
- Screenshots — if applicable
- Browser/OS — your environment details
- Console errors — any relevant browser console output
Use the Bug Report issue template when available.
We welcome feature ideas! When suggesting a feature:
- Describe the problem it solves
- Propose a solution with as much detail as possible
- Consider alternatives you've thought about
- Provide context — who would benefit from this feature?
Use the Feature Request issue template when available.
This project follows the Contributor Covenant Code of Conduct. By participating, you are expected to uphold this code. Please report unacceptable behavior through GitHub issues or by contacting the repository owner.
Thank you for helping make World Monitor better! 🌍