Sentinel Tools
A live suite of security tools for links, repositories, and files, sharing one design system and one explainable scoring model.
Shipped four production apps on custom subdomains with a shared component library, a transparent 100-point risk model, CI, unit tests, and strict rules against overclaiming what a scan can prove.
- Role
- Designer & Full-Stack Web Developer
- Team size
- Solo build
- Updated
- 2026-06-12

Overview
What the project is and why it mattered.
Sentinel Tools packages three focused security checkers behind one hub: LinkSentinel inspects URLs before you click, RepoSentinel reads the public surface of a GitHub repository before you clone, and FileSentinel verifies files in the browser before you open them. Every report explains its score deduction by deduction and is written for non-security readers.
Suite
Hub plus three scanners on one shared design system
Scoring
Explainable 100-point model with visible deductions
Platform
npm workspaces monorepo on Cloudflare Workers
Problem
Single-purpose security checkers tend to either overwhelm people with raw output or hide everything behind a verdict like "safe", which a scan cannot honestly promise. The suite needed consistent visual language, consistent scoring, and consistent honesty across three very different scan targets, plus real deployment on shared infrastructure instead of three copy-pasted codebases.
Role
I designed and built the monorepo: the shared design system and scoring packages, all four apps, the Cloudflare Workers deployment pipeline, CI, tests, and the project documentation, then migrated the previously standalone LinkSentinel into the suite without breaking its existing behavior.
Build details
Stack, constraints, and decisions.
Stack
Constraints
- No tool may ever call something "safe", "clean", or "virus-free"; the strongest allowed claim is "no obvious issues detected by these checks", and that rule is documented and enforced in copy review.
- FileSentinel hashes everything in the browser, so file contents can never leave the machine; the optional VirusTotal lookup sends only a SHA-256 hash and only after an explicit click.
- RepoSentinel is read-only over the GitHub API and must mask any detected secret down to a path, line number, and masked preview.
- API keys live as server-side runtime secrets and must never reach a client bundle.
- Cloudflare's Next.js Pages adapter tops out at Next 15, so deployment had to go through the OpenNext Workers adapter with webpack builds.
Decisions made
One design system, zero copy-paste styling
All shared UI lives in a sentinel-ui package consumed as raw TypeScript through transpilePackages, so the four apps stay visually identical without duplicating components or tokens.
Make every score auditable
A shared scoring core starts at 100 and subtracts a fixed penalty per finding by severity, and every report lists each deduction, so a grade like Caution is traceable to specific evidence.
Treat honest language as a product feature
A safety-language document bans verdict words and defines approved phrasings like "known malware reputation" and "unknown", which keeps marketing copy and scan output from promising more than the checks deliver.
Ship production URLs in committed env files
Public cross-app URLs are inlined at build time, so each app carries a committed .env.production; an early deploy that shipped localhost buttons proved why this needed to be impossible to forget.
Outcome
What came out of it.
Outcome
- Four apps live on sentineltools.net and its repo, file, and link subdomains, each as its own Cloudflare Worker with a custom domain.
- RepoSentinel reads repository metadata, hygiene files, dependency manifests, and risk indicators through the GitHub tree API without cloning, and redacts anything secret-shaped.
- FileSentinel computes SHA-256, SHA-1, and legacy-labeled MD5 locally, compares expected checksums, flags suspicious naming and type traits, and offers an opt-in VirusTotal reputation lookup by hash.
- Migrated the standalone LinkSentinel app into the monorepo, swapping its local components for the shared library while keeping every route and its scanner logic intact.
- Backed the suite with GitHub Actions CI, 47 unit tests across scoring, parsing, redaction, and trait detection, and shared security headers on every response.
Lessons
- Build-time and runtime configuration are different worlds on serverless platforms; an env var that exists at deploy time may not exist at build time, and the bugs that follow are silent.
- Shared egress IPs on edge platforms exhaust unauthenticated API quotas almost immediately, so "optional" API tokens become required the moment you deploy.
- Migrating an app into a monorepo is dramatically cheaper when its design system was extracted into a package first.
Next
- Tighten the Content-Security-Policy with per-request nonces instead of allowing inline scripts.
- Add rate limiting and abuse controls in front of the scanning endpoints.
- Expand RepoSentinel checks toward dependency vulnerability data and commit-history secret scanning.
Keep browsing
Keep moving through the archive or reach out if you want to talk through similar work.