# Como validar CPF em aplicações Svelte e SvelteKit

> Aprenda a integrar validação de CPF em aplicações Svelte e SvelteKit usando a API do CPFHub.io, com exemplos de componentes e server routes.

**Publicado:** 16/07/2024
**Autor:** Redação CPFHub.io
**URL:** https://cpfhub.io/blog/como-validar-cpf-em-aplicacoes-svelte-e-sveltekit

---


Para validar CPF em aplicações Svelte e SvelteKit, crie uma server route em `src/routes/api/cpf/[cpf]/+server.ts` que chama a API do CPFHub.io com o header `x-api-key` — mantendo a chave segura no servidor via `$env/static/private` — e consuma esse endpoint no componente Svelte com validação local dos dígitos antes da requisição. O resultado é um fluxo de validação completo, com progressive enhancement via form actions e feedback visual em tempo real.

## Introdução

O Svelte e o SvelteKit vêm ganhando adoção significativa entre desenvolvedores web, oferecendo uma abordagem compilada que resulta em aplicações mais leves e rápidas que frameworks tradicionais. Para projetos brasileiros que utilizam Svelte, a validação de CPF é uma funcionalidade recorrente -- seja em formulários de cadastro, checkout de e-commerce ou sistemas internos de gestão.

---

## Pré-requisitos

* **Node.js 18+** -- Necessário para rodar o SvelteKit.

* **Projeto SvelteKit** -- Se ainda não tem, crie um com `npm create svelte@latest`.

* **Conta no CPFHub.io** -- Crie uma conta gratuita em [cpfhub.io](https://www.cpfhub.io/)

### Configuração do ambiente

Crie um arquivo `.env` na raiz do projeto:

```
CPFHUB_API_KEY=SUA_CHAVE_DE_API
```

---

## Entendendo a API

Para referência, a chamada à API do CPFHub.io:

```bash
curl -X GET https://api.cpfhub.io/cpf/12345678900 \
 -H "x-api-key: SUA_CHAVE_DE_API" \
 -H "Accept: application/json"
```

Resposta:

```json
{
 "success": true,
 "data": {
 "cpf": "12345678900",
 "name": "João da Silva",
 "nameUpper": "JOAO DA SILVA",
 "gender": "M",
 "birthDate": "15/06/1990",
 "day": 15,
 "month": 6,
 "year": 1990
 }
}
```

---

## Server route para consulta de CPF

No SvelteKit, as server routes (arquivos +server.ts ou +server.js) executam no servidor, protegendo a chave de API. Crie o arquivo `src/routes/api/cpf/[cpf]/+server.ts`:

```typescript
import { json, error } from '@sveltejs/kit';
import { CPFHUB_API_KEY } from '$env/static/private';
import type { RequestHandler } from './$types';

interface CPFData {
 cpf: string;
 name: string;
 nameUpper: string;
 gender: string;
 birthDate: string;
 day: number;
 month: number;
 year: number;
}

interface CPFHubResponse {
 success: boolean;
 data?: CPFData;
}

export const GET: RequestHandler = async ({ params }) => {
 const cpf = params.cpf.replace(/\D/g, '');

 if (cpf.length !== 11) {
 throw error(400, 'CPF deve ter 11 dígitos');
 }

 try {
 const response = await fetch(
 `https://api.cpfhub.io/cpf/${cpf}`,
 {
 headers: {
 'x-api-key': CPFHUB_API_KEY,
 'Accept': 'application/json'
 },
 signal: AbortSignal.timeout(10000)
 }
 );

 if (response.status === 401) {
 throw error(500, 'Erro de configuração da API');
 }

 const dados: CPFHubResponse = await response.json();

 if (!dados.success) {
 throw error(404, 'CPF não encontrado');
 }

 return json({
 success: true,
 data: dados.data
 });

 } catch (err) {
 if (err && typeof err === 'object' && 'status' in err) {
 throw err;
 }
 throw error(500, 'Falha na consulta de CPF');
 }
};
```

---

## Componente Svelte de validação de CPF

Crie o componente `src/lib/components/CPFValidator.svelte`:

```svelte
<script lang="ts">
 let cpf = '';
 let resultado: {
 nome?: string;
 nascimento?: string;
 genero?: string;
 } | null = null;
 let erro = '';
 let carregando = false;

 function formatarCPF(valor: string): string {
 const numeros = valor.replace(/\D/g, '').substring(0, 11);
 if (numeros.length > 9) {
 return numeros.replace(/(\d{3})(\d{3})(\d{3})(\d{2})/, '$1.$2.$3-$4');
 } else if (numeros.length > 6) {
 return numeros.replace(/(\d{3})(\d{3})(\d{1,3})/, '$1.$2.$3');
 } else if (numeros.length > 3) {
 return numeros.replace(/(\d{3})(\d{1,3})/, '$1.$2');
 }
 return numeros;
 }

 function handleInput(event: Event) {
 const input = event.target as HTMLInputElement;
 cpf = formatarCPF(input.value);
 resultado = null;
 erro = '';
 }

 async function validarCPF() {
 const cpfLimpo = cpf.replace(/\D/g, '');

 if (cpfLimpo.length !== 11) {
 erro = 'CPF deve ter 11 dígitos.';
 return;
 }

 carregando = true;
 erro = '';
 resultado = null;

 try {
 const response = await fetch(`/api/cpf/${cpfLimpo}`);
 const dados = await response.json();

 if (response.ok && dados.success) {
 resultado = {
 nome: dados.data.name,
 nascimento: dados.data.birthDate,
 genero: dados.data.gender === 'M' ? 'Masculino' : 'Feminino'
 };
 } else {
 erro = dados.message || 'CPF não encontrado.';
 }
 } catch (e) {
 erro = 'Erro ao validar CPF. Tente novamente.';
 } finally {
 carregando = false;
 }
 }
</script>

<div class="cpf-validator">
 <label for="cpf-input">CPF</label>
 <div class="input-group">
 <input
 id="cpf-input"
 type="text"
 value={cpf}
 on:input={handleInput}
 placeholder="000.000.000-00"
 inputmode="numeric"
 maxlength="14"
 />
 <button on:click={validarCPF} disabled={carregando}>
 {carregando ? 'Validando...' : 'Validar'}
 </button>
 </div>

 {#if erro}
 <p class="erro">{erro}</p>
 {/if}

 {#if resultado}
 <div class="resultado">
 <p><strong>Nome:</strong> {resultado.nome}</p>
 <p><strong>Nascimento:</strong> {resultado.nascimento}</p>
 <p><strong>Gênero:</strong> {resultado.genero}</p>
 </div>
 {/if}
</div>

<style>
 .cpf-validator {
 max-width: 400px;
 }
 .input-group {
 display: flex;
 gap: 8px;
 }
 input {
 flex: 1;
 padding: 8px 12px;
 border: 1px solid #ccc;
 border-radius: 6px;
 font-size: 16px;
 }
 button {
 padding: 8px 16px;
 background: #2563eb;
 color: white;
 border: none;
 border-radius: 6px;
 cursor: pointer;
 }
 button:disabled {
 opacity: 0.6;
 cursor: not-allowed;
 }
 .erro {
 color: #dc2626;
 margin-top: 8px;
 }
 .resultado {
 margin-top: 12px;
 padding: 12px;
 background: #f0fdf4;
 border: 1px solid #22c55e;
 border-radius: 6px;
 }
</style>
```

---

## Usando o componente em uma página

Crie ou edite `src/routes/cadastro/+page.svelte`:

```svelte
<script>
 import CPFValidator from '$lib/components/CPFValidator.svelte';
</script>

<h1>Cadastro</h1>
<CPFValidator />
```

---

## Validação com SvelteKit form actions

Para formulários que usam form actions (progressive enhancement), crie `src/routes/cadastro/+page.server.ts`:

```typescript
import { fail } from '@sveltejs/kit';
import { CPFHUB_API_KEY } from '$env/static/private';
import type { Actions } from './$types';

export const actions: Actions = {
 validar: async ({ request }) => {
 const formData = await request.formData();
 const cpf = (formData.get('cpf') as string).replace(/\D/g, '');

 if (cpf.length !== 11) {
 return fail(400, { cpf, erro: 'CPF deve ter 11 dígitos' });
 }

 try {
 const response = await fetch(
 `https://api.cpfhub.io/cpf/${cpf}`,
 {
 headers: {
 'x-api-key': CPFHUB_API_KEY,
 'Accept': 'application/json'
 },
 signal: AbortSignal.timeout(10000)
 }
 );

 const dados = await response.json();

 if (!dados.success) {
 return fail(404, { cpf, erro: 'CPF não encontrado' });
 }

 return {
 sucesso: true,
 dados: dados.data
 };

 } catch (e) {
 return fail(500, { cpf, erro: 'Falha na validação' });
 }
 }
};
```

---

## Validação local com store reativo

Crie um store Svelte para validação local de CPF em `src/lib/stores/cpf.ts`:

```typescript
import { writable, derived } from 'svelte/store';

export const cpfInput = writable('');

export const cpfLimpo = derived(cpfInput, ($cpf) =>
 $cpf.replace(/\D/g, '')
);

export const cpfValido = derived(cpfLimpo, ($cpf) => {
 if ($cpf.length !== 11) return false;
 if (/^(\d)\1{10}$/.test($cpf)) return false;

 let soma = 0;
 for (let i = 0; i < 9; i++) {
 soma += parseInt($cpf[i]) * (10 - i);
 }
 let resto = (soma * 10) % 11;
 if (resto === 10) resto = 0;
 if (resto !== parseInt($cpf[9])) return false;

 soma = 0;
 for (let i = 0; i < 10; i++) {
 soma += parseInt($cpf[i]) * (11 - i);
 }
 resto = (soma * 10) % 11;
 if (resto === 10) resto = 0;
 if (resto !== parseInt($cpf[10])) return false;

 return true;
});
```

---

## Boas práticas

* **Chave de API no servidor** -- Use `$env/static/private` do SvelteKit para garantir que a chave nunca seja exposta no cliente.

* **Validação em camadas** -- Valide os dígitos localmente no componente antes de chamar a server route.

* **Progressive enhancement** -- Use form actions para que o formulário funcione mesmo sem JavaScript habilitado.

* **Feedback visual** -- Mostre estados de carregamento, sucesso e erro de forma clara para o usuário.

* **Controle de consumo** -- Desabilite o botão durante o carregamento para evitar requisições duplicadas. O CPFHub.io não bloqueia ao atingir o limite do plano — cobra R$0,15 por consulta adicional —, então evitar requisições desnecessárias protege tanto a experiência quanto o orçamento.

---

## Perguntas frequentes

### Como o SvelteKit protege a chave de API do CPFHub.io?

O SvelteKit separa código de servidor e cliente em tempo de build. Ao importar a chave via `$env/static/private`, o compilador garante que ela nunca seja incluída no bundle enviado ao navegador. Qualquer tentativa de usar uma variável `static/private` em um componente `.svelte` gera erro em tempo de build — uma proteção automática e auditável.

### Posso usar a validação de CPF diretamente no componente Svelte, sem server route?

Não é recomendado. Chamar a API do CPFHub.io diretamente do frontend exporia sua chave de API ao navegador. A server route atua como proxy seguro: o componente Svelte chama `/api/cpf/{cpf}` (sua rota interna), e apenas o servidor conhece a `x-api-key`. Essa arquitetura também permite adicionar cache e rate limiting no servidor sem tocar no componente.

### O componente funciona sem JavaScript habilitado no navegador?

Sim, quando implementado com form actions (o arquivo `+page.server.ts`). O SvelteKit suporta progressive enhancement nativamente: sem JavaScript, o formulário faz um POST tradicional e recebe a resposta do servidor; com JavaScript, a ação é interceptada e o resultado é exibido de forma reativa sem recarregar a página.

### Como armazenar o resultado da validação de CPF no estado global da aplicação Svelte?

Use o store reativo `cpfInput` e `cpfValido` demonstrados acima como ponto de partida. Para estado global mais complexo — como compartilhar o resultado de validação entre múltiplos componentes —, armazene o objeto `data` retornado pela API em um `writable` store e acesse-o via `$cpfStore` em qualquer componente que importe o store. Consulte a [documentação oficial do SvelteKit](https://kit.svelte.dev/docs/state-management) para padrões recomendados de gerenciamento de estado.

### Leia também

- [Como validar CPF no frontend com React e API REST](https://cpfhub.io/blog/como-validar-cpf-no-frontend-com-react-e-api-rest)
- [SLA de API de CPF: níveis de disponibilidade e o que exigir do seu provedor](https://cpfhub.io/blog/sla-api-cpf-niveis-disponibilidade)
- [API de CPF grátis para desenvolvedores: como começar em 5 minutos](https://cpfhub.io/blog/api-cpf-gratis-desenvolvedores-comecar-5-minutos)
- [10 erros mais comuns ao integrar uma API de CPF e como evitá-los](https://cpfhub.io/blog/10-erros-mais-comuns-ao-integrar-uma-api-de-cpf)

---

## Conclusão

O Svelte e o SvelteKit oferecem uma experiência de desenvolvimento fluida para integrar validação de CPF, com componentes reativos, server routes seguras e form actions com progressive enhancement. A API do CPFHub.io complementa esse stack com um endpoint simples, resposta em ~900ms e planos que escalam do desenvolvimento à produção sem mudanças de código.

Cadastre-se em [cpfhub.io](https://www.cpfhub.io/) — 50 consultas mensais gratuitas, sem cartão de crédito — e adicione validação de CPF ao seu projeto Svelte em menos de 30 minutos.

