Construindo um mock E-commerce com Astro e SQLite
O Heyahub foi um projeto piloto de e-commerce que desenvolvi para explorar as capacidades do Astro em aplicações de alta performance com dados dinâmicos. Utilizando JWT para proteção de rotas, o site possui vários avisos para assegurar o usuário que nenhum dado sensível dele é armazenado. Todo o processo é apenas uma simulação com uma série de links para orgãos reais que aceitam doações, para que, se você realmente puder gastar dinheiro com meus produtos de faz de conta, você possa ajudar uma instituição de caridade com o valor de sua compra.
A Escolha do Stack
Escolhi Astro por sua flexibilidade: ele permite usar SSR para páginas que precisam de dados em tempo real e SSG para páginas estáticas, tudo no mesmo projeto. Além disso, tomei proveito das Server Islands do astro para a hidratação dos componentes dinâmicos sem precisar de SSR na página inteira, dessa forma mantendo o código simples com JS vanilla, HTML5 e TailwindCSS nas partes prerrendered e nas partes de server islands.
O sistema armazena os dados de login do usuário mas os apaga automaticamente depois de uma semana e não exige verificação por e-mail, já que é um projeto piloto. O libSQL permite que a conexão com o banco fique em hibernação e seja reativada quando preciso, junto com encriptação de ponta, o que garante a performance do site.
| Tecnologia | Função |
|---|---|
| Astro | Framework principal |
| TailwindCSS | Estilização |
| Node.js (astro adapter) | Servidor |
| libSQL | Um fork do SQLite criado e mantido pela Turso |
Arquitetura
O projeto seguiu uma arquitetura simples e eficaz:
- Telas de Login e Register — Proporciona a autenticação para demonstrar as proteções de rota do app feitas com JWT.
- Catálogo de produtos — Gerado encima de um place holder estático e depois hidratado com dados do banco de dados, com imagens obtidas pela Unsplash
- Carrinho — A parte do fluxo mais desafiadora. O estado do carrinho é gerenciado no cliente com o nanostores com o JS vanilla atualizando-o otimisticamente junto ao DOM e sincronizando o banco de dados apenas quando necessário evitando a constante comunicação com o servidor.
- Checkout — Endpoint para processamento do pedido que leva o usuário por um fluxo convencional de carrinho com checkout, mas que redireciona o usuário a uma página de incentivo a doações a causas beneficentes. Já que essa parte do fluxo é apenas para demonstração ela foi feita estática e não recebe dados de nenhum banco de dados mesmo sendo protegida.
// Exemplo de componente Server Island
interface Props {
page?: number;
category?: string | null;
pageSize?: number;
}
const {
page = 1,
category = null,
pageSize = 12,
} = Astro.props;
const offset = (page - 1) * pageSize;
const whereClause = category ? eq(products.category, category) : undefined;
const productList = whereClause
? db.select().from(products).where(whereClause).limit(pageSize).offset(offset).all()
: db.select().from(products).limit(pageSize).offset(offset).all();
---
...
{productList.length === 0 ? (
<div class="text-center py-20 bg-white/5 rounded-3xl border border-white/5">
<p class="text-gray-400 font-medium">Nenhum produto encontrado nesta categoria.</p>
</div>
) : (
<>
<!-- Product grid -->
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
{productList.map((product) => (
<ProductCard product={product} />
))}
</div>
...
Lições Aprendidas
- libSQL é surpreendentemente adequado para projetos pequenos e mantém a filosofia do SQLite de dados baseado em texto proporcionando escalabilidade com sharding, replicas e encriptação.
- Astro’s SSR + SSG mode com Node adapter funciona muito bem para APIs simples, porém eu usaria alguma framework com @astrojs/vue, @astrojs/svelte ou @astrojs/react em uma aplicação muito reativa ou dinâmica.
- TailwindCSS v4 trouxe melhorias significativas de performance no build e casa bem com projetos web vanilla.
Foi uma experiência muito rica que me deu base sólida para projetos futuros.