Imported from jason5ng32/MyIP (
AGENTS.md). Install upstream withnpx skills add jason5ng32/MyIP. Copyright stays with the author.
AGENTS.md
Single source of truth for anyone — human or AI — contributing to MyIP. Area-specific details: @frontend/AGENTS.md (Vue SPA) · @api/AGENTS.md (Express API).
Local skill discovery
Before choosing a workflow for a project task, check the repository-root
.skills/ directory. It contains local skills at .skills/<name>/SKILL.md
and may not appear in the agent's automatically supplied skill list.
- If the directory exists, discover its skill files with
rg --files --hidden --no-ignore .skills -g SKILL.md(it is gitignored). - Read each skill's frontmatter
nameanddescription; read the fullSKILL.mdfor any skill that applies, then follow its workflow. - Complete this discovery before choosing a fallback tool or telling the user that a project capability or service is unavailable. Load supporting files only when the selected skill requires them.
Overview
MyIP (IPCheck.ing) is an open-source IP toolbox: IP lookup, connectivity tests, WebRTC / DNS-leak detection, speed test, MTR, Whois, security checklist, browser fingerprint, anonymity checks, persona check, IP calculator, and more. Single repo, two halves: a Vue 3 SPA front-end and an Express 5 back-end API.
Stack
| Layer | Technology |
|---|---|
| Frontend | Vue 3 (<script setup>) · Pinia · vue-router (HTML5 history) · vue-i18n (locales registered in common/locale-registry.js) |
| Build | Vite + @vitejs/plugin-vue; Tailwind CSS v4 + tw-animate-css |
| UI | shadcn-vue copy-in primitives (reka-ui) · lucide icons · circle-flags via @iconify/vue · vaul-vue drawer · vue-sonner toast |
| Backend | Express 5 |
| Logger | pino singleton at common/logger.js (+ pino-http, opt-in) |
| Auth | Firebase Auth (optional, env-gated) |
| Error monitoring | Sentry — optional & env-gated on both halves: @sentry/vue (no VITE_SENTRY_DSN_FRONTEND, no Sentry in the build — see frontend/AGENTS.md) + @sentry/node (no SENTRY_DSN_BACKEND, never loaded — see api/AGENTS.md) |
| PWA | manifest.webmanifest only — installable but online-only, no service worker |
| Tests | Node built-in test runner (node --test) |
| Runtime libs | chart.js · chartjs-chart-geo · @cloudflare/speedtest · maxmind · whoiser · thumbmarkjs · ua-parser-js · detect-gpu · @vueuse/core |
Commands
| Command | What it does |
|---|---|
pnpm dev |
Vite + backend (nodemon) together |
pnpm build |
Front-end production build |
pnpm preview |
Vite preview of the build output |
pnpm start |
Built front-end + backend |
pnpm test |
Run all tests/*.test.js specs |
pnpm check |
test + build — the pre-commit self-check |
pnpm only (pinned via packageManager); pnpm-lock.yaml is committed and
pnpm-workspace.yaml holds the allowBuilds install-script approvals. Never
use npm / yarn — they'd produce a competing lockfile.
Project layout
.
├── AGENTS.md / CLAUDE.md ← this file + Claude pointer to it
├── frontend/ ← Vue 3 SPA (see frontend/AGENTS.md)
├── api/ ← Express handlers (see api/AGENTS.md)
├── common/ ← code shared by both halves (valid-ip /
│ fetch-with-timeout / guards / logger / …)
├── tests/ ← Node test runner specs
├── backend-server.js ← Express app (default port 11966)
├── sentry-instrument.js ← backend Sentry bootstrap via `node --import`;
│ no-op without SENTRY_DSN_BACKEND
├── frontend-server.js ← static server for `pnpm start` (+ SPA fallback)
├── ecosystem.config.cjs ← pm2 definitions (carries the `--import` flag)
├── index.html ← Vite entry
├── vite.config.js / jsconfig.json (alias @ → frontend/) / package.json
Conventions
Language
- JavaScript only. New files are
.js/.vue; nolang="ts", no TypeScript migration. - English by default for code comments, commit messages, and AGENTS.md. Locale packs obviously carry their own language; planning docs are free.
Functions
- New functions use
constarrow syntax (const fn = async () => {}), notfunctiondeclarations. Object methods keep shorthand. Arrow consts aren't hoisted — declare before use. Applies to new / rewritten code only; don't mass-convert existing declarations.
Comments
- Every new file opens with a header comment stating its purpose —
except
frontend/components/ui/, which holds shadcn-vue CLI output kept verbatim so it can be re-synced (see frontend/AGENTS.md). - Large templates / functions carry block comments per meaningful region.
- Comments describe the code as it is now — no changelog narration
(
previously…,…fixes that); git history covers the past. A comment stays shorter than the code it explains.
i18n coverage
- Copy-surfacing features land in every
fulllocale in the same change — includingfrontend/data/changelog.jsonentries (tests/changelog.test.jsandtests/locale-packs.test.jsenforce it againsten).betalocales are free to lag: their gaps resolve down the fallback chain incommon/locale-registry.js, which is also where a new language is registered. - Contributor-facing walkthrough: TRANSLATING.md — keep it in
step when the registry, the pack gate or
pnpm i18n-statuschanges.
Logging (backend)
- Always the shared logger (
common/logger.js) in backend files; bareconsole.*is banned there (frontend keeps usingconsole.*). - Pino first-arg-is-context:
logger.error({ err, ip }, 'short message'). - Env knobs:
LOG_LEVEL(default info),LOG_FORMAT=jsonfor shippers,LOG_HTTP=trueto mountpino-httpon/api(off by default; handlers never log "received request" lines themselves). NoNODE_ENVanywhere. - Startup-only lines lead with an emoji (🚀 listening · 📦 ready · 📥 downloading · 🛡️ security · 🐢 throttling · 🗓️ schedule · ⚠️ recoverable · ❌ failure); per-request logs stay plain.
Testing
- Any non-visual logic exercisable without a network call — pure functions,
composables with mockable inputs, transforms, validators — ships with a
spec in
tests/, in the same change (don't defer; update affected tests when behavior shifts). - UI rendering, real network behavior, and browser APIs are out of scope.
pnpm checkmust be green before handing off.
Security & Boundaries
Access control and timeouts live in shared middleware, not handlers (details in @api/AGENTS.md):
requireRefereris global on/api/*;requirePublicIP()per-route — handlers never repeat these checks.- Every upstream HTTP call goes through
fetchUpstream(common/fetch-with-timeout.js, 8s timeout). Never a barefetch()inapi/.
Workflow
- Branch discipline —
devin,devout.mainonly moves via dev → main PRs. From a worktree, fast-forward dev withgit push . HEAD:dev(repo hasreceive.denyCurrentBranch=updateInstead), notgit update-ref. - No commits without explicit user approval — AI edits → user reviews → user tests → user says "commit". Even with tests green, visual changes need user eyes before landing.
- One concern per commit, message style per
git log(Feat(xxx):/Fix(ui):/Refactor(xxx):/Style:/Chore:), AI adds itself as co-author. - Self-test before handing off (
pnpm check); if a change is visual and headless-unverifiable, say so explicitly. - On every commit, scan AGENTS.md (root + relevant sub-file) for staleness — conventions, renames, flipped rules, dead examples get fixed in the same commit. Doc drift is this file's main failure mode.
If local-context.md exists in the workspace root, read it too — it lists machine-local Knowledge Hub paths (not in git).