Stack técnico completo
para sites WordPress de alto desempenho.
Documentação técnica integral de uma arquitetura WordPress + Elementor com captura de leads anti-bot, SEO técnico avançado, cache multi-camada, identidade visual coesa e operação observável. Implementação 100% inline, sem assinatura comercial — pronta para ser replicada em qualquer projeto.
Infra observável
nginx + PHP-FPM + MySQL + Redis · systemd timers · backups antes de cada mudança · idempotência em todo script
Performance real
Cache Redis 3-níveis · Gzip · preload fonts · defer JS · TTFB -85% em cache quente · Brotli compilado em standby (ver §11 gotcha)
Captura segura
REST API · 10 camadas anti-bot · honeypots · time-trap · rate limit estratificado · logger de bloqueios
Como as camadas se relacionam.
[Cliente]
│ HTTPS · Gzip negociado (Brotli compilado mas off · ver §11 gotcha)
▼
[nginx 1.18]
│ ├─ HTTP/2 · TLS · cache headers
│ ├─ Gzip compress on (Brotli em standby · módulos .so disponíveis)
│ ├─ rewrite → index.php se não-asset
│ └─ proxy → php-fpm 8.1 via unix socket
▼
[PHP-FPM 8.1]
│ ├─ WordPress core
│ ├─ Elementor + Elementor Pro
│ ├─ W3 Total Cache → page cache em Redis db2
│ ├─ MU-plugins ativos:
│ │ ├─ site-seo-meta (Schema @graph · OG · Twitter · canonical)
│ │ ├─ site-seo-schema (Service/Product/FAQPage por página)
│ │ ├─ site-performance (preload fonts · defer JS · remove bloat)
│ │ └─ site-lp-forms (REST API · anti-bot 10 camadas · email duplo)
│ ├─ wp_mail() → WP Mail SMTP → Locaweb SMTP (transactional)
│ └─ wp-cron + systemd timers
▼
[Redis 6379] [MySQL] [Filesystem]
├─ db0 objects ├─ wp_* ├─ /wp-content/{site}-leads/*.jsonl (PII)
├─ db1 dbcache └─ leads PII ├─ /usr/local/share/{site}-builders/*.php
└─ db2 pgcache ├─ /usr/local/bin/*.sh (watchdogs)
└─ /usr/local/share/{site}-backups/* (snapshots)
Camada base · servidor + cache + mailer.
nginx 1.18 + gzip (Brotli em standby)
Web server com gzip ativo. Brotli compilado como módulo dinâmico contra google/ngx_brotli mas DESABILITADO por padrão — conflito de double-compression com W3TC documentado em §11.
- HTTP/2 + TLS 1.3 (SNI enabled)
- gzip on · gzip_vary on · gzip_disable msie6
- gzip_types text/css application/javascript application/json image/svg+xml
- Browser cache 1 ano (max-age) para CSS/JS/imagens
- Módulos brotli compilados em /usr/lib/nginx/modules/ — prontos para ativar quando W3TC parar de pré-comprimir HTML
- Backup pre-mudança em /usr/local/share/{site}-backups/pre-brotli-{timestamp}/
- Sempre validar com `nginx -t` antes de `systemctl reload nginx`
# Brotli em STANDBY — ativar SOMENTE após resolver double-compression. # Pré-requisito: desabilitar W3TC browsercache.html.compression # (senão gera response com 2 Content-Encoding e quebra navegador) # # Quando seguro, descomentar: # load_module modules/ngx_http_brotli_filter_module.so; # load_module modules/ngx_http_brotli_static_module.so; # brotli on; brotli_static on; brotli_comp_level 6; # brotli_min_length 256; # brotli_types text/plain text/css application/javascript # application/json image/svg+xml font/woff2;
PHP-FPM 8.1 + Redis ext
Pool PHP com php-redis extension para que WordPress fale com Redis diretamente.
- pm.max_children dinâmico baseado em RAM
- opcache habilitado (revalidate_freq=60s em produção)
- sendmail_path stubbed (SMTP via WP Mail SMTP)
- Extensões críticas: redis, mysqli, curl, intl, mbstring, opcache
- Reload graceful: `systemctl reload php8.1-fpm` (não restart — preserva sessões)
Redis 7 · 3 bancos lógicos
Cache em RAM com 3 dbs separados para isolamento de escopo.
- db0 · Object cache (queries + transients WP)
- db1 · DB cache (queries SQL repetidas)
- db2 · Page cache (HTML completo em RAM, gerado pelo W3TC)
- Persistent connections (não abre socket por request)
- Bind 127.0.0.1 · sem auth (local-only)
- Estatísticas via `redis-cli info stats` + `redis-cli info keyspace`
MySQL/MariaDB + Locaweb SMTP
Persistência relacional + relay de email autenticado para entrega comercial.
- wp_options · wp_postmeta indexados
- Backup wp_options.sql antes de cada mudança crítica
- SMTP via email-ssl.com.br:465 SSL (provedor identificado via `host -t MX`)
- Anti-promo headers: Auto-Submitted, Precedence: transactional
- Logs em wp_wpmailsmtp_debug_events
- Gotcha: nunca assumir provedor — sempre validar MX records
CMS + page builder ajustados para performance.
WordPress 7+ ajustado
Core enxuto com bloat removido pela MU-plugin de performance.
- Heartbeat desabilitado no front-end
- Emoji core removido (libera ~13KB JS/CSS)
- wp-block-library + global-styles dequeued (site 100% Elementor)
- wp_generator + RSD + wlwmanifest + shortlink removidos
- feed_links_extra removido (não há feeds em uso)
Elementor + Elementor Pro
Page builder com config de cache otimizada.
- `elementor_css_print_method = internal` (CSS inline no HTML — imune a flushes)
- Helpers próprios eCol/eSec/eInner com `_inline_size` numérico (nunca null — colapsa colunas)
- Construção de páginas via PHP builders idempotentes em /usr/local/share/{site}-builders/
- Marker `_ulpf_marker=1` na seção do form (idempotência da injeção)
- CSS Elementor regenerado limpando `_elementor_css` postmeta
// Sempre setar _inline_size numérico (não null)
function eCol($size, $widgets) {
return [
'elType' => 'column',
'settings' => [
'_inline_size' => (float)$size,
'_inline_size_tablet' => 100,
'_inline_size_mobile' => 100,
],
'elements' => $widgets,
];
}Cinco camadas independentes de cache.
Cada uma protege contra falha das outras. Cache hit em qualquer camada significa response rápido.
| # | Camada | Tecnologia | Escopo |
|---|---|---|---|
| 1 | Browser cache | nginx Cache-Control: max-age=31536000 | CSS, JS, imagens, fontes (1 ano) |
| 2 | Compressão | Gzip (W3TC pré-gera) · Brotli compilado mas off | HTML/CSS/JS ~25% menos bytes |
| 3 | Page cache (W3TC) | Redis db2 (HTML em RAM) | Páginas anônimas servidas em <100ms |
| 4 | DB cache (W3TC) | Redis db1 (queries SQL repetidas) | SELECTs idênticos não tocam MySQL |
| 5 | Object cache (W3TC) | Redis db0 (objects + transients WP) | get_post(), options, hooks |
| 6 | Minify (W3TC) | CSS + JS + HTML minify (file engine) | ~25% menos bytes por asset |
| 7 | Lazy load nativo | W3TC + Elementor loading=lazy | Imagens fora do viewport defer |
| 8 | CSS inline (Elementor) | elementor_css_print_method=internal | Imune a flushes de cache de plugin |
Quatro plugins isolados · separation of concerns.
Cada MU-plugin tem responsabilidade única. Fácil debugar, ativar/desativar individualmente, sem dependências cruzadas.
SEO Engine v2 · meta description + Schema base
Injeta meta description (custom ou fallback do conteúdo), canonical, OG, Twitter Cards, JSON-LD @graph com WebSite + Organization + WebPage + BreadcrumbList.
- Roda em wp_head priority 1 (antes de qualquer outra coisa)
- Remove rel_canonical do core em singular (evita duplicação)
- Fallback automático: deriva description do post_excerpt ou post_content (158 chars)
- document_title_parts filter: remove tagline duplicada quando título já contém marca
-
fetchpriority=high + loading=eager na primeira
(LCP boost)
SEO Schema Extender · Service/Product/FAQ
Estende o SEO Engine com Schema.org específico por página + FAQ auto-extracted de accordion Elementor.
- Mapa post_id → tipo Service ou Product
- Service: serviceType, audience, areaServed, provider
- FAQPage gerado automaticamente walking _elementor_data buscando widget accordion
- Cada Question/Answer no @graph FAQPage
- Aparece como rich result no Google SERP + AI search engines
Performance Engine · preload + defer + remove bloat
Reduz render-blocking + tempo de execução de JS sem dependência de plugins.
- preconnect: fonts.googleapis.com + fonts.gstatic.com
- preload: Plus Jakarta Sans (weights 400/500/600/700)
- defer automático em scripts não-críticos (exceto jquery, elementor-frontend)
- Remove emojis core, RSD, wlwmanifest, wp_generator, feed_links_extra
- Dequeue wp-block-library + global-styles no front-end
- Deregister heartbeat fora do admin
LP Forms v1.6 · captura + anti-bot + email duplo
Sistema completo de formulários custom substituindo plugins externos abandonados.
-
ShortcodeFale com o comercial
Solicite uma proposta comercial
Nossa equipe entra em contato em até 1 dia útil com proposta personalizada.
- REST API endpoint POST /wp-json/{ns}/v1/lp-submit (não admin-ajax — AIOWPS bloqueia)
- Resposta HTTP em ~0.8s (envio assíncrono via fastcgi_finish_request)
- JSONL local como source of truth (lead nunca se perde mesmo com SMTP off)
- 2 emails simultâneos: notificação comercial + confirmação ao cliente
- Headers transacionais anti-Pasta Promoções (Auto-Submitted, Precedence: transactional)
- From dinâmico identificando canal: "LP Site : Produto" vs "Site : Produto"
Dez camadas de defesa.
Cada camada é independente. Bot precisa passar por todas para submeter — humano legítimo passa por todas sem fricção visível.
| # | Camada | Detecta | Reação |
|---|---|---|---|
| 1 | Honeypots múltiplos | 3 campos invisíveis (hp_field · website · confirm_email) | hp_field: 200 OK silencioso · outros: 403 |
| 2 | Time-trap | _render_ts: submit em <3s ou form >24h velho | 403 + strike |
| 3 | JS-required token | _js_ready formato regex 1:<ts36>:<rand> | 403 + strike |
| 4 | User-Agent filter | Blocklist 19 patterns (curl, wget, python-requests, bot, spider) | 403 + strike |
| 5 | Referer/Origin lockdown | host(Referer) ≠ próprio domínio | 403 + strike |
| 6 | Payload size limit | Total params >5KB | 403 + strike |
| 7 | Rate limit nível 1 | ≥2 submits/minuto por IP | 429 |
| 8 | Rate limit níveis 2+3 | >5/hora · >20/dia por IP | 429 |
| 9 | Strike + blocklist | 3 violações em 24h → IP bloqueado 24h | 429 por 24h |
| 10 | Semantic checks | URL no nome · email descartável (15 domínios) · telefone <10 dígitos · endereço sem número | 422 + mensagem amigável |
Logger de bloqueios: tentativas falhas registradas em
/wp-content/{site}-leads/blocked-YYYY-MM.jsonl com IP, UA, Referer, reason e payload size. Permite análise de padrões de ataque sem poluir leads válidos.Cobertura completa · Google + AI search.
Meta tags + Open Graph
Cobertura 100% das páginas publicadas.
- meta description custom (postmeta _meta_description) com fallback automático
- canonical em todas singular pages
- og:locale, og:type, og:site_name, og:title, og:description, og:url, og:image
- twitter:card summary_large_image + título/descrição/imagem
- robots: index,follow,max-image-preview:large,max-snippet:-1,max-video-preview:-1
JSON-LD Schema.org @graph
Rich results no Google SERP + ingestão correta por AI search.
- WebSite @id (canonical do domínio)
- Organization/LocalBusiness com endereço, telefone, areaServed
- WebPage por URL específica
- BreadcrumbList automática
- Service/Product específico por página-produto
- FAQPage auto-extracted de Elementor accordion
AI search engines · llms.txt + robots.txt
Pioneirismo em SEO para IA generativa.
- llms.txt na raiz · estrutura Markdown estilo proposta llms.txt
- Lista produtos com URL + descrição curta
- robots.txt com Allow explícito: GPTBot, ChatGPT-User, PerplexityBot, Claude-Web, ClaudeBot, anthropic-ai, cohere-ai
- Sitemap reference no robots.txt
- JSON-LD rico = ingestão correta sem ambiguidade
Sitemap + crawling
Indexação acelerada por crawlers.
- wp-sitemap.xml dinâmico (WordPress 5.5+ nativo)
- sitemap.xml redireciona para wp-sitemap.xml
- robots.txt disallow: /wp-admin/, /wp-includes/, /wp-content/cache/, /wp-content/{site}-leads/
- robots.txt disallow: /?s= · /search/ · /*?attachment_id= · /*?replytocom=
- Google Search Console + Site Kit para monitoramento
Sistema de design tokens.
Paleta de design tokens
Definida como const PHP nos builders, herdada por todos os componentes.
- NAVY #0d1a5c · brand principal (h1, navbar, CTA)
- NAVY_DEEP #091244 · hero backgrounds
- BLUE #2055c7 · accents secundários, hover
- CYAN #00a8d4 · destaques, pílulas, ênfase italic
- GREEN/AMBER/RED · status semantic
- T_DARK/T_MID/T_LIGHT/T_QUIET · escala de texto (contraste WCAG AA validado)
- BORDER #e7eaf3 · HAIRLINE #eaecf3 · separadores
- PAPER #f8fafc · PALE #eff3fb · backgrounds suaves
Tipografia responsiva automática
Helper _respSize() escala desktop→tablet→mobile proporcional.
- Plus Jakarta Sans (preconnect+preload)
- Pesos: 400, 500, 600, 700
- Heading h1 56px → 36px tablet → 28px mobile
- Heading h2 40px → 29px → 24px
- Body 16px com line-height 1.75 · letter-spacing -0.005em
- Code blocks: SF Mono, Menlo, Consolas, monospace
- Italic + peso 700 para ênfase (não 400/500 que ficaria fraco)
Padding/spacing responsivo
Helper tPad() reduz padding vertical em mobile (110px → 56px).
- Padding desktop ≥60px tem auto-tablet (×0.65) e auto-mobile (×0.50)
- Padding horizontal mobile capped em 20px
- Section gap "extended" em desktop, "no" em mobile
- CSS grid 2 colunas desktop → 1 mobile (≤640px)
Componentes reutilizáveis
Funções PHP que retornam blocos Elementor consistentes.
- w_h() · heading com tipografia responsiva automática
- w_t() · text-editor com fontes/cores padronizadas
- w_pill() · button pequeno como pílula (decorativa ou link)
- w_il() · icon-list com ícones do FontAwesome
- w_btn() · button principal com gradient
- w_div() · divider configurável
- w_html() · widget HTML escopado (CSS inline pra não vazar)
- eSec/eCol/eInner · estrutura Elementor com _inline_size correto
Watchdog · backup · idempotência.
Persistência após reboot
Nada importante em /tmp (limpa no boot por systemd-tmpfiles).
- Scripts: /usr/local/bin/*.sh
- Builders: /usr/local/share/{site}-builders/*.php
- Backups: /usr/local/share/{site}-backups/{timestamp}/
- Logs: /var/log/{component}.log
- Services enabled (auto-start): nginx, php-fpm, mysql, redis-server, cron
- Systemd timers: watchdog CSS · archive de sessões · health checks
Watchdog + recovery automático
Detecta perda de CSS inline e regenera.
- cron a cada 30min: /usr/local/bin/elementor-css-watchdog.sh
- systemd timer redundante (OnUnitActiveSec=30min, Persistent=true)
- Critério: bloco >1000 chars contendo .elementor-element-
- Recovery: delete _elementor_css + wp w3-total-cache flush all
- Log: /var/log/elementor-watchdog.log com rotação simples (5000 linhas)
Backups antes de cada mudança
Rollback rápido se algo quebrar.
- Builders idempotentes (marker meta + check de existência)
- Snapshot nginx.conf + sites-enabled antes de editar
- Backup _elementor_data por post antes de strip/rewrite
- Backup w3tc-config/master.php antes de mudança
- mysqldump wp_options antes de massupdate
- tar de /usr/lib/nginx/modules antes de instalar módulo novo
Validação em cada step
Falha fast, não chega em produção quebrado.
- php -l antes de salvar MU-plugin
- nginx -t antes de reload
- curl HTTP code check após mudança
- JSON-LD validation via regex parsing
- Smoke test todas páginas-amostra (HTTP 200)
- Lighthouse before/after pra mudanças de performance
Second Brain integrado.
Vault Obsidian (PARA mode)
Knowledge base local com estrutura organizacional padrão.
- Estrutura PARA: Projects · Areas · Resources · Archive
- Session logs estruturados (1 arquivo por sessão Claude Code)
- Project notes vinculadas via wikilinks
- Memory cross-session em /memory/ (feedback rules + references)
- Templates: project, session-log, concept, entity, source, question
- Git auto-commit a cada mudança (PostToolUse hook)
Graphify · grafo de conhecimento
Busca semântica BFS sobre o vault, ~71× mais token-econômica que Grep/Glob.
- graphify update . re-indexa o vault completo
- graphify query "pergunta" faz BFS retornando nodes + edges relevantes
- Hook automático Stop dispara reindex após cada turno
- Útil para "o que decidimos sobre X?" sem reler transcripts
Auto-archive de transcripts
JSONL bruto → markdown legível agrupado por sessionId.
- Cron horário + systemd timer
- Idempotente (não duplica arquivos)
- Vault recebe contexto de qualquer sessão (mesmo as compactadas)
- Continuidade real entre sessões via documentação, não memória LLM
Princípios que guiam toda decisão.
Não quebrar nada
Backup antes de cada mudança. nginx -t antes de reload. Rollback automático em falha. Mudanças incrementais validadas a cada step.
Source of truth local
Lead salvo no JSONL antes de tentar enviar email. Email é notificação, não armazenamento. Nunca depender de serviço externo para integridade.
Idempotência total
Scripts podem rodar 1× ou 100× — efeito é o mesmo. Marker meta + check de existência. Rebuild seguro a qualquer momento.
Separation of concerns
MU-plugins isolados por responsabilidade. SEO meta ≠ SEO schema ≠ Performance ≠ Forms. Fácil ativar/desativar individualmente.
Persistência consciente
Nada importante em /tmp. /usr/local/bin para scripts, /usr/local/share para dados, /var/log para logs. systemd services enabled.
Validação contínua
php -l, nginx -t, curl HTTP code, JSON parse, Lighthouse delta, screenshot diff. Falha fast, não chega quebrado em produção.
Documentação obrigatória
Session log + memory persistente + project note + Graphify reindex em cada interação substantiva. Próxima sessão pega contexto cold-start.
Design não é negociável
Plus Jakarta Sans + paleta tokens + tipografia responsiva automática + heading peso 700 + contraste WCAG AA. Forms e popups com mesma qualidade visual das páginas.
Anti-fragilidade
Watchdog regenera CSS perdido. Cron + systemd timer redundantes. JSONL acumula mesmo se email falhar. Cache em camadas independentes.
Erros que custam horas se você não souber.
Catálogo de armadilhas técnicas descobertas durante a implementação. Cada uma é uma falha silenciosa que parece estar funcionando mas não está.
-
DOUBLE-COMPRESSION W3TC + Brotli — Se W3TC tem
browsercache.html.compression=true(pré-gera HTML gzipped) E nginx tembrotli on, o response sai com DOIS headersContent-Encoding(gzip + br). Navegador tenta descomprimir bytes gzip como brotli e exibe lixo binário (€õ‹í½kcÛ¶...). Fix: escolher UMA camada de compressão — recomendado mover tudo pro nginx (gzip OU brotli) e desabilitar compressão no W3TC. Diagnosticar comcurl -sI -H "Accept-Encoding: br,gzip" URL | grep -i content-encoding— se aparecer 2 linhas é double-compression. Status atual: Brotli compilado mas desativado para evitar essa armadilha. - /tmp é limpo no boot em systemd-tmpfiles padrão Ubuntu. NUNCA salve scripts/dados importantes lá. Use /usr/local/{bin,share}.
- Elementor _inline_size=null colapsa colunas para 100% em mobile. Sempre setar valor numérico (float ou int).
-
W3TC minify HTML strippa aspas dos atributos (name="x" vira name=x). Regex de validação precisa ser flexível:
name=("?)description\1. -
css_id em <section> do Elementor NÃO vira id= no HTML. Funciona apenas em widget via
_element_id. - W3TC requer /wp-content/cache/page_enhanced/{domain}/ existir como diretório. Deletar completamente faz TODAS as páginas retornarem 0 bytes (HTTP 200 vazio).
- admin-ajax.php POST anônimo é bloqueado por AIOWPS Security plugin. Sempre usar REST API endpoint customizado.
- Caldera Forms não tem SMTP próprio — depende inteiramente de wp_mail(). Se WP Mail SMTP estiver com creds erradas, forms "funcionam" no front-end mas email nunca sai.
- site-mailer (Elementor) com quota=0 intercepta wp_mail silenciosamente. Marca status="not sent" e descarta. Desativar se plano não inclui Mailer.
- SMTP provider correto via host -t MX antes de configurar. Assumir Titan vs Locaweb vs Gmail é causa #1 de auth 535.
- List-Unsubscribe header marca email como newsletter e cai em Pasta Promoções do Gmail. Não usar em emails transacionais.
-
Mídias placeholder 1×1 pixel disfarçadas de JPG em alguns plugins (332 bytes, dimensões 1×1) — sempre verificar com
fileantes de usar. - php-redis precisa reload php-fpm após install — extensão não é detectada hot.
- nginx -V mostra --add-dynamic-module com path do builder Ubuntu original (/build/nginx-UlKqXz/...) — REMOVER antes de re-passar para ./configure ao recompilar módulos dinâmicos.
-
W3TC config NÃO é JSON puro — master.php tem
<?php exit; ?>prefix antes do JSON. Strip antes de json_decode. - Defer em elementor-frontend quebra Elementor. Lista de scripts que NÃO deferir: jquery, jquery-core, jquery-migrate, elementor-frontend, wp-i18n, wp-polyfill.
- MCPs adicionados durante uma sessão ficam disponíveis só na PRÓXIMA — restart obrigatório.
- Skills do Claude plugin entram no system prompt na inicialização — não dá pra carregar hot mid-session.
- Auto-Submitted: auto-generated + Precedence: transactional é a combinação RFC mais forte para Gmail entender que é transacional (não marketing).
- Lighthouse simulado mascara ganhos reais de TTFB — ele simula 3G + CPU 4× throttling, então Performance score reflete principalmente JS execution + DOM size, não rede.
- FAQ schema FAQPage auto-extracted de widget accordion Elementor — qualquer FAQ futuro vira rich result Google sem trabalho manual.
Ganho real mensurado.
| Métrica | Antes | Depois | Ganho |
|---|---|---|---|
| TTFB (cache quente) | 8.7s | 1.3s | -85% |
| HTML transferido | 330KB | 32KB | -90% |
| HTML transferido (gzip) | ~330KB raw | ~48KB gzip | -85% |
| Lighthouse SEO | 85 | 92 | +7 |
| pa11y violações WCAG (controláveis) | 9 | 0 | -100% |
| Plugins ativos (superfície de ataque) | 20 | 15 | -25% |
| Bots bloqueados em bateria de teste | 0/8 | 8/8 | 100% |
| Cobertura WebP em imagens publicadas | 94% | 100% | +6pp |
| Cobertura meta description | 53% | 100% | +47pp |
| Cobertura Schema.org Service/FAQ | 0 | 9 páginas | +9 |
Load time percebido pelo usuário (rede normal): ~8-12s → ~3-4s (-60% a -70%).
Esta arquitetura é replicável.
Use como blueprint.
Stack 100% inline · sem dependência de plugins comerciais · sem CDN externo · sem CAPTCHA visual · sem custos recorrentes além de hosting + SMTP. Todos os MU-plugins, builders, scripts e configs podem ser portados para qualquer site WordPress + Elementor mantendo a mesma qualidade.
