A location-based weather monitoring and alerting platform. You register the coordinates you care about — a field, a depot yard, an event site — define threshold rules, and the system watches them for you.
Instead of just displaying the current weather, it collects readings on a schedule, stores them as a time series, and evaluates user-defined rules against them. When a rule fires, an alert is recorded and pushed to your dashboard in real time.
What it does
- Pulls weather readings from Open-Meteo every 15 minutes for each active location
- Stores readings as a time series and charts them over 24 hours, 3 days or 7 days
- Evaluates rules on every new reading — simple thresholds or composite conditions chained with AND / OR
- Prevents alert fatigue with hysteresis: an alert fires once and stays quiet until the value falls back past a reset threshold
- Supports time-window conditions such as "maximum wind speed over the last 3 hours"
- Scans the forecast every 6 hours and raises proactive warnings for frost, storms and heavy rainfall
- Shows a 3-day forecast per location and plots every location on a map
- Delivers alerts over WebSocket to the dashboard, plus browser, email and SMS channels
Only two of the four channels work out of the box. This is deliberate, not a bug.
| Channel | Works by default | Why |
|---|---|---|
| Dashboard (WebSocket) | Yes | No configuration needed |
| Browser notification | Yes | Just grant permission in Settings |
| No | Requires your own SMTP credentials | |
| SMS | No | Requires a paid Twilio account |
Email is disabled by default and the SMTP values in application.properties are placeholders. Turning it on requires all four of these:
EMAIL_ENABLED=true- Real
MAIL_USERNAMEandMAIL_PASSWORD - The rule has
EMAILselected under notification channels - Email is toggled on in Settings
If you use Gmail, your normal password will not work — you need an app password, which requires two-factor authentication to be enabled first.
The backend tells you where you stand on startup:
EMAIL IS OFF. Set EMAIL_ENABLED=true to turn it on.
EMAIL IS ON but SMTP credentials are still placeholders.
Email channel ready, sending from [email protected]
You can also test it without waiting for a rule to fire:
GET /api/diagnostics/notifications status of each channel
POST /api/diagnostics/test-email sends a test mail to your own address
The Twilio integration is written and wired up, but it is switched off and the credentials are dummy values. It needs a real Twilio account to do anything.
Worth knowing before you sign up: Twilio charges roughly $0.03 per SMS to Turkish networks plus a monthly fee for the sending number. Trial accounts can only message verified numbers, cap out at 50 messages a day, and prefix every message with "Sent from a Twilio Trial account". Current Twilio documentation also states that trial accounts must use pre-approved message templates rather than custom message bodies — which does not fit this project's dynamic alert text.
If you do have an account, set the environment variables listed below and flip notification.sms-enabled to true. Nothing else needs to change.
Both channels fail safely. If email or SMS is enabled but misconfigured, the application logs a warning, skips that channel, and carries on. The dashboard and browser notifications keep working.
Backend
| Language | Java 21 |
| Framework | Spring Boot 3.3.4 |
| Persistence | Spring Data JPA, Hibernate |
| Database | PostgreSQL 14+ |
| Security | Spring Security, JWT (access + refresh tokens) |
| Real time | WebSocket over STOMP |
| Weather data | Open-Meteo API |
| Spring Mail (JavaMailSender) | |
| SMS | Twilio SDK 12.1.1 |
| Docs | springdoc-openapi (Swagger UI) |
| Build | Maven |
Frontend
| Framework | Next.js 15 (App Router) |
| UI | React 19 |
| Styling | SCSS Modules |
| Charts | Recharts 3 |
| Maps | Leaflet, react-leaflet 5 |
| Real time | @stomp/stompjs, sockjs-client |
| Tool | Version |
|---|---|
| Java | 21+ |
| Maven | 3.8+ |
| PostgreSQL | 14+ |
| Node.js | 18.18+ |
Maven must run on Java 21.
CREATE DATABASE mikroiklim;
cd mikro-iklim-backend
mvn clean install
mvn spring-boot:runWait for Started MikroIklimApplication in the console. Leave this terminal running.
Verify: http://localhost:8080/swagger-ui.html
In a second terminal:
cd mikro-iklim-frontend
npm install
cp .env.local.example .env.local
npm run dev- Sign up. You land on the login page — follow the "Sign up" link.
- Add a location. Go to Locations. Either click Pick on map and click a point, or enter coordinates by hand.
- Force a data pull. Cards will say "No readings collected for this location yet" — the collector runs every 15 minutes and you just added the location. Restarting the backend triggers a collection 30 seconds after startup, which is the quickest way to see data.
- Create a rule. Go to Rules and start from one of the three templates: frost risk, storm warning, heavy rainfall.
- Trigger an alert. Rather than waiting for real weather, create a rule that is always true — temperature greater than -50 °C, severity INFO — then force another data pull. The alert appears on the dashboard and the bell counter increments.
None are required for local development — every one falls back to a safe default. Set them when you want a channel to actually work, or before deploying anywhere real.
| Variable | Default | Purpose |
|---|---|---|
DB_USERNAME |
postgres |
Database user |
DB_PASSWORD |
postgres |
Database password |
JWT_SECRET |
placeholder | Token signing key — change this before deploying |
EMAIL_ENABLED |
false |
Turns the email channel on |
MAIL_USERNAME |
placeholder | SMTP user, also used as the From address |
MAIL_PASSWORD |
placeholder | SMTP password or app password |
TWILIO_ACCOUNT_SID |
dummy | Twilio account SID |
TWILIO_AUTH_TOKEN |
dummy | Twilio auth token |
TWILIO_FROM_NUMBER |
Twilio test number | Sending number |
No real credentials are committed to this repository.
Micro-Climate/
├── mikro-iklim-backend/
│ └── src/main/java/com/microiklim/
│ ├── entity/ 7 entities, 6 enums
│ ├── repository/ Spring Data JPA interfaces
│ ├── dto/ request and response records
│ ├── client/ Open-Meteo client with mock fallback
│ ├── service/ business logic, alert engine, notifications
│ ├── controller/ REST endpoints
│ ├── scheduler/ scheduled collection and forecast analysis
│ ├── security/ JWT generation, filter, user details
│ ├── config/ security, WebSocket, RestTemplate
│ └── exception/ global error handling
└── mikro-iklim-frontend/
├── public/
│ ├── icons/ SVG icon set
│ └── images/ logo, empty state
└── src/
├── app/ App Router pages
├── components/ reusable components
├── context/ AuthContext
├── services/ api client, formatters, WebSocket
└── styles/ all SCSS lives here
- If Open-Meteo is unreachable, a mock data generator takes over so the system keeps running. Check the
sourcefield on a reading to tell them apart:OPEN_METEOorMOCK. - Readings are cached — the same location is not re-fetched within 10 minutes.
- Map marker images are loaded from a CDN. Without internet access the pins will not render; download them into
public/icons/and update the three URLs inMapView.jsif that matters. - The frontend expects the backend on port 8080 and CORS is configured for
http://localhost:3000. ChangeSecurityConfigif you run either on a different port.