SvelteKit é o framework full-stack do ecossistema Svelte que combina renderização server-side, roteamento baseado em arquivos e um modelo de dados elegante com load functions e form actions. Para integrar a API de CPF da CPFHub.io, a chave de API fica protegida em +page.server.ts — nunca exposta ao cliente — enquanto o formulário funciona com ou sem JavaScript graças ao mecanismo de form actions.
Estrutura do projeto SvelteKit
O SvelteKit utiliza roteamento baseado em arquivos. Para nossa integração com a API de CPF, criaremos a seguinte estrutura:
src/
lib/
server/
cpfhub.ts # Servico de consulta (server-only)
routes/
consulta-cpf/
+page.svelte # Interface do formulario
+page.server.ts # Load function e form actions
A separação entre +page.svelte (frontend) e +page.server.ts (backend) é fundamental. O arquivo +page.server.ts executa exclusivamente no servidor, garantindo que a chave de API nunca seja exposta ao cliente.
Serviço de consulta no servidor
Primeiro, criamos o módulo que encapsula a comunicação com a API da CPFHub.io
// src/lib/server/cpfhub.ts
import { CPFHUB_API_KEY } from "$env/static/private";
interface CPFData {
cpf: string;
name: string;
nameUpper: string;
gender: string;
birthDate: string;
day: number;
month: number;
year: number;
}
interface CPFResponse {
success: boolean;
data?: CPFData;
}
export async function consultarCPF(cpf: string): Promise<CPFResponse> {
const cpfLimpo = cpf.replace(/\D/g, "");
if (cpfLimpo.length !== 11) {
throw new Error("CPF deve conter 11 digitos");
}
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 10000);
try {
const response = await fetch(
`https://api.cpfhub.io/cpf/${cpfLimpo}`,
{
method: "GET",
headers: {
"x-api-key": CPFHUB_API_KEY,
"Accept": "application/json"
},
signal: controller.signal
}
);
clearTimeout(timeout);
if (!response.ok) {
throw new Error(`API retornou status ${response.status}`);
}
return await response.json();
} catch (error) {
clearTimeout(timeout);
if (error instanceof Error && error.name === "AbortError") {
throw new Error("Timeout na consulta de CPF");
}
throw error;
}
}
Note o uso de $env/static/private — um recurso do SvelteKit que garante que variáveis de ambiente privadas nunca sejam acessíveis no cliente. A chave CPFHUB_API_KEY deve estar no arquivo .env do projeto.
Form action para processar a consulta
O form action é o mecanismo do SvelteKit para processar formulários no servidor. Ele funciona mesmo sem JavaScript habilitado no navegador, o que melhora a acessibilidade e a resiliência da aplicação. Consulte a documentação oficial do SvelteKit para a referência completa de form actions:
// src/routes/consulta-cpf/+page.server.ts
import type { Actions, PageServerLoad } from "./$types";
import { fail } from "@sveltejs/kit";
import { consultarCPF } from "$lib/server/cpfhub";
export const load: PageServerLoad = async () => {
return {
titulo: "Consulta de CPF",
descricao: "Informe o CPF para consultar os dados cadastrais."
};
};
export const actions: Actions = {
consultar: async ({ request }) => {
const formData = await request.formData();
const cpf = formData.get("cpf")?.toString() ?? "";
// Validacao basica no servidor
const cpfLimpo = cpf.replace(/\D/g, "");
if (cpfLimpo.length !== 11) {
return fail(400, {
cpf,
erro: "CPF invalido. Informe 11 digitos."
});
}
try {
const resultado = await consultarCPF(cpfLimpo);
if (!resultado.success || !resultado.data) {
return fail(404, {
cpf,
erro: "CPF nao encontrado na base de dados."
});
}
return {
cpf,
sucesso: true,
dados: {
nome: resultado.data.name,
genero: resultado.data.gender,
dataNascimento: resultado.data.birthDate
}
};
} catch (error) {
const mensagem = error instanceof Error
? error.message
: "Erro desconhecido";
return fail(500, {
cpf,
erro: `Falha na consulta: ${mensagem}`
});
}
}
};
O form action consultar valida o CPF, chama a API e retorna os dados ou uma mensagem de erro. O uso de fail() permite retornar erros com status HTTP apropriados.
Interface com Svelte
O componente Svelte renderiza o formulário e exibe os resultados. O SvelteKit cuida da comunicação com o form action automaticamente:
<!-- src/routes/consulta-cpf/+page.svelte -->
<script lang="ts">
import type { PageData, ActionData } from "./$types";
import { enhance } from "$app/forms";
export let data: PageData;
export let form: ActionData;
let carregando = false;
function formatarCPF(valor: string): string {
const digitos = valor.replace(/\D/g, "").slice(0, 11);
if (digitos.length <= 3) return digitos;
if (digitos.length <= 6) return `${digitos.slice(0, 3)}.${digitos.slice(3)}`;
if (digitos.length <= 9)
return `${digitos.slice(0, 3)}.${digitos.slice(3, 6)}.${digitos.slice(6)}`;
return `${digitos.slice(0, 3)}.${digitos.slice(3, 6)}.${digitos.slice(6, 9)}-${digitos.slice(9)}`;
}
let cpfInput = form?.cpf ?? "";
function handleInput(event: Event) {
const target = event.target as HTMLInputElement;
cpfInput = formatarCPF(target.value);
target.value = cpfInput;
}
</script>
<svelte:head>
<title>{data.titulo}</title>
</svelte:head>
<main>
<h2>{data.titulo}</h2>
<p>{data.descricao}</p>
<form
method="POST"
action="?/consultar"
use:enhance={() => {
carregando = true;
return async ({ update }) => {
carregando = false;
await update();
};
}}
>
<label for="cpf">CPF:</label>
<input
id="cpf"
name="cpf"
type="text"
value={cpfInput}
on:input={handleInput}
placeholder="000.000.000-00"
maxlength="14"
required
/>
<button type="submit" disabled={carregando}>
{carregando ? "Consultando..." : "Consultar CPF"}
</button>
</form>
{#if form?.erro}
<div class="erro" role="alert">
<p>{form.erro}</p>
</div>
{/if}
{#if form?.sucesso && form?.dados}
<div class="resultado">
<h3>Dados encontrados</h3>
<dl>
<dt>Nome</dt>
<dd>{form.dados.nome}</dd>
<dt>Genero</dt>
<dd>{form.dados.genero === "M" ? "Masculino" : "Feminino"}</dd>
<dt>Data de nascimento</dt>
<dd>{form.dados.dataNascimento}</dd>
</dl>
</div>
{/if}
</main>
O use:enhance transforma o formulário em uma experiência de SPA quando JavaScript está disponível, mas o formulário continua funcionando sem JavaScript — o SvelteKit faz o POST tradicional e re-renderiza a página.
Adicionando validação com Zod
Para validações mais robustas, podemos integrar Zod no form action:
// src/routes/consulta-cpf/schema.ts
import { z } from "zod";
export const cpfSchema = z.object({
cpf: z
.string()
.transform((val) => val.replace(/\D/g, ""))
.refine((val) => val.length === 11, "CPF deve ter 11 digitos")
.refine((val) => !/^(\d)\1+$/.test(val), "CPF invalido")
});
E no form action, substituímos a validação manual:
// Dentro do form action
const parsed = cpfSchema.safeParse({ cpf });
if (!parsed.success) {
return fail(400, {
cpf,
erro: parsed.error.errors[0].message
});
}
const resultado = await consultarCPF(parsed.data.cpf);
Proteção com rate limiting
Para evitar abusos na sua própria aplicação, implemente rate limiting no form action usando um Map simples ou uma solução como sveltekit-rate-limiter:
const tentativas = new Map<string, { count: number; resetAt: number }>();
function verificarRateLimit(ip: string): boolean {
const agora = Date.now();
const registro = tentativas.get(ip);
if (!registro || registro.resetAt < agora) {
tentativas.set(ip, { count: 1, resetAt: agora + 60000 });
return true;
}
if (registro.count >= 5) {
return false;
}
registro.count++;
return true;
}
Variáveis de ambiente no SvelteKit
O SvelteKit oferece quatro módulos para variáveis de ambiente:
| Módulo | Servidor | Cliente | Tipo |
|---|---|---|---|
$env/static/private | Sim | Não | Estático |
$env/static/public | Sim | Sim | Estático |
$env/dynamic/private | Sim | Não | Dinâmico |
$env/dynamic/public | Sim | Sim | Dinâmico |
Para a chave de API da CPFHub.io, use sempre $env/static/private ou $env/dynamic/private. Nunca exponha a chave no cliente.
Perguntas frequentes
Como o SvelteKit protege a chave de API da CPFHub.io?
O arquivo +page.server.ts executa exclusivamente no servidor — nunca no navegador. Ao importar a chave via $env/static/private, o SvelteKit garante em tempo de build que essa variável não vaze para o bundle do cliente. A chave fica segura mesmo em aplicações SSR ou com hydration ativa.
O formulário de consulta de CPF funciona sem JavaScript?
Sim. O mecanismo de form actions do SvelteKit funciona como um POST HTML tradicional quando o JavaScript não está disponível. O use:enhance é uma progressiva enhancement: ele melhora a experiência em browsers modernos, mas o fluxo de validação server-side funciona de qualquer forma.
Como tratar erros de timeout na chamada à API de CPF?
A latência da CPFHub.io é de aproximadamente 900ms. Defina o timeout do AbortController em 10 segundos para cobrir variações de rede sem impactar o usuário. No form action, capture o AbortError e retorne um fail(500, { erro: "Timeout na consulta" }) — o SvelteKit re-renderiza o formulário com a mensagem de erro automaticamente.
Como limitar o número de consultas por usuário no SvelteKit?
Implemente rate limiting no form action usando o IP do cliente (disponível em request.headers.get("x-forwarded-for")). Uma estrutura Map<string, { count, resetAt }> resolve o caso básico. Para produção com múltiplas instâncias, use Redis ou um KV store distribuído — o pacote sveltekit-rate-limiter abstrai essa lógica.
Conclusão
O SvelteKit oferece uma combinação poderosa de load functions e form actions que torna a integração com APIs externas como a CPFHub.io direta e segura.
Cadastre-se em cpfhub.io
CPFHub.io
Pronto para integrar a API?
50 consultas gratuitas para testar agora. Sem cartão de crédito. Acesso imediato à documentação.
Sobre a redação
Redação CPFHub.io
Time editorial especializado em APIs de CPF, identidade digital e compliance no mercado brasileiro. Produzimos guias técnicos, análises regulatórias e tutoriais sobre LGPD e KYC para desenvolvedores e líderes de produto.



