Getting Started
Prerequisites
| Tool | Version | Install |
|---|---|---|
| Rust | stable | rustup.rs |
| Docker + Compose plugin | 24+ | docs.docker.com |
| Node.js | 20+ | nodejs.org |
| sqlx-cli | latest | cargo install sqlx-cli --no-default-features --features postgres |
Option A — Docker Compose Recommended
Start the full stack with a single command. This option starts Postgres, NATS, MinIO, the API server, the worker, Grafana, Prometheus, and Tempo — all pre-configured and networked.
git clone https://github.com/VisionLab-de/VisionPush.git
cd VisionPush
# Start everything: Postgres, NATS, MinIO, API, Worker, Grafana, Prometheus, Tempo
docker compose -f infra/docker/docker-compose.yml up -d --build
# Admin panel (dev server with hot reload)
cd admin && npm install && npm start
Once running, the following services are available:
| Service | URL |
|---|---|
| Admin panel | http://localhost:4200 |
| API | http://localhost:8090 |
| API docs (Swagger UI) | http://localhost:8090/docs |
| Grafana | http://localhost:3001 (admin / admin) |
| Prometheus | http://localhost:9090 |
| Tempo (traces) | http://localhost:3200 |
| MinIO console | http://localhost:9001 |
| NATS monitoring | http://localhost:8222 |
Option B — Run Services Individually
Use this approach when you need finer control over each service, for example when working on a single crate without starting the full stack.
1. Start infrastructure
docker compose -f infra/docker/docker-compose.yml up -d postgres nats minio minio-init
2. Configure environment
cp .env.example .env
# Edit .env — minimum required:
# DATABASE_URL
# NATS_URL
# JWT_SECRET (openssl rand -base64 32)
# CREDENTIAL_ENCRYPTION_KEY (openssl rand -base64 32)
3. Run database migrations
sqlx migrate run --database-url postgres://visionpush:secret@localhost:5432/visionpush
4. Start the API
cargo run -p visionpush-api
# → http://localhost:8090
# → http://localhost:8090/docs (Swagger UI)
5. Start the worker
cargo run -p visionpush-worker
6. Start the admin panel
cd admin && npm install && npm start
# → http://localhost:4200
First Login
Open http://localhost:4200. On a fresh database the seed migration creates a default organization and admin user:
| Field | Value |
|---|---|
admin@example.com |
|
| Password | changeme |
Create Your First Push Notification
Register a device (from your mobile app)
Call this endpoint from the mobile SDK when the app starts or the push token refreshes. It upserts by push token, so it is safe to call on every app launch.
curl -X POST http://localhost:8090/v1/devices/register \
-H "Authorization: Bearer vp_live_..." \
-H "Content-Type: application/json" \
-d '{
"app_id": "<your-app-uuid>",
"push_token": "<fcm-or-apns-token>",
"platform": "android",
"external_id": "user-123"
}'
Send a push notification
curl -X POST http://localhost:8090/v1/push/send \
-H "Authorization: Bearer vp_live_..." \
-H "Content-Type: application/json" \
-d '{
"app_id": "<your-app-uuid>",
"name": "Hello world",
"contents": {
"en": { "title": "Hello!", "body": "This is your first push." }
}
}'
Running Tests
# Unit + integration tests (requires running Postgres)
DATABASE_URL=postgres://visionpush:secret@localhost:5432/visionpush_test \
cargo test --workspace --all-features
# Specific crate
cargo test -p visionpush-analytics
# Check + fmt + clippy (no running services needed, uses .sqlx offline cache)
cargo check --workspace --all-features
cargo fmt --all -- --check
cargo clippy --workspace --all-features -- -D warnings
Code Structure
VisionPush/
├── Cargo.toml — workspace manifest
├── crates/
│ ├── visionpush-api/ — REST API server
│ ├── visionpush-worker/ — background push processor
│ ├── visionpush-core/ — APNS / FCM / VAPID clients
│ ├── visionpush-analytics/ — Parquet + DataFusion
│ ├── visionpush-auth/ — OAuth 2.1 / OIDC 1.0
│ └── visionpush-storage/ — blob storage (fs + S3)
├── admin/ — Angular 18 admin panel
├── webseite/ — landing page
├── migrations/ — sqlx migrations (001…011)
├── infra/
│ ├── docker/ — Dockerfiles, Compose files
│ └── k8s/ — Helm chart, bootstrap scripts
└── docs/ — this documentation
Common Development Tasks
Add a new API endpoint
- Add route handler in
crates/visionpush-api/src/routes/<feature>.rs - Register in
crates/visionpush-api/src/routes/mod.rs - Add
utoipaannotations for OpenAPI generation - Write a sqlx query (run
cargo sqlx prepareto update.sqlx/cache)
pub struct Handler; impl Handler { ... } block — free-standing async functions are not acceptable.
Add a database migration
# Create migration file
sqlx migrate add --source migrations <description>
# Apply
sqlx migrate run --database-url $DATABASE_URL
# Update sqlx offline cache (required before committing)
cargo sqlx prepare --workspace
Regenerate OpenAPI spec
The spec is generated at runtime from utoipa annotations and served at
GET /docs/openapi.json. No build step is required — just restart the API server.
Load testing
# Start mock FCM endpoint first, then run the load test binary
NUM_BATCHES=100 DEVICES_PER_BATCH=500 RATE_MS=100 \
cargo run --release --bin loadtest
See the README — Load Testing section for full configuration options.