Commit Graph
2021 Commits
Author SHA1 Message Date
jason5ng32 d5452c0fce Improvements 2026-10-21 14:31:47 +08:00
jason5ng32andClaude Fable 5.1 e7bc4db293 Feat(analytics): track how the Security Checklist is read and used
GA saw only category switches and resets, so a month of visits could
not say whether anyone read an item's details or ticked one. Four
labels on the existing SecurityChecklist event — ItemInfo and
CategoryIntro when a details panel or intro opens, Check and Ignore
when an item is ticked or set aside — read as a funnel after
ChangeList. Only the positive direction fires; closing and undoing
stay silent.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-21 12:24:21 +08:00
jason5ng32andClaude Fable 5.1 49c3dfa887 Feat(tools): move the Security Checklist into a reference group
The checklist is content to read and work through, not a test that
runs, yet it sat among the network diagnostics where a card promises a
result. A fourth group, 'reference', now closes the Advanced Tools grid
and holds it alone; the group's title lands in every full locale, and
the self-hosted grouping test expects the group to survive the gates.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-21 12:24:21 +08:00
jason5ng32 5cfb73994a Improvements 2026-10-21 11:33:54 +08:00
jason5ng32andClaude Opus 5.5 45f920248f Fix(analytics): one NavClick label per tool, sent once
Tool opens labelled NavClick with the slug's first letter capitalized
('Pingtest'), while keyboard shortcuts sent a second, hand-written label
('PingTest', 'AsnProfile') on top of the one openTool already sent. GA
labels are case-sensitive, so one tool split into two rows and every
shortcut open counted twice. The label is now the slug as-is, the same
id as /tools/<slug>, and shortcuts rely on openTool's event alone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 10:44:56 +08:00
jason5ng32andClaude Opus 5.5 50885c6317 Fix(pulse): show cloud-origin outages and drop empty Radar events
Radar files some events against a cloud region (originDetails) rather
than a location or ASN. The feed ignored that subject, so an ongoing
ORIGIN anomaly rendered as a blank first row and escaped dedupe against
its matching outage. Origins are now mapped, shown, and matched in
dedupe; stub annotations with no subject and no text are dropped. The
new PLATFORM outage level gets a translation in every full locale.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 10:42:45 +08:00
jason5ng32andClaude Fable 5.1 7a608cb8ce Feat(footer): fold the product links into a four-column footer
The Raycast / curl / Lite badges sat in an unlabelled image row of their
own under the Advanced Tools. The footer now has four columns aligned
with that card grid — brand, Project, Docs & Support, Clients — so the
product entries get a heading and show on every route; the curl
commands keep their dialog. Docs links share one locale-aware helper.
The footer never repeats on-page content, and the fixed footer height
in style.css goes, as the columns size themselves.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-20 18:45:09 +08:00
jason5ng32andClaude Fable 5.1 d28fe239ae Fix(nav): collapse the link row by measured width, not by isMobile
Tablets report a desktop UA, so between 768px and ~1366px the flat
link row rendered and wrapped inside its links; no single breakpoint
fits six locales. use-nav-overflow.js measures the row against the
space beside the brand and actions and collapses to the hamburger
when it doesn't fit. The row stays rendered (invisible, inert) so it
remains measurable. DocsSearch switches to its icon below xl by CSS so
the action group's width never depends on the collapse state.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-20 17:54:46 +08:00
jason5ng32 35e691da6e Improvements 2026-10-19 23:45:41 +08:00
Jason Ng 116a74b1a0 Merge pull request #507 from jason5ng32/feat/adblock-test
Feat: Ad & Tracker Blocking Test
2026-10-19 23:23:34 +08:00
jason5ng32 072a76cae0 Improvements 2026-10-19 23:18:32 +08:00
jason5ng32andClaude Opus 5.5 4cc48d151b Fix(adblocktest): state what the probes cannot tell
A probe is a plain fetch from this page, so a filter rule aimed only at
one request type (e.g. `$script`) can let it through while still
blocking the real script on a website; a line under the list version now
says so. The empty "not blocked only" / "blocked only" views claimed
everything was (or nothing was) blocked even when results had timed out
or were still pending; they now say only that no request was confirmed
in that state.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 23:15:51 +08:00
jason5ng32andClaude Opus 5.5 88423522e3 Feat(report): add the Ad & Tracker Blocking Test to shareable reports
A blocker setup is part of the visitor's own environment, like the
browser info and proxy-rule sections, and is worth handing to whoever
helps debug it. The section stays deliberately small: request counts per
category (blocked / not blocked / no answer / total), no per-address or
per-vendor rows, so a report stays readable and the list can change
without breaking old links. Group ids are capped strings rather than an
enum for the same reason.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 23:04:09 +08:00
jason5ng32andClaude Opus 5.5 1163ea4a13 Docs(readme): list the Ad & Tracker Blocking Test
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 22:53:43 +08:00
jason5ng32andClaude Opus 5.5 06402ce688 Feat(adblocktest): add the Ad & Tracker Blocking Test
People running uBlock Origin, Privacy Badger, a blocking browser, or a
DNS / VPN / router filter had no way here to see what their setup lets
through. The new tool probes a static list of widely used ad, analytics,
social, error-monitoring and device-maker endpoints plus popular tracking
scripts (fetched with no-cors and no cookies or referrer, never run), and
places bait elements for cosmetic filters. Nothing runs until the visitor
starts it; every group starts selected.

A timeout reads as "no answer" and stays out of the score, and every
listed host was checked to resolve, serve valid HTTPS and not redirect to
http:// or in a loop, since any of those would fail like a block. Element
hiding is left out of the score (DNS-level filters can never pass it) and
instead tells browser-level from network-level blocking. The page copy
says outright that blocking everything is not automatically better.

Ships with the x shortcut, locale copy for every full locale and a
changelog entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 22:53:43 +08:00
jason5ng32andClaude Opus 5.5 c2751d37f7 Feat(ui): add the shadcn-vue Alert component
Notices across the tools are hand-rolled boxes; Alert gives new ones the
primitive instead. In this JavaScript setup the CLI imports `cn` from a
bare "cn" module and installs an unrelated npm package of that name, so
the dependency is dropped and the components import from @/lib/utils;
frontend/AGENTS.md records the trap for the next `shadcn-vue add`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 22:53:29 +08:00
jason5ng32andClaude Opus 5.5 b84a1d3764 Refactor(ip-infos): drop the default map images
A card only shows its map once location data has landed, so the bundled
placeholder maps were never meant to be seen, and their labels sat in one
language among many. An empty map URL now renders a same-sized muted box,
which also covers a payload with a country but no coordinates.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 09:35:31 +08:00
jason5ng32andClaude Opus 5.5 6e40a611d3 Fix(api): require a tag-shaped language in the map proxy
Any non-empty language reached Static Maps, so every distinct value was an
uncached upstream call whose answer the edge kept for a year. A tag-shape
check still passes region-tagged UI locales (zh-TW, pt-BR) without an
allow-list, and the handler block now covers both sides.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 09:35:27 +08:00
Victor SolanoandClaude Opus 5.5 64ace80bf2 Fix(api): accept region-tagged languages in the map proxy (#506)
The UI passes its locale code as the map language, and pt-BR and zh-TW are
registered locales, but /api/map only accepted a bare two-letter code, so
every map request from those two locales answered 400 and the map never
loaded. Pass the tag through like every other ?lang (api/AGENTS.md) and
URL-encode it where the Static Maps URL is built, so the value stays one
query parameter.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-17 09:27:27 +08:00
jason5ng32andClaude Opus 5.5 79a91171f7 Refactor(probes): take chain options as an object and share version validators
runChain's optional originalSite / accept move into an options object, so a
chain that needs only one no longer passes an `undefined` placeholder.

The per-version validators become isValidIPv4 / isValidIPv6 in
common/valid-ip.js, next to isValidIP: the "Valid" prefix keeps them apart
from the non-validating isIPv6 discriminator.

Tests now run the four single-version entry points against a stubbed fetch,
so dropping or swapping a chain's validator fails the suite.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 23:28:12 +08:00
14649814andAntigravity f4d90fe44c Fix(probes): strictly validate IP version on dedicated v4/v6 chains (#504)
- Require isValidIP && isIPv6 on IPv6-only probes (ipChecking6, cloudflareV6)
- Require isValidIP && !isIPv6 on IPv4-only probes (ipChecking4, cloudflareV4)
- Export isIPv4 and isOnlyIPv6 and add dedicated unit tests in getips.test.js

Co-authored-by: Antigravity <antigravity@google.com>
2026-10-15 23:25:19 +08:00
jason5ng32 70c1cbd2b9 Merge branch 'sponsors-2026-10b' into dev 2026-10-14 18:02:07 +08:00
jason5ng32andClaude Opus 5.5 547e9a1e84 Docs(sponsors): add Proxy-Seller and link sponsor names
Proxy-Seller joins the paid sponsors in all six READMEs and the footer
acknowledgement list. Each sponsor's bold name in the description line now
links to the same destination as its logo, so the copy is clickable too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:01:52 +08:00
jason5ng32 5d378c5e13 Improvements 2026-10-13 09:54:52 +08:00
jason5ng32 47dff987b1 Improvements 2026-10-13 09:48:16 +08:00
jason5ng32 6036a7c570 Merge branch 'readme-supporters-layout' into dev 2026-10-11 10:41:18 +08:00
Jason Ng da9614c87e Merge pull request #502 from jason5ng32/readme-supporters-layout
Docs(sponsors): separate supporters and stack their logos
2026-10-11 10:41:06 +08:00
jason5ng32andClaude Opus 5.5 068ea5a795 Docs(sponsors): separate supporters and stack their logos
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 10:40:29 +08:00
Jason Ng 6211b124b0 Merge pull request #501 from jason5ng32/sponsors-2026-10
Docs(sponsors): add SwiftProxy and split paid sponsors from supporters
2026-10-10 10:25:35 +08:00
jason5ng32 e23f00a818 Merge branch 'sponsors-2026-10' into dev 2026-10-10 10:24:47 +08:00
jason5ng32andClaude Opus 5.5 2961d9ba8d Docs(sponsors): add SwiftProxy and split paid sponsors from supporters
The README listed every sponsor as an equal-size logo at the bottom, with
the only ad copy hidden in a hover-only title attribute. Paid sponsors now
get their own group with a visible one-line description under each logo;
free-plan supporters share one row of smaller logos. V.PS links carry the
README's locale in utm_content.

SwiftProxy joins the paid group and the footer acknowledgement list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 10:24:19 +08:00
jason5ng32 a509b99207 Improvements 2026-10-09 14:23:04 +08:00
jason5ng32 187ede91a9 Improvements 2026-10-07 15:34:08 +08:00
jason5ng32andClaude Opus 5.5 017e5c9af3 Feat(ip-infos): point score details to a live blocklist check
Score details is one of the most-opened panels, but the score is not a
live reading. A line under it links to Blocklist Check with the IP
carried as `?q=`, which the tool now prefills without running: the
visitor may be signed out or out of quota.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 15:26:02 +08:00
jason5ng32 117ebaa65a Improvements 2026-10-07 10:03:06 +08:00
jason5ng32andClaude Opus 5.5 89a103a3b7 Fix(footer): open the About sheet only on the page on screen
Home and ToolPage are both kept alive with a Footer each, so once a tool
page had been visited, a footer link on Home opened both sheets and the
cached one, stuck on its own tab, covered the right one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 00:45:35 +08:00
jason5ng32 6d7221538d Improvements 2026-10-06 13:03:58 +08:00
jason5ng32 8d7b53d1de Improvements 2026-10-06 11:35:36 +08:00
Jason Ng 015d6aef7b Merge pull request #500 from jason5ng32/feat/tools-as-pages
Feat/tools as pages
2026-10-06 11:31:09 +08:00
Claude de9d3d2118 Fix(service-status): drop a detail answer from before a reload
A detail request still in flight when the overview reloads (Refresh, or
the re-pull on activation) wrote its answer back after the reload had
cleared the cache, so the reopened card skipped its fetch and showed the
older snapshot. Reload bumps an epoch; an answer from an earlier one is
discarded.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-06 03:03:58 +00:00
Claude de6c5d730d Style: open PageBreadcrumb and UserMenu with their purpose comment
Their purpose was stated in <script setup>; it now opens the template as
in the rest of components/, with the script comment keeping only what
the markup does not say.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-06 02:59:39 +00:00
Claude f2d684faa8 Chore: document the ASN Profile graph's expand-to-drawer
The profile page keeps ASNConnectivity expandable; the guide, the host
card's comment and the prop's comment said otherwise.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-06 02:57:58 +00:00
Claude 26cb4ad15c Fix(breadcrumb): a section crumb stays a link at the end of the trail
Tool pages end their breadcrumb on Advanced Tools, as the <h1> beside it
names the tool. The crumb was rendered as the current page (aria-current,
not clickable) and its section ignored; now any crumb with a section links
to it, and only a bare last crumb is the current page.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-06 02:57:58 +00:00
Claude 7571e0c71e Fix(service-status): re-pull the overview when shown again after a backend cycle
The tool page is kept alive, so a visitor returning after the backend's
5-minute refresh saw the status pulled at mount until they hit Refresh.
On activation, an overview older than that cycle reloads as Refresh does.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-06 02:57:58 +00:00
Claude e39aed71e3 Fix(achievements): open the sheet when it mounts after the request
UserMenu raises the request from a tool, privacy or report page and goes
Home first. Home's Achievements is an async component: on a first visit it
can mount after the flag is already set, so the request was missed and the
flag stayed set, swallowing every later one. The watcher now runs
immediately and acts only on a raised flag.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-06 02:57:58 +00:00
jason5ng32 b616b7e00e Improvements 2026-10-06 10:48:50 +08:00
jason5ng32 8543879bbd Improvements 2026-10-06 10:33:31 +08:00
jason5ng32 78db2f8934 Improvements 2026-10-06 10:16:04 +08:00
Claude 4429020d91 Fix(nav): navigate from the mobile sheet after it has closed
WebKit records a page's back/forward snapshot as it navigates away,
so a tool or section picked from the mobile nav sheet left a snapshot
with the sheet still sliding out, which a swipe back then showed. The
sheet closes first and the navigation follows its slide-out.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-06 01:57:12 +00:00
Claude 3e4a268ce5 Fix(ui): resolve the route in Footer's setup
useRoute() inside the computed ran inject() outside setup, which
returns undefined: Footer threw on every render and the navigation
back to the homepage lost its scroll restore (the page landed at the
top). The route is resolved once in setup.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013GbLTGMZ45MV78qd2tHoco
2026-10-06 01:45:51 +00:00