Pular para o conteúdo
Operating Intelligence 10 min de leitura

Svelte 5 e SvelteKit: uma loja leve e rápida no celular

O Svelte manda menos código para o celular do cliente. A página abre mais rápido, e a velocidade ajuda a sua loja a aparecer na busca e na resposta da IA.

AC

Alexandre Caramaschi

Founder da Brasil GEO, ex-CMO da Semantix (Nasdaq), cofundador da AI Brasil

Atualizado em 16 de junho de 2026

Este guia mostra como o Svelte 5 e o SvelteKit deixam a sua loja on-line leve no celular do cliente. Você vai ver o que essa escolha economiza, o que ela entrega ao robô do Google e quando ela vale a pena.

Pense numa loja de artigos de papelaria com milhares de itens. A tela precisa de filtro, variação de produto, carrinho, cupom e frete. E precisa abrir rápido num celular comum, numa conexão instável. Esse cenário acompanha o guia até o fim.

Cada pedaço de programa enviado ao celular atrasa a primeira abertura da página. Isso custa venda e custa presença na busca. O Svelte 5 ataca esse ponto: ele resolve na hora de gerar o site o que os outros deixam para o celular resolver.

A loja se monta com três peças: as runes do Svelte 5, o catálogo montado no servidor e os formulários que funcionam sem depender do celular. Juntas, elas melhoram a velocidade da página e a chance de a sua loja ser citada pela IA.

As camadas do storefront, da tela ao servidor

  1. 1
    Componentes com runes$state, $derived, $props e $effect cuidam do estado no cliente
  2. 2
    SnippetsMarcação reutilizável dentro do mesmo componente
  3. 3
    Form actions e use:enhanceO POST é processado no servidor, com ou sem JavaScript
  4. 4
    load() em +page.server.tsDados carregados no servidor; o HTML chega já preenchido

Por que isso deixa a sua loja mais rápida?

Porque o celular do seu cliente recebe menos código e trabalha menos. Os outros programas mandam junto um motor que, a cada mudança, compara a tela inteira para descobrir o que mudou.

O Svelte faz essa conta antes, na hora de gerar o site. Ele já sabe onde o valor muda e escreve a instrução exata para trocar só aquele pedaço da tela.

Virtual DOM e compilador

Framework com virtual DOM

  • Runtime embarcado que diffa árvores de componentes a cada atualização
  • Mais JavaScript enviado ao navegador
  • Primeiro carregamento mais lento no 4G instável

Svelte 5

  • Reatividade resolvida durante o build
  • Instruções diretas só para os nós do DOM afetados
  • Bundle inicial menor e thread principal menos ocupada

Na prática, o pacote que chega ao celular fica menor e o aparelho fica mais livre. Numa vitrine com muitos produtos, isso aparece nos dois números de velocidade que o Google usa como sinal de qualidade. São o tempo até a página aparecer e o tempo de resposta ao toque.

Um catálogo que abre rápido e responde ao toque sem travar vira sinal de qualidade. A busca do Google e os assistentes de IA usam esse sinal para decidir se vale a pena guardar e citar a sua loja.

O que são as runes e para que elas servem?

São palavras do próprio Svelte que começam com cifrão e dizem o que muda na tela. O $state guarda um valor que muda, o $derived calcula outro a partir dele, e o $props recebe o que vem de fora. Nada disso precisa ser importado.

As runes do Svelte 5

$stateDeclara estado reativo
$derivedDeriva valores; $derived.by para lógica que não cabe em uma expressão
$propsRecebe o que o componente ganha de fora
$effectEfeitos colaterais que tocam o mundo fora do componente

Como fica um item de carrinho com quantidade e subtotal?

O exemplo abaixo é um item de carrinho. O $state guarda a quantidade, o $derived recalcula o subtotal a cada mudança dela, e o $props recebe o nome e o preço do produto.

<script lang="ts">
  let { nome, precoUnitario } = $props();

  let quantidade = $state(1);
  let subtotal = $derived(quantidade * precoUnitario);
</script>

<div class="item">
  <span>{nome}</span>
  <button onclick={() => quantidade = Math.max(1, quantidade - 1)}>-</button>
  <strong>{quantidade}</strong>
  <button onclick={() => quantidade++}>+</button>
  <span>Subtotal: R$ {subtotal.toFixed(2)}</span>
</div>

Repare em dois detalhes do Svelte 5. O clique se escreve como um atributo simples, onclick={...}. E o subtotal dispensa qualquer aviso de que depende da quantidade, porque o $derived percebe isso sozinho ao ler o valor. Quando a quantidade muda, só o subtotal é repintado.

O que acontece quando a quantidade muda

  1. $props entrega nome e preço unitárioO componente recebe os dados de fora
  2. $state torna a quantidade reativaO onclick altera esse valor
  3. $derived recalcula o subtotalA dependência nasce ao ler quantidade e precoUnitario
  4. Só o texto do subtotal é repintadoNenhuma declaração manual de dependência

Como fica o filtro de produtos da vitrine?

Catálogo sem busca rápida esconde o próprio estoque. Aqui o $state guarda o que a pessoa digitou, o bind:value liga a caixa de busca a esse valor, e o $derived monta a lista filtrada. Para uma conta maior, existe o $derived.by.

<script lang="ts">
  let { produtos } = $props();

  let termo = $state('');

  let filtrados = $derived.by(() => {
    const q = termo.trim().toLowerCase();
    if (!q) return produtos;
    return produtos.filter((p) => p.nome.toLowerCase().includes(q));
  });
</script>

<input type="search" placeholder="Buscar produto" bind:value={termo} />

<ul>
  {#each filtrados as produto}
    <li>{produto.nome} — R$ {produto.preco.toFixed(2)}</li>
  {/each}
</ul>

A cada tecla, o valor digitado muda, a lista filtrada é recalculada e a vitrine repinta. Tudo isso sai do próprio Svelte, sem código extra para ouvir o teclado. Ele já sabe quais pedaços da tela dependem da lista.

O ciclo da busca a cada tecla

  1. 1
    bind:value atualiza termoTwo-way binding com o input
  2. 2
    $derived.by recomputa filtradosSem addEventListener, sem store, sem useMemo
  3. 3
    A lista repintaSó os nós que dependem de filtrados

Como salvar o carrinho quando o cliente recarrega a página?

Com o $effect, que serve para conversar com o mundo fora da tela. Ele fala com a memória do navegador, com a medição de acesso ou com outro sistema. Ele roda depois que a tela atualiza e volta a rodar quando o valor que ele lê muda.

$derived ou $effect

  • Seo valor é calculado a partir de outro estado
    então$derived
  • Seprecisa tocar o mundo fora do componente (localStorage, analytics, API do navegador)
    então$effect, que roda depois que o DOM atualiza
  • Seo carrinho precisa sobreviver ao recarregar a página
    então$effect que lê carrinho e grava no localStorage a cada alteração da lista

O caso mais comum numa loja é guardar o carrinho, para que os itens continuem lá quando o cliente recarregar a página.

<script lang="ts">
  let carrinho = $state<Array<{ id: string; qtd: number }>>([]);

  // Hidrata uma vez, no cliente.
  $effect(() => {
    const salvo = localStorage.getItem('carrinho');
    if (salvo) carrinho = JSON.parse(salvo);
  });

  // Persiste sempre que o carrinho muda.
  $effect(() => {
    localStorage.setItem('carrinho', JSON.stringify(carrinho));
  });
</script>

O segundo $effect lê o carrinho, então roda de novo a cada mudança na lista. Use o $effect com parcimônia: ele é a ponte para o lado de fora. Para calcular um valor a partir de outro, o lugar certo é o $derived. Confundir os dois é o erro mais comum de quem chega agora.

Como entregar o catálogo já pronto para o Google e para a IA?

Com a função load(), que roda no servidor e alimenta a página antes de mandá-la. A página chega ao navegador, e ao robô que a lê, já preenchida com os produtos. O SvelteKit faz isso por padrão.

Como o catálogo chega já renderizado

  1. A rota de categoria é pedidasrc/routes/categoria/[slug]
  2. load() roda no servidorEm +page.server.ts, busca os produtos
  3. data alimenta a página+page.svelte consome sem saber de onde os dados vieram
  4. O HTML chega preenchidoAo navegador e ao crawler, com nome, preço e descrição

No SvelteKit, cada endereço do site é uma pasta. O +page.svelte é a tela e o +page.server.ts busca os dados e trata os formulários. O +layout.svelte envolve as telas, e o +server.ts abre uma porta de comunicação. Veja uma página de categoria:

Os arquivos de uma rota em src/routes

+page.svelteA UI da página
+page.server.tsCarrega dados e trata formulários
+layout.svelteEnvolve as rotas
+server.tsDefine endpoints
// src/routes/categoria/[slug]/+page.server.ts
import type { PageServerLoad } from './$types';

export const load: PageServerLoad = async ({ params, fetch }) => {
  const resposta = await fetch(`https://api.minhaloja.com.br/categorias/${params.slug}/produtos`);
  const produtos = await resposta.json();

  return { produtos, slug: params.slug };
};

A tela usa os dados sem precisar saber de onde vieram. Como tudo foi resolvido no servidor, a primeira página já chega com os produtos dentro:

<!-- src/routes/categoria/[slug]/+page.svelte -->
<script lang="ts">
  let { data } = $props();
</script>

<h1>Categoria: {data.slug}</h1>

<ul>
  {#each data.produtos as produto}
    <li>{produto.nome} — R$ {produto.preco.toFixed(2)}</li>
  {/each}
</ul>

Isso decide a sua presença na resposta da IA. O robô do Google e a maioria dos coletores que alimentam os assistentes leem a página servida, sem rodar os programas pesados dela.

Se o catálogo só existisse depois que esses programas rodassem no celular, boa parte desses robôs veria uma página vazia. Com o catálogo montado no servidor, eles veem nome, preço e descrição, que é o material citado quando alguém pergunta qual loja vende aquele produto no Brasil.

Catálogo só no cliente e catálogo com SSR

Catálogo montado só pelo JavaScript

  • Crawlers e coletores de modelos generativos leem o HTML sem executar JavaScript pesado
  • Boa parte desses agentes vê uma página vazia

Catálogo com SSR

  • O HTML servido já contém nome, preço e descrição
  • É o material que um motor generativo cita quando alguém pergunta qual loja vende X no Brasil

Montar a página no servidor vale além do Google. Vale para qualquer robô que lê páginas, inclusive os assistentes que respondem às perguntas dos seus clientes antes de eles chegarem ao seu site.

Como fazer o formulário funcionar mesmo no celular fraco?

Com o envio tratado no servidor pelo +page.server.ts e a marca use:enhance no formulário. O servidor recebe e processa o envio. A marca acrescenta o comportamento melhor no celular, quando o aparelho dá conta.

O mesmo formulário com e sem JavaScript

123456Navegador sem JSNavegador com JSServidor
Envia o POSTmethod="POST" nativo
A action processaEm +page.server.ts
Página recarregaCom o resultado
use:enhance interceptaO envio não recarrega
A mesma action processaNada muda no servidor
UI atualizaSem recarregar a página

Veja o cadastro de e-mail, o pão com manteiga de qualquer loja que monta a própria lista de contatos:

// src/routes/+page.server.ts
import type { Actions } from './$types';
import { fail } from '@sveltejs/kit';

export const actions = {
  default: async ({ request }) => {
    const form = await request.formData();
    const email = String(form.get('email') ?? '');

    if (!email.includes('@')) {
      return fail(400, { email, erro: 'E-mail inválido.' });
    }

    // Aqui você grava o contato na sua base.
    return { sucesso: true };
  }
} satisfies Actions;

No componente, o formulário usa method="POST". Sem os programas da página, o navegador envia e recarrega a tela com o resultado. Com o use:enhance, a tela atualiza sem recarregar:

<!-- src/routes/+page.svelte -->
<script lang="ts">
  import { enhance } from '$app/forms';
  let { form } = $props();
</script>

<form method="POST" use:enhance>
  <input type="email" name="email" placeholder="Seu e-mail" required />
  <button type="submit">Quero novidades</button>

  {#if form?.erro}<p class="erro">{form.erro}</p>{/if}
  {#if form?.sucesso}<p class="ok">Inscrição confirmada.</p>{/if}
</form>

Esse é o coração da ideia: o básico funciona sozinho, e a experiência melhora quando o celular dá conta. Num checkout, isso vira robustez. O cliente com conexão ruim ou com bloqueador ligado ainda consegue comprar.

Como reaproveitar o mesmo card de produto na vitrine?

Com o {#snippet}, que define um pedaço de tela reutilizável, e o {@render}, que o desenha. No Svelte 5, esse recurso ocupa o lugar dos antigos encaixes para repetir marcação dentro de uma mesma tela.

<script lang="ts">
  let { produtos } = $props();
</script>

{#snippet cardProduto(p)}
  <article class="card">
    <h3>{p.nome}</h3>
    <p>R$ {p.preco.toFixed(2)}</p>
    <button onclick={() => console.log('adicionar', p.id)}>Adicionar</button>
  </article>
{/snippet}

<section class="grade">
  {#each produtos as produto}
    {@render cardProduto(produto)}
  {/each}
</section>

O pedaço chamado cardProduto recebe os dados do produto e é desenhado quantas vezes for preciso. Você deixa de criar um arquivo separado para um trecho pequeno e repetido, e o pacote final continua enxuto.

Slots antigos e snippets

Antes: slots ou componente separado

  • Arquivo de componente separado para um pedaço pequeno de marcação repetida
  • Slots para reúso de marcação

Svelte 5: snippets

  • {#snippet} define o trecho e {@render} o renderiza
  • Recebe argumentos como uma função
  • Árvore enxuta e bundle final menor

Quando o Svelte é a escolha certa para a sua loja?

Quando a tela tem muita interação e o peso dos programas no celular é um problema real do seu público. É o caso da vitrine com filtros, da página de produto com variações e carrinho, e do caminho até o pagamento.

A decisão honesta compara com os vizinhos. Para páginas de conteúdo com pouca interação, o Astro com islands entrega ainda menos código ao celular.

Se o seu time já trabalha em React e o produto é um painel pesado de retaguarda, o Next 16 com React 19 traz mais peças prontas. O comparativo lado a lado está em como escolher a stack de frontend para e-commerce.

Svelte, Astro ou Next

  • Sea rota tem muita interação por unidade de conteúdo e o peso do JavaScript no mobile é restrição real
    entãoSvelte 5 com SvelteKit: listagem com filtros, produto com variações, carrinho e checkout
  • Sea página é majoritariamente conteúdo editorial e marketing com pouca interação
    entãoAstro com islands entrega ainda menos JavaScript
  • Seo time já vive em React e o produto é um dashboard pesado de back-office
    entãoNext 16 com React 19 traz o ecossistema mais amplo

O Svelte ocupa o meio-termo. Ele é leve como uma página parada e confortável com muita interação. Para a loja de um negócio médio que precisa de velocidade sem abrir mão de filtro, carrinho e busca, essa combinação é difícil de bater.

Comece pequeno

  1. Reescreva a listagem de categoria em SvelteKitCom load() no servidor
  2. Adicione o filtro client-sideCom $derived
  3. Meça LCP e INP antes e depoisNum Android intermediário

O que fazer hoje

Comece pequeno. Reescreva uma página de categoria em SvelteKit, com os produtos buscados no servidor e o filtro rodando na tela. Meça a velocidade antes e depois num celular comum. Depois aprofunde nestes guias:

A loja de papelaria do começo tinha milhares de itens e um celular fraco do outro lado. Uma página que abre rápido, responde ao toque e chega pronta do servidor agrada o cliente e vira a fonte que os assistentes de IA preferem citar.

Perguntas frequentes

Serve para loja de verdade. A vantagem aparece justamente em catálogos com muita coisa clicável, porque o código gerado dispensa o motor pesado que os outros carregam. Lojas médias brasileiras com milhares de itens ganham em tempo de carga e em consumo de dados no celular.

Não precisa. As runes são poucos símbolos e ocupam o lugar de padrões que antes exigiam mais código. Quem já escrevia Svelte migra em dias, e quem chega agora aprende um modelo mais explícito desde o começo.

Entrega, por padrão. A função que busca os dados roda no servidor e devolve a página já preenchida com o catálogo. O robô do Google e os assistentes leem esse conteúdo sem precisar rodar os programas da página.

O Astro brilha em páginas de conteúdo com pouca interação. O Next domina painéis pesados em React e tem mais peças prontas. O Svelte entrega a loja mais leve quando a tela tem muito filtro, carrinho e busca.

Funciona. Um formulário com envio tratado no servidor já dá conta sozinho. A marca use:enhance acrescenta a camada melhor: ela evita o recarregamento e atualiza a tela quando o celular dá conta.

Para levar deste guia

  1. O Svelte resolve na hora de gerar o site o que os outros deixam para o celular resolver. Chega menos código ao cliente.

  2. As runes deixam claro o que muda na tela: a quantidade do carrinho, o filtro da vitrine e o total da compra.

  3. O SvelteKit monta o catálogo no servidor. A página chega pronta e o robô do Google e a IA conseguem ler.

  4. O formulário funciona mesmo quando o celular do cliente não dá conta dos programas da página.

  5. Velocidade vira sinal de qualidade. Ela ajuda a busca comum e a citação da sua loja pelos assistentes de IA.

Formações gratuitas do portal de educação de Alexandre Caramaschi, fundador da Brasil GEO.

Leve a decisão para o seu contexto

Este guia dá o mapa. Os números são da sua operação. As calculadoras do portal transformam o argumento em conta feita com os seus dados.

Conteúdo curado por Alexandre Caramaschi, Founder da Brasil GEO, ex-CMO da Semantix (Nasdaq), cofundador da AI Brasil. Parte do portal GEO-Ecommerce, a serviço da operação Onclick.