WatchTower is a lightweight observability dashboard for early-stage teams. It captures runtime errors, Core Web Vitals, and user feedback from any instrumented web app — then correlates them with the deploy events from your CI so you know exactly when the regression landed.
PostHog and Sentry are great when you've scaled. WatchTower is tightened down to what you actually need when your software first ships — and nothing more.
Uncaught exceptions and unhandled rejections with full stack traces, captured by a tiny SDK that hooks window.onerror.
Core Web Vitals (LCP, INP, CLS) and page-load timing, sampled via PerformanceObserver. No extra config.
Drop-in rating + comment widget. Real signal from real users, alongside the technical data.
WatchTower is built for the moment when "my software is in production now and I have no idea what it's doing."
Open the dashboard. See errors spiking after a 1:47am deploy. Click into the trace, find the line, ship a fix. Go back to bed.
Ship from your laptop. WatchTower lives on Cloudflare Workers' free tier; one SDK include on your site is the whole integration.
Built by 13 CSE 110 students in five sprints. Vanilla JS, zero framework lock-in, every decision captured as an ADR you can read on your way in.
22 ADRs, an architecture doc, a changelog, sprint retros, and a wiki — written so the next team can pick this up without a handoff meeting.
Three steps. About five minutes total.
Create an account on the dashboard. You'll get a projectId to identify your app.
One <script> tag. No build step, no bundler, no npm install. Served from jsDelivr.
<script
src="https://cdn.jsdelivr.net/gh/cse110-sp26-group7/Watchtower@main/client/watchtower.min.js"
defer></script>
Configure with your projectId and tell WatchTower which environment this is.
const wt = new Watchtower({
projectId: "your_project_id",
endpoint: "https://watchtower-ingest.cse110piedpiper7.workers.dev/ingest",
environment: "prod",
});
wt.init();
Drop this button into your page to confirm the round-trip ends up in the dashboard.
<button id="trigger-error">Trigger Test Error</button>
<script>
document.getElementById("trigger-error").addEventListener("click", () => {
throw new Error("Manual test error triggered");
});
</script>
Full setup instructions are in the repo README.
WatchTower is a five-layer pipeline: SDK → Ingest Worker → D1 → API Worker → Dashboard SPA. Every layer is one file or one folder you can read in an afternoon.
events table.See the architecture doc and the 22 architectural decision records for the reasoning.