A quick vibe-coded site to test response times of PLC.directory mirrors (over 3 attempts)

Add handle resolution to DID input

Enhance input handling to accept ATProto handles in addition to DIDs. If the entered string doesn't start with did:plc, resolve the handle via the quickdid API, use the resolved DID for benchmarking, and display errors via toasts. Update UI hints accordingly.

X-Lovable-Edit-ID: edt-eb32d8ac-36e8-471d-9660-b8d29b6e4f8a

Changed files
+38 -5
src
pages
+38 -5
src/pages/Index.tsx
···
const [loading, setLoading] = useState(false);
const [results, setResults] = useState<BenchmarkResult[]>([]);
const handleBenchmark = async () => {
if (!did.trim()) {
-
toast.error("Please enter a DID");
return;
}
···
setResults([]);
try {
-
const benchmarkResults = await benchmarkAllMirrors(mirrors, did.trim());
setResults(benchmarkResults);
const successCount = benchmarkResults.filter(r => r.status === "success").length;
···
<div className="space-y-4">
<div>
<label htmlFor="did-input" className="block text-sm font-medium mb-2">
-
ATProto DID
</label>
<div className="flex gap-3">
<Input
id="did-input"
type="text"
-
placeholder="did:plc:example123..."
value={did}
onChange={(e) => setDid(e.target.value)}
onKeyPress={handleKeyPress}
···
<div className="bg-muted/30 border border-border rounded-lg p-6">
<h3 className="font-semibold mb-2">How to use:</h3>
<ol className="list-decimal list-inside space-y-1 text-sm text-muted-foreground">
-
<li>Enter an ATProto DID (e.g., did:plc:z72i7hdynmk6r22z27h6tvur)</li>
<li>Click "Run Benchmark" or press Enter</li>
<li>View response times and status for each mirror</li>
</ol>
···
const [loading, setLoading] = useState(false);
const [results, setResults] = useState<BenchmarkResult[]>([]);
+
const resolveHandle = async (handle: string): Promise<string | null> => {
+
try {
+
const response = await fetch(
+
`https://quickdid.smokesignal.tools/xrpc/com.atproto.identity.resolveHandle?handle=${encodeURIComponent(handle)}`
+
);
+
const data = await response.json();
+
+
if (data.error) {
+
toast.error(`Unable to resolve handle: ${data.message || "Invalid handle"}`);
+
return null;
+
}
+
+
return data.did;
+
} catch (error) {
+
toast.error("Failed to resolve handle");
+
console.error(error);
+
return null;
+
}
+
};
+
const handleBenchmark = async () => {
if (!did.trim()) {
+
toast.error("Please enter a DID or handle");
return;
}
···
setResults([]);
try {
+
let resolvedDid = did.trim();
+
+
// If input doesn't start with "did:plc", treat it as a handle
+
if (!resolvedDid.startsWith("did:plc")) {
+
const resolved = await resolveHandle(resolvedDid);
+
if (!resolved) {
+
setLoading(false);
+
return;
+
}
+
resolvedDid = resolved;
+
toast.success(`Resolved to ${resolvedDid}`);
+
}
+
+
const benchmarkResults = await benchmarkAllMirrors(mirrors, resolvedDid);
setResults(benchmarkResults);
const successCount = benchmarkResults.filter(r => r.status === "success").length;
···
<div className="space-y-4">
<div>
<label htmlFor="did-input" className="block text-sm font-medium mb-2">
+
ATProto DID or Handle
</label>
<div className="flex gap-3">
<Input
id="did-input"
type="text"
+
placeholder="did:plc:example123... or handle.bsky.social"
value={did}
onChange={(e) => setDid(e.target.value)}
onKeyPress={handleKeyPress}
···
<div className="bg-muted/30 border border-border rounded-lg p-6">
<h3 className="font-semibold mb-2">How to use:</h3>
<ol className="list-decimal list-inside space-y-1 text-sm text-muted-foreground">
+
<li>Enter an ATProto DID or handle (e.g., did:plc:z72i7hdynmk6r22z27h6tvur or handle.bsky.social)</li>
<li>Click "Run Benchmark" or press Enter</li>
<li>View response times and status for each mirror</li>
</ol>