"use client"; import * as React from "react"; import { Map as MapIcon, Search } from "lucide-react"; import type { MapResult } from "@/lib/api"; import { runMap } from "@/actions/crawls"; import { Alert } from "@/components/ui/alert"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; import { CopyButton } from "@/components/ui/copy-button"; import { Input } from "@/components/ui/input"; import { Field, Hint, Label } from "@/components/ui/label"; import { formatNumber } from "@/lib/format"; /** Mini tool: discover the URLs of a site (sitemap + links) with POST /v1/map, synchronously. */ export function MapTool() { const [url, setUrl] = React.useState(""); const [search, setSearch] = React.useState(""); const [limit, setLimit] = React.useState(200); const [pending, startTransition] = React.useTransition(); const [error, setError] = React.useState(null); const [result, setResult] = React.useState(null); function submit(e: React.FormEvent) { e.preventDefault(); setError(null); startTransition(async () => { const res = await runMap({ url: url.trim(), search: search.trim() || undefined, limit: Math.min(10_000, Math.max(1, Math.round(limit || 1))) }); if (!res.ok) { setResult(null); setError(res.error.message); return; } setResult(res.data); }); } return ( Map a site List the URLs of a site from its sitemap and the links on the seed page, without fetching every page. Same as POST /v1/map; runs synchronously (up to 60 s).
setUrl(e.target.value)} placeholder="https://example.com" autoComplete="off" autoCapitalize="off" spellCheck={false} className="font-mono text-[13px]" /> setSearch(e.target.value)} placeholder="blog, /docs/*, /regex/" maxLength={256} autoComplete="off" spellCheck={false} className="font-mono text-[12.5px]" /> setLimit(Number(e.target.value))} className="font-mono tabular" />
{error ? {error} : null} {result ? (
{formatNumber(result.count)} URL{result.count === 1 ? "" : "s"} sitemap {formatNumber(result.sources?.sitemap ?? 0)} links {formatNumber(result.sources?.links ?? 0)} {result.truncated ? truncated at {formatNumber(limit)} : null}
{result.urls.length ? (
    {result.urls.map((u, i) => (
  1. {i + 1} {u}
  2. ))}
) : ( No URLs found. The site may have no sitemap and the seed page no links, or the filter matched nothing. )}
) : ( Use the result to pick include/exclude patterns before starting a crawl. )}
); }