Point it at a public GitHub repository and get a report of which package.json dependencies have newer versions on npm, in the browser and, after confirming your address, by email every 6, 12 or 24 hours or once a week.
| Check a repository | Report |
|---|---|
![]() |
![]() |
sequenceDiagram
autonumber
actor User as Browser
participant Caddy
participant API as NestJS API
participant GitHub as GitHub GraphQL
participant npm as npm registry
participant SendGrid
User->>Caddy: POST /v1/subscriptions {owner, repo, email, period}
Caddy->>API: proxy (same origin)
API->>GitHub: repository exists? HEAD:package.json
GitHub-->>API: package.json
API->>npm: latest version of every dependency
npm-->>API: versions
API->>API: classify major / minor / patch, cache 1 h, store pending subscription
API->>SendGrid: confirmation email
API-->>User: report + subscription {status: pending}
User->>API: POST /v1/subscriptions/:token/confirm
API->>SendGrid: first report
loop every hour
API->>API: find active subscriptions whose period elapsed
API->>SendGrid: report with unsubscribe link
end
The browser talks to a single origin. Caddy serves the Svelte bundle and proxies /v1/* to the NestJS API, which reads package.json from GitHub's GraphQL API, checks every dependency against the npm registry and optionally sends the report through SendGrid. The interactive diagram is generated from docs/architecture.json with archify and published by the Pages workflow.
| Directory | Role | Stack |
|---|---|---|
api/ |
REST API | NestJS 12 · TypeScript 6 (ESM, strict) · graphql-request · npm registry · SendGrid · Vitest |
ui/ |
Single-page app | Svelte 5 (runes) · TypeScript · Vite |
packages/contracts/ |
Types and constants shared by both, so the API and the UI cannot drift apart | TypeScript |
docs/ |
Architecture diagram published to GitHub Pages | archify |
Requires Docker with Compose.
make up # creates .env on the first run, then builds and starts the stackSet TOKEN in .env to a GitHub token, run make up again and open http://localhost:8080.
| Command | Description |
|---|---|
make up |
Build the images and start the stack in the background |
make down |
Stop and remove the containers |
make logs |
Follow the logs |
make ps |
Container status (the UI waits for a healthy API) |
Without make: cp .env.example .env && docker compose up -d --build.
Requires Node.js 24.15+ (see .nvmrc). The repository is an npm workspace with one lockfile.
make install # npm ci for every workspace, then builds packages/contracts
make lint # prettier --check, oxlint, tsc for the API, svelte-check for the UI
make test # API unit + e2e tests, UI unit + component tests
make smoke # Playwright against the running stack (make up first)
make smoke-stub # Playwright against stubbed GitHub and npm; what CI runs
npm run dev:api # http://localhost:3288
npm run dev:ui # http://localhost:5173, /v1 proxied to the API| Method | Path | Body | Response |
|---|---|---|---|
GET |
/health |
{ "status": "ok" } |
|
GET |
/v1/repositories/:owner/:repo |
{ "valid": boolean } |
|
GET |
/v1/repositories/:owner/:repo/report |
Report, 404 unknown repo, 422 no package.json, 502 GitHub unreachable |
|
POST |
/v1/subscriptions |
{ owner, repo, email, period: 6 | 12 | 24 | 168 } |
201 report and a pending subscription; a confirmation email is sent |
POST |
/v1/subscriptions/:token/confirm |
Activates the subscription and sends the first report | |
DELETE |
/v1/subscriptions/:token |
204, 404 unknown token |
|
POST |
/v1/subscriptions/:token/unsubscribe |
One-click unsubscribe (RFC 8058); 204, 404 unknown token |
Swagger UI is served at /docs (http://localhost:8080/docs with Docker) and the OpenAPI document at /docs/openapi.json. Response shapes, status codes and module layout are documented in api/README.md.
Copy .env.example to .env. Only TOKEN is required; the report is emailed when both SENDGRID_API_KEY and EMAIL_FROM are set. The API validates its environment at startup and refuses to start with invalid values. All variables are listed in api/README.md.
.
├── api/ NestJS API
│ ├── src/
│ │ ├── config/ typed, validated environment
│ │ ├── github/ GraphQL client
│ │ ├── dependencies/ npm registry client and outdated check
│ │ ├── report/ report building, one-hour cache, HTML and text rendering
│ │ ├── email/ SendGrid delivery
│ │ ├── subscriptions/ subscription lifecycle, hourly delivery, SQLite store
│ │ ├── routes/ /v1 controllers and DTOs
│ │ └── health/ liveness probe
│ └── test/ e2e tests
├── ui/ Svelte 5 SPA served by Caddy
├── packages/contracts/ types and constants shared by api and ui
├── docs/ architecture diagram (GitHub Pages)
├── docker-compose.yml
└── Makefile
See CONTRIBUTING.md. Work is tracked as issues on the project board; commits follow Conventional Commits with the issue number as the scope, for example feat(#4): restructure the API into modules, and release-please turns them into releases and the changelog. CodeQL scans every push and pull request. Dependabot opens grouped update pull requests every Monday for both apps, GitHub Actions and the Docker base images. See SECURITY.md for reporting vulnerabilities.
api/ and ui/ started as separate repositories (package-validator-api, package-validator-ui) and were merged with git subtree, so their full history is preserved.
Murat Mayadağ · GitHub
MIT © Murat Mayadağ

