Use Cases (Atualizado: 02/06/2026)

Geolocation API com Claude Code: permissões, privacidade, fallback e testes

Implemente Geolocation API com Claude Code: permissões, HTTPS, fallback manual, privacidade e testes.

Geolocation API com Claude Code: permissões, privacidade, fallback e testes

Geolocalização parece uma função pequena, mas em produto real envolve permissão do navegador, HTTPS, falhas de dispositivo, entrada manual, privacidade, integração com mapa e testes. Um buscador de lojas, uma estimativa de entrega ou um check-in de equipe de campo não pode depender apenas do caminho feliz.

Claude Code é útil quando recebe um pedido preciso. Se você pedir apenas “adicione localização atual”, ele pode gerar um getCurrentPosition sem explicar o motivo ao usuário, sem fallback e com latitude e longitude no log. A versão publicável precisa pedir localização só depois de uma ação, respeitar negação, limitar tempo de espera e provar o comportamento com mocks.

As referências principais são MDN Geolocation API, getCurrentPosition, watchPosition, Permissions API, W3C Geolocation specification, Chrome sobre secure origins, Chrome DevTools Sensors, Playwright emulation e Claude Code permissions. Para aprofundar no site, veja integração com mapas, auditoria de segurança e design responsivo.

Defina o limite da função

Geolocation API pede ao navegador uma posição estimada do dispositivo. O navegador pode usar GPS, Wi-Fi, antenas, IP, serviços do sistema operacional ou cache. A aplicação não escolhe a origem nem deve prometer precisão absoluta.

Antes de implementar, decida quatro pontos. Peça permissão apenas depois de um clique claro. Use enableHighAccuracy: false por padrão. Ofereça busca manual por endereço, cidade ou CEP. Decida se as coordenadas serão guardadas; muitas vezes basta salvar a zona de atendimento ou a loja selecionada.

DecisãoPadrão recomendadoFalha comum
MomentoApós ação do usuárioPedir permissão ao carregar
PrecisãoAlta precisão desligadaGPS para qualquer lista
FallbackCEP, cidade ou endereçoBloquear usuário que negou
LogsEventos e bucketsCoordenadas brutas no analytics

Também separe mapa de localização. Geolocation devolve coordenadas. Renderizar mapa, geocodificar endereço, calcular rota e buscar locais próximos é responsabilidade de Google Maps, Mapbox, OpenStreetMap ou do seu backend.

Casos de uso concretos

O primeiro caso é busca de lojas. O usuário clica em “usar minha localização” e o app ordena resultados por distância. O campo de CEP deve estar visível junto do botão, porque negar permissão não significa abandonar a compra.

O segundo caso é entrega ou serviço em domicílio. Mercado, reparo, aluguel e atendimento local podem verificar se o usuário está dentro da área e mostrar horários disponíveis. Em geral, basta guardar inside_zone, faixa de distância ou loja responsável.

O terceiro caso é check-in de equipe de campo. Limpeza, manutenção, eventos e vendas podem confirmar proximidade do local. Quando a localização falha, o fluxo precisa aceitar foto, aprovação de supervisor ou observação manual.

O quarto caso é conteúdo local. Clima, eventos, estoque próximo e avisos regionais podem usar localização. Se cidade ou região bastam, uma preferência salva é melhor do que localização precisa ao vivo.

Exemplo getCurrentPosition para copiar

Salve como geo-demo.html e rode em localhost ou HTTPS. O exemplo mostra explicação, timeout, cache, arredondamento e fallback manual.

<!doctype html>
<html lang="pt">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>Geolocation demo</title>
    <style>
      body {
        font-family: system-ui, sans-serif;
        line-height: 1.6;
        margin: 2rem;
      }
      button,
      input {
        font: inherit;
        padding: 0.7rem 0.9rem;
      }
      .panel {
        border: 1px solid #ddd;
        max-width: 36rem;
        padding: 1rem;
      }
    </style>
  </head>
  <body>
    <main class="panel">
      <h1>Encontrar lojas próximas</h1>
      <p>
        Usamos sua localização apenas para ordenar lojas.
        Não salvamos endereço exato nem histórico.
      </p>

      <button id="useLocation" type="button">Usar minha localização</button>
      <p id="status" role="status" aria-live="polite"></p>
      <pre id="result"></pre>

      <form id="manualForm">
        <label for="postcode">CEP, cidade ou endereço</label>
        <input id="postcode" name="postcode" autocomplete="postal-code" />
        <button type="submit">Buscar manualmente</button>
      </form>
    </main>

    <script type="module">
      const status = document.querySelector("#status");
      const result = document.querySelector("#result");
      const button = document.querySelector("#useLocation");
      const form = document.querySelector("#manualForm");

      function showManual(reason) {
        status.textContent =
          `${reason}. Também é possível buscar por CEP ou cidade.`;
      }

      function onSuccess(position) {
        const { latitude, longitude, accuracy } = position.coords;
        status.textContent = "Localização recebida.";
        result.textContent = JSON.stringify(
          {
            lat: Number(latitude.toFixed(5)),
            lng: Number(longitude.toFixed(5)),
            accuracyMeters: Math.round(accuracy),
          },
          null,
          2,
        );
      }

      function onError(error) {
        const messages = {
          1: "A permissão de localização foi negada",
          2: "A posição do dispositivo está indisponível",
          3: "A solicitação de localização expirou",
        };
        showManual(messages[error.code] ?? "Localização indisponível");
      }

      button.addEventListener("click", () => {
        if (!("geolocation" in navigator)) {
          showManual("Este navegador não suporta Geolocation");
          return;
        }

        status.textContent = "Verificando permissão de localização...";
        navigator.geolocation.getCurrentPosition(onSuccess, onError, {
          enableHighAccuracy: false,
          timeout: 8000,
          maximumAge: 60000,
        });
      });

      form.addEventListener("submit", (event) => {
        event.preventDefault();
        const data = new FormData(form);
        status.textContent =
          `Buscando perto de "${data.get("postcode")}".`;
      });
    </script>
  </body>
</html>

timeout limita a espera, maximumAge aceita uma posição em cache e enableHighAccuracy pede maior precisão quando possível. Use cache maior para busca de lojas e cache menor para check-in.

watchPosition com limpeza

watchPosition envia atualizações contínuas. Ele serve para rotas e acompanhamento ativo, não para uma busca pontual. Sempre chame clearWatch ao encerrar.

import { useEffect, useRef, useState } from "react";

type LocationPoint = {
  lat: number;
  lng: number;
  accuracy: number;
  at: string;
};

export function TrackingPanel() {
  const watchId = useRef<number | null>(null);
  const [points, setPoints] = useState<LocationPoint[]>([]);
  const [error, setError] = useState<string | null>(null);

  function start() {
    if (!navigator.geolocation || watchId.current !== null) return;

    watchId.current = navigator.geolocation.watchPosition(
      (position) => {
        const { latitude, longitude, accuracy } = position.coords;
        setPoints((current) => [
          {
            lat: Number(latitude.toFixed(5)),
            lng: Number(longitude.toFixed(5)),
            accuracy: Math.round(accuracy),
            at: new Date(position.timestamp).toISOString(),
          },
          ...current.slice(0, 9),
        ]);
      },
      (err) => setError(`Falha no rastreamento: ${err.code}`),
      {
        enableHighAccuracy: true,
        timeout: 10000,
        maximumAge: 5000,
      },
    );
  }

  function stop() {
    if (watchId.current === null) return;
    navigator.geolocation.clearWatch(watchId.current);
    watchId.current = null;
  }

  useEffect(() => stop, []);

  return (
    <section>
      <button type="button" onClick={start}>Iniciar rastreamento</button>
      <button type="button" onClick={stop}>Parar</button>
      {error && <p role="alert">{error}</p>}
      <ol>
        {points.map((point) => (
          <li key={point.at}>
            {point.lat}, {point.lng}
            {" / "}
            {point.accuracy}m
          </li>
        ))}
      </ol>
    </section>
  );
}

Rastreamento precisa ter estados visíveis: iniciar, pausar e finalizar. Também defina retenção, acesso e remoção dos dados.

Privacidade e logs

Latitude e longitude não devem ser logs comuns. Elas podem ir para monitoramento, analytics, replay de sessão ou suporte. Prefira eventos e agrupamentos.

type GeoLogInput = {
  lat: number;
  lng: number;
  accuracy: number;
  permission: "granted" | "prompt" | "denied" | "unknown";
};

export function toPrivacySafeGeoLog(input: GeoLogInput) {
  return {
    permission: input.permission,
    accuracyBucket:
      input.accuracy <= 50 ? "high" :
      input.accuracy <= 500 ? "medium" : "low",
    latBucket: Number(input.lat.toFixed(2)),
    lngBucket: Number(input.lng.toFixed(2)),
  };
}

Para análise, eventos como permission_denied, manual_search_used, timeout e results_shown normalmente bastam. Inclua no prompt para Claude Code: “não registrar latitude e longitude brutas”.

Permissions API pode ler granted, prompt e denied, mas o prompt real aparece quando Geolocation é chamado.

export async function readGeoPermission() {
  if (!("permissions" in navigator)) return "unknown";

  try {
    const status = await navigator.permissions.query({
      name: "geolocation",
    });
    return status.state;
  } catch {
    return "unknown";
  }
}

Falhas e testes

Teste HTTP, HTTPS e iframe. Geolocation exige contexto seguro e pode ser bloqueada por Permissions-Policy.

Teste permissão negada. O fluxo deve ir para entrada manual sem insistir no prompt.

Teste timeout e localização indisponível. Desktop, interiores, VPN, localização do sistema desligada e navegador corporativo podem falhar.

Teste cache antigo. maximumAge ajuda performance, mas pode ser ruim para check-in.

import { expect, test } from "@playwright/test";

test.use({
  geolocation: {
    latitude: -23.55052,
    longitude: -46.633308,
    accuracy: 50,
  },
  permissions: ["geolocation"],
});

test("shows nearby stores from mocked location", async ({ page }) => {
  await page.goto("/stores");
  await page.getByRole("button", { name: "Usar minha localização" }).click();
  await expect(page.getByText("Localização recebida")).toBeVisible();
});

Prompt seguro para Claude Code

Use um prompt com escopo, restrições e verificação.

claude <<'PROMPT'
Implement a beginner-friendly Geolocation feature.

Scope:
- Edit only src/features/location and related tests.
- Do not change billing, analytics, or map provider config.
- Preserve existing API keys and environment variable names.

Requirements:
- Request location only after the user clicks a button.
- Explain why location is needed before the browser prompt.
- Use getCurrentPosition with timeout and maximumAge.
- Add manual postcode/address fallback for denied or timeout cases.
- Do not log raw latitude or longitude.
- Add a Playwright test with mocked geolocation.
- Return a short verification checklist.
PROMPT

Em equipe, limite permissões para proteger .env e evitar push automático.

{
  "permissions": {
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)",
      "Bash(git push *)"
    ],
    "allow": [
      "Bash(npm test *)",
      "Bash(npm run lint)"
    ]
  }
}

Para transformar isso em padrão de equipe, checklist de revisão ou prompt específico do seu repositório, a página Claude Code training and consultation é o próximo passo.

Nota de verificação

Verifiquei os exemplos no Chrome em localhost, com DevTools Sensors em São Paulo e “Location unavailable”, e com Playwright concedendo permissão de geolocalização. Antes de publicar, teste permissão negada, localização do sistema desligada, iframe, quota do provedor de mapas e ausência de coordenadas brutas nos logs.

#Claude Code #Geolocation #geolocalizacao #mapa #Web API
Grátis

PDF grátis: cheatsheet do Claude Code

Informe seu e-mail e baixe uma página com comandos, hábitos de revisão e workflows seguros.

Cuidamos dos seus dados e não enviamos spam.

Masa

Sobre o autor

Masa

Engenheiro focado em workflows práticos com Claude Code.