# Headless Starter Kit: guia completo

> Guia completo de instalação, configuração e implantação do Headless Starter Kit: plugin WordPress que transforma a sua loja WooCommerce em comércio headless, com starter Next.js 15 chave na mão entregue pré-configurado.

- Página: <https://www.datafirefly.com/pt/documentation/headless-starter-kit/>
- Idioma: pt
- Atualizado em: 2026-09-02
- Outros idiomas: [fr](https://www.datafirefly.com/documentation/headless-starter-kit/index.md), [en](https://www.datafirefly.com/en/documentation/headless-starter-kit/index.md), [es](https://www.datafirefly.com/es/documentation/headless-starter-kit/index.md), [de](https://www.datafirefly.com/de/documentation/headless-starter-kit/index.md), [it](https://www.datafirefly.com/it/documentation/headless-starter-kit/index.md), [pl](https://www.datafirefly.com/pl/documentation/headless-starter-kit/index.md), [nl](https://www.datafirefly.com/nl/documentation/headless-starter-kit/index.md)
- Índice: <https://www.datafirefly.com/pt/documentation/llms.txt>

Este guia cobre a instalação, a configuração e a utilização completa do **Headless Starter Kit**, o plugin WordPress que transforma a sua loja WooCommerce em comércio headless, acompanhado de um starter Next.js 15 chave na mão.

**A quem se destina este guia.** Programador, agência ou comerciante técnico que quer passar um WooCommerce existente para headless sem reinventar a autenticação, o carrinho e o checkout. Tem de estar à vontade com a linha de comandos, o Node.js e alguma configuração de servidor se escolher o Hetzner.

## Visão de conjunto

O Headless Starter Kit apresenta-se em **dois entregáveis** distribuídos na mesma compra:

1. **O plugin WordPress** (ZIP a carregar em `/wp-admin/plugins.php`) que expõe do lado do backend: autenticação JWT, API de carrinho, ponte de checkout, endpoint de configuração público, webhooks ISR e CORS estrito.
2. **O starter Next.js 15** (ZIP descarregável a partir da administração do WordPress depois de o plugin estar ativo e configurado) que contém um projeto Next.js completo com páginas inicial, listagem, ficha de produto ISR, carrinho, checkout, início de sessão, registo e área de cliente, com as variáveis de ambiente já preenchidas com os seus URL e segredos.

A arquitetura é propositadamente simples: o seu WooCommerce continua a ser a fonte de verdade (produtos, encomendas, stocks, pagamentos) e o Next.js consome a API REST através de rotas proxy seguras. Sem duplicação de base de dados e sem replicação para gerir.

## Requisitos

### Do lado do WordPress

- WordPress **6.4 ou superior**
- WooCommerce **8.0 ou superior** (testado até à 9.5)
- PHP **8.1 ou superior**
- Permalinks configurados em _Nome do artigo_ (e não em _Simples_)
- HTTPS ativo (indispensável para os cookies httpOnly e para a autenticação em produção)
- Um par de chaves REST do WooCommerce em leitura e escrita (geradas em _WooCommerce → Definições → Avançado → API REST_)

### Do lado do frontend Next.js

- Node.js **20 ou superior** (recomendado: gerir as versões com o `nvm`)
- Alojamento compatível com Node: Vercel, VPS Hetzner, Netlify, Railway ou qualquer servidor capaz de executar Node 20+

**Um alojamento partilhado clássico não serve** para alojar o frontend Next.js, que exige um runtime Node persistente. O plugin WordPress, esse, funciona em qualquer alojamento WP.

## Instalação do plugin WordPress

1. No back-office do WordPress, vá a _Plugins → Adicionar plugin → Carregar plugin_.
2. Selecione o ficheiro `dfheadlessstarterkit.zip` e clique em _Instalar agora_.
3. Clique em _Ativar plugin_.
4. Aparece um novo menu **Headless Kit** na barra lateral esquerda, com três separadores: _Definições_, _Diagnósticos_ e _Descarregar o starter_.

Na ativação, o plugin gera automaticamente um segredo JWT e um token de revalidação aleatórios. Pode regerá-los a qualquer momento a partir das definições.

## Configuração

Abra _Headless Kit → Definições_. Cada secção é independente e pode ser ajustada sem reiniciar seja o que for.

### URL do frontend

Indique o URL público completo da sua aplicação Next.js, sem barra final. Exemplo:

```
https://loja.exemplo.pt
```

Este URL serve para três coisas: construir os webhooks ISR, alimentar a variável `NEXT_PUBLIC_SITE_URL` do starter entregue, e validar a origem CORS predefinida.

### Segredo JWT e token de revalidação

São usados dois segredos:

- **Segredo JWT**: assina os tokens de acesso e de refresh. No mínimo 32 carateres. Nunca o partilhe.
- **Token de revalidação**: enviado no cabeçalho `Authorization: Bearer …` dos webhooks ISR. Tem de ser igual à variável `REVALIDATE_TOKEN` do lado do Next.js.

Um botão _Regerar_ ao lado de cada campo produz um segredo aleatório criptograficamente sólido através do `crypto.getRandomValues`.

**Depois de regerar o segredo JWT, todos os tokens de acesso e de refresh existentes ficam inválidos.** Os utilizadores terão de iniciar sessão de novo. Avise-os ou faça-o fora das horas de maior tráfego.

### Modo de carrinho: JWT ou servidor?

A escolha faz-se através de um botão de opção nas definições.

#### Modo JWT (predefinido, recomendado)

O carrinho completo é serializado num token assinado HS256 e devolvido através do cabeçalho `X-DFHSK-Cart`. Nenhum dado é guardado do lado do WordPress. Ideal para:

- Implantações em Vercel edge, Cloudflare ou em várias instâncias
- Lojas de tráfego elevado onde evitar a base de dados a cada chamada é um ganho claro
- Configurações em que o WordPress é puramente API e não precisa de sessões

#### Modo servidor (WC_Session)

O carrinho vive na tabela nativa WC_Session do WooCommerce. A privilegiar se:

- Usa extensões WooCommerce que fazem hook no carrinho (WooCommerce Subscriptions, Dynamic Pricing, plugins YITH, etc.)
- Quer conservar a lógica de sessão nativa do WooCommerce (recuperação nativa de carrinhos abandonados, cross-sell no servidor, etc.)

### Origens CORS

Uma lista de permissões estrita das origens autorizadas a chamar a API. Uma origem por linha, no formato completo `https://…`. Os wildcards de subdomínio são suportados:

```
https://loja.exemplo.pt
https://preview.exemplo.pt
https://*.previews.exemplo.pt
http://localhost:3000
```

Acrescente `http://localhost:3000` durante o desenvolvimento e retire-o em produção.

### Eventos ISR

Cinco caixas de seleção indicam que eventos do WordPress desencadeiam um webhook ISR para o Next.js:

- **Produtos**: `save_post_product`, `woocommerce_update_product`
- **Categorias**: criação, atualização e eliminação de termos da taxonomia `product_cat`
- **Encomendas**: mudanças de estado (útil para atualizar a página da conta do cliente)
- **Páginas**: `save_post_page`
- **Cupões**: criação e atualização de códigos promocionais

Uma caixa de texto _Caminhos a revalidar_ permite definir com precisão que caminhos do Next.js são revalidados em cada evento (por predefinição, o plugin deduz de forma inteligente os caminhos em causa).

## Diagnósticos

Separador _Headless Kit → Diagnósticos_. São executadas onze verificações automáticas a cada apresentação da página:

1. **WooCommerce ativo**: a classe `WooCommerce` está disponível
2. **Permalinks limpos**: a estrutura não é _Simples_
3. **API REST acessível**: o `/wp-json/` responde com 200
4. **HTTPS ativo**: o `is_ssl()` devolve true
5. **WPGraphQL detetado**: apenas informativo, não bloqueante
6. **Segredo JWT definido**: no mínimo 32 carateres
7. **URL do frontend configurado**: não vazio e com formato de URL válido
8. **Origens CORS preenchidas**: pelo menos uma origem
9. **Token de revalidação definido**: no mínimo 24 carateres
10. **Chaves REST do WooCommerce**: o plugin deteta um par consumer_key/consumer_secret ativo
11. **Modo de carrinho legível**: o armazenamento escolhido funciona

Cada verificação aparece a verde (OK), laranja (aviso, não bloqueante) ou vermelho (bloqueante). Resolva tudo o que estiver a vermelho antes de passar a produção.

## Descarregar e lançar o starter Next.js

Depois de preencher as definições e com os diagnósticos a verde, abra _Headless Kit → Descarregar o starter_. Clique no botão grande _Descarregar o starter Next.js_.

O ZIP entregue é um projeto Next.js 15 completo, gerado na hora com os seus URL e segredos já injetados. Os marcadores substituídos na geração:

- `{{SITE_URL}}` → URL do seu WordPress
- `{{FRONTEND_URL}}` → URL do front configurado
- `{{REVALIDATE_TOKEN}}` → o seu token de revalidação
- `{{CURRENCY}}` → moeda do WooCommerce
- `{{SITE_NAME}}` → título do site
- `{{LOCALE}}` → locale do WordPress (pt, fr, en, es, etc.)

O ficheiro `.envtmpl` passa a chamar-se `.env.example` na geração.

### Variáveis de ambiente a completar manualmente

Alguns valores não podem ser obtidos automaticamente e têm de ser acrescentados ao ficheiro `.env` (a criar a partir do `.env.example`):

```
WOO_REST_CONSUMER_KEY=ck_xxxxxxxxxxxxxx
WOO_REST_CONSUMER_SECRET=cs_xxxxxxxxxxxxxx
SESSION_PASSWORD=a-sua-palavra-passe-de-32-carateres-no-minimo
```

Gere uma `SESSION_PASSWORD` sólida:

```
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
```

### Desenvolvimento local

```
npm install
cp .env.example .env
# Edite o .env com os segredos em falta
npm run dev
```

O front fica acessível em `http://localhost:3000`. Acrescente este URL às origens CORS do lado do WordPress durante o desenvolvimento.

### Implantação em Vercel

```
npx vercel link
npx vercel env pull .env.production
npx vercel deploy --prod
```

Configure depois todas as variáveis de ambiente no dashboard da Vercel (_Project → Settings → Environment Variables_). O ficheiro `vercel.json` entregue fixa a região em `cdg1` (Paris) e desativa a cache nas rotas `/api/*`.

### Implantação em Hetzner (ou em qualquer VPS Ubuntu/Debian)

```
# No servidor, como root ou com sudo
git clone o-seu-repo.git storefront && cd storefront
cp .env.example .env
nano .env                       # Preencha todas as variáveis
bash deploy/hetzner.sh
```

O script instala o Docker se for necessário, constrói a imagem, lança o contentor e expõe o serviço em `127.0.0.1:3000`. Acrescente o Caddy ou o nginx como reverse-proxy para o TLS. Exemplo de Caddyfile mínimo:

```
loja.exemplo.pt {
  encode zstd gzip
  reverse_proxy 127.0.0.1:3000
}
```

## Endpoints REST expostos

Todos os endpoints do plugin estão no namespace `dfhsk/v1`. URL completo: `https://exemplo.pt/wp-json/dfhsk/v1/…`

### Autenticação

- `POST /auth/login`: corpo `{ username, password }` → devolve `{ token, refresh_token, user }`
- `POST /auth/refresh`: corpo `{ refresh_token }` → devolve um novo `token`
- `GET /auth/me`: cabeçalho `Authorization: Bearer …` → devolve o utilizador atual
- `POST /auth/register`: corpo `{ email, password, first_name, last_name }`
- `POST /auth/logout`: invalida o refresh token

### Carrinho

Todas as chamadas transmitem o token de carrinho através do cabeçalho `X-DFHSK-Cart`. O servidor devolve um novo token no mesmo cabeçalho em cada resposta.

- `GET /cart`: snapshot completo (itens, totais, impostos, portes)
- `POST /cart/add`: corpo `{ product_id, quantity, variation? }`
- `POST /cart/update`: corpo `{ key, quantity }`
- `POST /cart/remove`: corpo `{ key }`
- `POST /cart/coupon`: corpo `{ code }`
- `DELETE /cart/coupon/{code}`
- `POST /cart/shipping`: corpo `{ country, postcode }` → devolve as tarifas aplicáveis
- `POST /cart/clear`

### Checkout

- `POST /checkout/create-order`: corpo `{ payment_method, billing, shipping? }` → devolve `{ order_id, order_key, redirect }`. O `redirect` é o URL para o gateway de pagamento (Stripe, PayPal, etc.).
- `GET /checkout/order/{id}`: exige o cabeçalho `Authorization: Bearer …`

### Configuração pública

- `GET /config`: acessível sem autenticação. Devolve `{ currency, base_country, countries, payment_methods, tax_settings }`. O starter Next.js usa este endpoint para preencher os formulários de checkout.

### Webhooks ISR (do lado do Next.js)

O plugin envia pedidos `POST` para `{FRONTEND_URL}/api/revalidate` com o cabeçalho `Authorization: Bearer {REVALIDATE_TOKEN}`. O corpo é um JSON:

```
{
  "paths": ["/products/casaco-linho", "/products"],
  "tags": ["product:casaco-linho"],
  "reason": "wc_update_product"
}
```

A rota `/api/revalidate` entregue no starter valida o token e depois chama `revalidatePath` e `revalidateTag` para cada entrada.

## Personalizar o starter

O código entregue está sob licença GPL v2: pode alterar, estender e redistribuir sem restrições. Os pontos de entrada habituais:

- **Paleta de cores**: `tailwind.config.ts`, paleta `brand` (laranja por predefinição)
- **Componentes da loja**: `src/components/shop/` (Header, Footer, ProductCard, CartProvider)
- **Páginas públicas**: `src/app/(shop)/`
- **Páginas da conta do cliente**: `src/app/(auth)/`
- **Formato de preços e datas**: `src/lib/format.ts`
- **Tipos TypeScript**: `src/types/woo.ts`
- **Helper de chamada à API**: `src/lib/woo-rest.ts` (funções `wooRest` e `dfhskFetch`)

Para acrescentar uma nova página que liste, por exemplo, os produtos de uma marca, duplique `src/app/(shop)/products/page.tsx` e adapte a query da REST do WooCommerce. A função `wooRest()` trata automaticamente da autenticação Basic.

## Resolução de problemas

### Erro de CORS na consola do navegador

A origem do front não consta da lista de permissões. Acrescente-a em _Definições → Origens CORS_, uma por linha, sem barra final.

### Webhooks ISR que respondem 401

O `REVALIDATE_TOKEN` do lado do Next.js não corresponde ao token configurado do lado do WordPress. Copie o valor exato das definições do WP para o `.env` do Next.js e volte a implantar.

### O login devolve 403 apesar de as credenciais estarem corretas

Verifique que a conta de utilizador tem mesmo uma palavra-passe definida (e não apenas um início de sessão social), que o HTTPS está ativo em produção, e que o segredo JWT tem pelo menos 32 carateres. Consulte o separador Diagnósticos.

### O carrinho esvazia-se entre duas páginas

No modo JWT, verifique que o starter lê e escreve mesmo o token no `localStorage` (chave `dfhsk_cart_token`). Abra o inspetor do navegador → separador _Application → Local Storage_.

### Uma encomenda criada no WooCommerce não aparece do lado do Next.js

Verifique que o evento _Encomendas_ está assinalado nos eventos ISR e que o webhook parte sem erro (ative o `WP_DEBUG_LOG`).

## Ir mais longe

O starter é um ponto de partida, não um produto acabado. Consoante o seu projeto, considere acrescentar:

- Um motor de pesquisa instantânea (Algolia, Meilisearch, Typesense) alimentado pelos mesmos webhooks ISR
- Um CMS de conteúdo editorial do lado do WordPress com o plugin ACF ou equivalente, e uma página Next.js dedicada
- Uma PWA com service worker para o modo offline (ver também o nosso módulo _dfpwa_)
- Personalização por IA em tempo real (ver _dfsmartcontent_)

Para qualquer questão técnica, contacte o suporte DataFirefly com os seus registos e os resultados do separador Diagnósticos.
