Inspiration

Web agencies keep their client work in Jira, yet the first sign that a client's site is broken is usually an annoyed email from the client. We had already scanned 43,077 small-business websites with a set of plain checks: of the 41,207 that answered, 51% had at least one problem a visitor would notice - a phone number you cannot tap on a phone (18.6%), a copyright year two or more years old (10.5%), images over 1 MB (8.2%), no mobile viewport (5.6%), the site down (5.3%). Every one of those is a ticket an agency would rather open itself.

What it does

Add client sites to a Jira project's watch list from the project page. Once a day the app checks every site and turns each defect into one Jira issue with the evidence - the HTTP status, the insecure URL, the oversized image and its size - and the steps to fix it. It never files the same problem twice, and when a rescan shows the problem gone it comments on the issue and moves it to Done. A site that does not answer closes nothing, so an outage cannot wipe the backlog.

The Rovo agent "Site Watch" answers "what is broken on joes-plumbing.com?" for any public site, and rescans a watched site on request. The same two tools are exposed through a rovo:mcp server, so any MCP client connected to Rovo can use them. Each scan also upserts a per-site report into Teamwork Graph (a graph:connector), so Rovo search answers "what is wrong with this client's site" without opening Jira.

How we built it

Forge, all on Atlassian: a UI Kit project page, a daily scheduled trigger, Forge storage for the watch list, Jira REST as the app for issues and transitions, a Rovo agent with two actions, and a rovo:mcp module over the same functions. The checks are the ones from our open-source GitHub Action, vendored byte-for-byte and pinned by a test. The decision logic (labels, dedupe, create / keep / resolve, issue body in Atlassian Document Format) is a pure module with its own tests, so it is checked without a Jira site. Most of the code and text was written by an AI system (Claude) under the entrant's direction; the entrant chose the problem, reviewed the work and owns the project.

Challenges

  • Outbound fetch to customer sites that cannot be listed in advance: the manifest declares allow-all egress, which keeps the app on "Runs on Atlassian" terms but has to be justified in the listing - the hosts contacted are the watched sites, plus two public lookup services that receive only the site's host name: crt.sh (certificate expiry) and dns.google (SPF/DMARC records).
  • Deciding when an issue may close: only when the site answered and the check ran and passed. "Not found this time" because the site was down is not a fix.
  • Labels as the dedupe key: Jira labels take no spaces, so each problem gets a short predictable label (sw-<host>-<check>) that JQL can match exactly.

Accomplishments

Issues an agency can act on without opening the site: what was found, where, and how to fix it, plus a backlog that cleans itself up.

What we learned

The useful part is not the check, it is the bookkeeping around it - knowing what has already been reported and what is now fixed.

What's next

A weekly client-ready summary per site, and Teamwork Graph relationships from each site report to the Jira issues and the client's account.

Share this project:

Updates