-
-
System architecture diagram
-
Event → decision lifecycle diagram
-
Real Mode home, live session 29:44 left, 1/1 devices online
-
Live View page with the WebRTC player and camera selector
-
A real Ring snapshot with its capture time
-
"Likely delivery" · LOW RISK · AI analysis complete
-
The money shot — NOTIFY, 90% confidence, matched rule, observations, uncertainty
-
The branded alert email with the analyzed frame
-
The same email showing what Matan saw and the rule that sent it
-
Smart Rules with real 7-day match counts
-
Assistant grounded in the user's own events
-
rends, charts and the Nova period summary
-
Ring capability matrix and read-only configuration
Inspiration
Ring's own app is not short of intelligence: Smart Alerts classify people, packages and vehicles, and AI Video Descriptions summarise an event. But that lives inside the Ring app, on a subscription. Through the Ring Partner API, a developer gets something rawer: a device, a history entry and a camera frame. And a description still isn't a decision — nobody decides, by rules you wrote, whether this particular event should wake you at two in the morning.
That gap is the project. Matan is Tetun for eye.
What it does
MATAN AI turns every Ring event into a decision you can read, and change.
- The event arrives — Matan polls Ring device history and keeps the real Ring type (
motion,package,vehicle,on_demand), device and duration. - The evidence is pulled — the camera frame for exactly that moment, fetched server-side, stored in a private per-user S3 prefix.
- Amazon Nova Pro reads it — through Bedrock's Converse API: what it sees, a category, a confidence, and what it is unsure about.
- A deterministic engine scores it — the model reads; it never decides.
- Your Smart Rules choose the action — low confidence → high risk → your rules → repeated activity → quiet hours → sensitivity → default.
- Only then does an email go out — with the analyzed frame, the decision, and the rule that sent it. Ignore and Monitor stay silent.

Everything is explainable after the fact: the frame the model looked at, its confidence and uncertainty, the matched rule, token usage, and a seven-step processing timeline. Live View streams the camera over WebRTC with the Ring token never leaving the server. An assistant answers questions grounded strictly in your own events — it cannot invent one.
How we built it

| Layer | What we used |
|---|---|
| App | Next.js 16 (App Router), React 19, TypeScript, Tailwind v4 |
| Ring | Partner API: devices + status/capabilities/location/configuration, history, snapshot, clip, WHEP live view, account |
| AI | Amazon Bedrock — Amazon Nova Pro, Converse API, validated structured output |
| Identity | Amazon Cognito (email + Google), verified server-side with aws-jwt-verify |
| Data | DynamoDB single table, PK = USER#{sub}, query-only |
| Media | Private S3 bucket (Block Public Access, SSE-S3), served through an authenticated route |
| Amazon SES with a configuration set, SMTP fallback while SES is in sandbox | |
| Hosting | AWS Amplify Hosting (Next.js SSR compute) with an IAM compute role — no long-lived keys |
Two rules shaped the whole build:
- The model reads, the engine decides. Any priority or action Nova emits is dropped during validation. Risk comes from deterministic code, so the same event always produces the same decision.
- Nothing is simulated in Real Mode. A panel is backed by Ring, AWS or Matan's own stored data — or it is labelled future integration with the reason. Ring exposes no device control to partners, so the siren and lights buttons say so instead of pretending.
Challenges we ran into
- Snapshots 404 until a live view has started. The device is online, it has history, and
media/image/downloadstill returns 404. Undocumented, and it cost an afternoon. Starting a WHEP session first fixes it. - A 30-minute token with no refresh. The Playground token simply expires. We built a sealed-cookie session, an expiry countdown and a reconnect flow — and made every cached device status show as last known once it lapses, because nothing can re-check it.
- Our own API calls came back as events. Every snapshot Matan requests appears in Ring history as an
on_demandentry, so the pipeline started analysing its own footprints and emailing about them. Fixed with a tight own-footprint filter. - Amplify console variables never reached the SSR runtime. S3 media silently 404'd in production while working locally. The build now copies an allow-list into the server bundle, and logs a
runtime_configline so a misconfigured instance is visible immediately. - Serverless froze our background work. Analysis started after the HTTP response never finished. We moved the queue into DynamoDB and made each analysis — including the email — complete inside a single request.
AccessDeniedfrom SES that named nothing. Sending with a configuration set needsses:SendEmailon both the identity and the configuration set. One missing ARN, and production mail stopped.
Accomplishments that we're proud of
- A complete loop against the real Ring API — simulate a package in the Playground and the alert arrives, analyzed and decided, with no manual step.
- Explainable decisions. Every event stores what the model saw, which rule matched, and why an email was or wasn't sent. That is what makes it safe to point at a grandparent's front door.
- Honest scope. Thirteen pages were audited one by one; every function is marked real or future integration with the reason. No fake buttons.
- It's yours. Your AWS account, your data, MIT licence, provisioning scripts and a Demo Mode that works before any Ring or AI service is configured.
- 66 unit tests, four architecture diagrams, and the full documentation browsable inside the app at
/docs.
What we learned
- Design for the token lifetime on day one. Retrofitting a session model around a 30-minute token touched every surface of the app.
- Let the model read, not decide. Nova is excellent at describing a doorbell frame and honest about uncertainty. Turning that into an action belongs in deterministic code you can test — and a confidence score is only useful if something acts on it.
- Assume the runtime is stateless. Three of our four production incidents came from code that was correct on a long-lived server.
- The real cost of an API is its undocumented behaviour, not its endpoints. We wrote the traps down so the next person doesn't pay for them twice.
What's next for MATAN AI
- Webhooks instead of polling, once Ring's lifecycle events can be exercised outside the Playground.
- Multi-device and multi-location — the logic is there and unit-tested; the Playground gives one synthetic device.
- Ring Appstore. This is exactly the shape of third-party app that channel opened for, and that is where we want it to live.
- Device control the day the Partner API exposes it — the UI already marks those actions as future integrations.
- SES out of sandbox, so alerts stop relying on the SMTP fallback.
- Tetun language support, because this was built for Timor-Leste first.
Built With
- amazon-bedrock
- amazon-cloudwatch
- amazon-cognito
- amazon-dynamodb
- amazon-nova-pro
- amazon-ses
- amazon-web-services
- aws-amplify
- aws-lambda
- aws-sdk
- json-api
- next.js
- node.js
- nodemailer
- react
- ring
- ring-api
- serverless
- tailwindcss
- typescript
- webrtc
- whep

Log in or sign up for Devpost to join the conversation.