From d576aa6871c2df36967fb17da6305945f87166cf Mon Sep 17 00:00:00 2001 From: Francisco Solla Date: Thu, 24 Sep 2026 00:40:48 -0300 Subject: [PATCH] =?UTF-8?q?docs(S36,C220,S37,S38,S39):=20planos=20+=20desi?= =?UTF-8?q?gns=20hi-fi=20=E2=80=94=20Central=20de=20Conte=C3=BAdos=20(logo?= =?UTF-8?q?,=20link=20do=20Instagram,=20lideran=C3=A7as,=20cards=20e=20se?= =?UTF-8?q?=C3=A7=C3=A3o=20na=20home)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...conteudos-cards-no-catalogo-ui-design.html | 94 ++++++++++++++ .../central-conteudos-cards-no-catalogo.md | 116 +++++++++++++++++ ...ntral-conteudos-header-logo-ui-design.html | 96 ++++++++++++++ docs/plans/central-conteudos-header-logo.md | 99 ++++++++++++++ ...entral-conteudos-liderancas-ui-design.html | 38 ++++++ docs/plans/central-conteudos-liderancas.md | 119 +++++++++++++++++ ...al-conteudos-link-instagram-ui-design.html | 46 +++++++ .../plans/central-conteudos-link-instagram.md | 112 ++++++++++++++++ ...entral-conteudos-secao-home-ui-design.html | 88 +++++++++++++ docs/plans/central-conteudos-secao-home.md | 121 ++++++++++++++++++ 10 files changed, 929 insertions(+) create mode 100644 docs/plans/central-conteudos-cards-no-catalogo-ui-design.html create mode 100644 docs/plans/central-conteudos-cards-no-catalogo.md create mode 100644 docs/plans/central-conteudos-header-logo-ui-design.html create mode 100644 docs/plans/central-conteudos-header-logo.md create mode 100644 docs/plans/central-conteudos-liderancas-ui-design.html create mode 100644 docs/plans/central-conteudos-liderancas.md create mode 100644 docs/plans/central-conteudos-link-instagram-ui-design.html create mode 100644 docs/plans/central-conteudos-link-instagram.md create mode 100644 docs/plans/central-conteudos-secao-home-ui-design.html create mode 100644 docs/plans/central-conteudos-secao-home.md diff --git a/docs/plans/central-conteudos-cards-no-catalogo-ui-design.html b/docs/plans/central-conteudos-cards-no-catalogo-ui-design.html new file mode 100644 index 00000000..42e82344 --- /dev/null +++ b/docs/plans/central-conteudos-cards-no-catalogo-ui-design.html @@ -0,0 +1,94 @@ + + + + + + + Design — S35 · Cards misturados ao catálogo + + + +
+
+ S35 · revisão do gate +

Cards e peças vivem no mesmo board.

+

Cada modelo é um item individual na ordem normal do catálogo. Não existe faixa, cabeçalho ou agrupamento próprio para cards.

+
+ +
+
CENA 01

Board padrão · desktop 1280 · peças e modelos misturados

+
+
Central de Conteúdos
+
+
Encontre uma peça por assunto, cidade ou tema…
Tipo⌄Cidade⌄Região⌄Tema⌄Instituição⌄
+

Escolha, compartilhe e peça voto

Uma lista só: peças oficiais e convites para criar seu card.

+
+
NEEDS ASSET · POSTER REAL▶
Vídeo

Título da peça publicada

Tema · Cidade

BaixarCompartilhar
+ +
NEEDS ASSET · FOTO REAL
Foto

Outra peça publicada

Tema da peça

BaixarCompartilhar
+
TIME DEVOCÊ
PLACEHOLDER · ARTE EXISTENTE
Card

Time de você

Entre para o time com sua foto.

santinho
Escolher este modelo →
+
NEEDS ASSET · CAPA REAL▶
Áudio

Mensagem para compartilhar

Campanha

BaixarCompartilhar
+
NOVOMINHA COLINHAPLACEHOLDER · ARTE EXISTENTE
Card

Minha colinha

Monte sua cola de votação.

santinhocolinha
Escolher este modelo →
+
+
Regra do gate: a ordem acima mistura itens por relevância/ordem do catálogo. “Card” é apenas o tipo do item — nunca um cabeçalho ou uma seção dentro do board.
+
+
+
+ +
+
CENA 02

Mobile 390 · board misto e Tipo “Card” ativo

+
☰
Busque uma peça ou card…
Tipo⌄Cidade⌄Tema⌄

Escolha, compartilhe e peça voto

+
NEEDS ASSET
POSTER REAL
Vídeo

Título da peça publicada

Ver peça →
+ + +
MINHA
COLINHA
Card · NOVO

Minha colinha

santinhocolinha
Escolher →
+

Sem divisor “Cards”. A alternância peça → card → peça é intencional.

+
☰
Busque um card…
Tipo · Card ×Tema⌄

Escolha, compartilhe e peça voto

6 itens com o filtro aplicado.

+
#SOU
Card

Card com seu nome

nome
+
◎
Card

Moldura quadrada

foto de perfil
+
▯
Card

Moldura vertical

foto de perfil
+
TIME DE
VOCÊ
Card

Time de você

santinho
+
TIME DO
ESTADUAL
Card

Time do estadual

estadual
+
MINHA
COLINHA
Card · NOVO

Minha colinha

santinhocolinha
+
+
+ +
+
CENA 03

Tipo “Card” ativo · os 6 modelos, sem cabeçalho próprio

+
Central de Conteúdos
Encontre uma peça por assunto, cidade ou tema…
Tipo · Card ×Cidade⌄Região⌄Tema⌄Instituição⌄

Escolha, compartilhe e peça voto

Resultados do filtro aplicado.

6 itens
+
+ + + + + + +
+
+
+ +
+
CENAS 04–05

Busca por apelido · “santinho” e “foto de perfil”

+
+
santinho×
Busca · “santinho” ×

2 itens encontrados

TIME DE VOCÊ
Card

Time de você

santinho
MINHA COLINHA
Card

Minha colinha

santinhocolinha
+
foto de perfil×
Busca · “foto de perfil” ×

2 itens encontrados

◎
Card

Moldura quadrada

foto de perfil
◎
Card

Moldura vertical

foto de perfil
+
+
Faceta geográfica ativa: os seis modelos somem, pois não são territoriais. Uma peça publicada de tipo Card continua seguindo a regra normal das peças.
Sem convite duplicado: o antigo tile “Card personalizado” foi removido. O estúdio segue acessível por cada modelo e pelo estado vazio já existente.
+
+
+ + diff --git a/docs/plans/central-conteudos-cards-no-catalogo.md b/docs/plans/central-conteudos-cards-no-catalogo.md new file mode 100644 index 00000000..a73fd208 --- /dev/null +++ b/docs/plans/central-conteudos-cards-no-catalogo.md @@ -0,0 +1,116 @@ +# S35 — Central de Conteúdos — cards personalizáveis como itens do catálogo + +Status: rascunho +Atualizado em: 2026-09-23 +Issue: #1304 +Priority: P1 +Impeccable: B — encaixe no catálogo existente (novos itens + busca/filtros), sem rota nova +Design UI: docs/plans/central-conteudos-cards-no-catalogo-ui-design.html +Appetite: ~1–1,5 dia eng; um outcome verificável (cada card encontrável por nome, busca e filtro no catálogo) +Responsável: — + +## Intenção + +Hoje os cards personalizáveis aparecem em `/conteudos` como **um único convite genérico** ("Faça seu card com Solla 1313"), que só é exibido quando nenhum filtro está ativo e não revela quais modelos existem. Quem procura um card pelo nome popular não acha nada, e quem não conhece a galeria nem sabe que há seis opções. O dono pediu literalmente: buscar **"santinho"** deve trazer os cards **"Time de você"** e **"colinha"**; buscar **"foto de perfil"** deve trazer os cards de foto de perfil. Cada modelo deve ser um item próprio do catálogo — **junto dos demais itens, sem seção separada** —, encontrável pelo próprio nome, por apelido e pelo filtro Tipo "Card", levando ao estúdio já com o modelo escolhido. + +Isso revoga explicitamente a decisão D6 do S27 (`docs/plans/central-conteudos-publica-impl.md:81-85`), que rejeitou a entrada catalogada e fixou o tile único — o tile morre, substituído pelos itens individuais. Card continua **não sendo peça**: sem linha no banco, sem arquivo, sem publicação/kill switch próprio; o estúdio `/cards` segue o único lugar que gera o card, no aparelho do visitante. + +## Persona e fluxo + +- **Persona / contexto:** eleitor/simpatizante no celular, chegando por busca ou link do WhatsApp; conhece os cards pelos apelidos ("santinho", "foto de perfil", "colinha"), não pelos nomes oficiais dos modelos. +- **Job principal:** achar o card que ele quer pelo nome que ele usa e cair no estúdio com o modelo já escolhido, sem varrer a galeria inteira. +- **Fluxo desejado:** abre `/conteudos` → busca "santinho" (ou "foto de perfil") ou filtra Tipo "Card" → vê cada modelo como item próprio, com nome, explicação curta e arte → toca no item → chega em `/cards?model=` com o modelo selecionado → faz e baixa o card no aparelho → o catálogo segue igual (nada do card fica lá). +- **Anti-goals de produto:** não transforma card em peça (arquivo, publicação, kill switch); não cria rota, galeria ou segundo estúdio; não move a geração para o servidor/catálogo; não captura dado novo (a foto continua 100% no aparelho); não vira SEO de palavras-chave nem página própria por card. + +### Esboço de fluxo (B) + +```text +[eleitor no celular] → /conteudos +→ busca "santinho" · "foto de perfil" · "colinha" · "estadual" ou Tipo "Card" +→ cada modelo de card aparece como item próprio, misturado às peças (sem seção separada) +→ toca no item → /cards?model= (modelo já escolhido no estúdio) +→ faz/baixa o card no aparelho (nada do card fica no catálogo) +→ volta ao catálogo: peças e cards juntos, sem convite duplicado +[filtro geográfico ativo (Cidade/Região/Instituição)] → cards somem (não são territoriais) +[sem JS] → a busca por querystring continua achando os itens do mesmo jeito +``` + +### Design UI (B) + +- Design UI (gate): `docs/plans/central-conteudos-cards-no-catalogo-ui-design.html` (+ assets em `central-conteudos-cards-no-catalogo-ui-design-assets/`) — itens de card **misturados ao board existente, sem seção/agrupamento próprio** (arte, nome, mini-descrição/apelido, caminho para o estúdio), o estado do filtro Tipo "Card" e o resultado das buscas por apelido. (Revisão do gate: a primeira versão agrupava os cards numa seção própria; o gate cortou a seção.) + +## Objetivo e aceite + +- Cada um dos 6 modelos é um item próprio do catálogo, **na mesma lista dos outros conteúdos, sem seção separada**, encontrável pelo nome do modelo e pelos apelidos: "santinho" traz "Time de você" e "Minha colinha"; "foto de perfil" traz "Moldura quadrada" e "Moldura vertical"; "colinha" traz "Minha colinha"; "estadual" traz "Time do estadual". +- O filtro Tipo "Card" traz os itens de card; a busca por termo e os filtros funcionam sem JS (querystring), como no catálogo atual. +- Cada item leva ao estúdio com o modelo já escolhido (`/cards?model=`); o estúdio segue alcançável pelo estado vazio. +- Guardrail — card não é peça: sem linha no banco, sem mídia, sem publicação/kill switch próprio; o item é um convite ao estúdio, nunca um arquivo para baixar/compartilhar. +- Guardrail — o tile único ("Card personalizado") deixa de existir; nada de convite duplicado. +- Guardrail — **sem seção/agrupamento separado de cards**: eles aparecem misturados aos demais itens do catálogo, sob a mesma busca e os mesmos filtros; nenhum cabeçalho/faixa própria de cards. +- Guardrail — cards não respondem a faceta geográfica (Cidade/Região/Instituição): com faceta ativa, somem do resultado (não são territoriais). +- Guardrail — catálogo sem peça publicada mantém o estado honesto atual (com o caminho para o estúdio), sem inventar um board vazio de cards. +- Guardrail — nada muda no estúdio: foto/recorte 100% no aparelho, sem PII e sem `Consent` novo; o clique no item pode alimentar o mecanismo anônimo do C213/S32 como abertura de card, nunca como peça. + +## Dados (intenção) + +- **Vou apresentar dados?** Não — o item não exibe número/contador; só roteia o visitante ao estúdio. A contagem de uso continua no mecanismo anônimo do C213/S32 (assunto card), sem métrica nova. +- **Decisões desbloqueadas:** o eleitor escolhe o modelo sem varrer a galeria; a comunicação passa a poder ler quais modelos são procurados no catálogo, se a questão (c) for aceita (leitura pelo mecanismo existente). +- **Forma:** *adiada ao plano de implementação* — nenhuma tabela/gráfico; quando muito, o evento anônimo já existente. + +## Dados da decisão (literais) + +- Modelos (id → rótulo atual, fonte única `src/lib/cardModels.ts:65-135`): `eu-sou-solla` → "Card com seu nome"; `perfil-quadrado` → "Moldura quadrada"; `perfil-retangular` → "Moldura vertical"; `time-de-voce` → "Time de você"; `time-do-estadual` → "Time do estadual" (S30, escolha entre 53 estaduais); `minha-colinha` → "Minha colinha" (S31, selo `NOVO`, escolha de estadual). +- Apelidos de busca por modelo (proposta verbatim): "santinho" → `time-de-voce` + `minha-colinha`; "foto de perfil" → `perfil-quadrado` + `perfil-retangular`; "colinha" → `minha-colinha`; "estadual" → `time-do-estadual`; o próprio nome de cada modelo sempre vale. +- URL de destino: `/cards?model=` — o estúdio já valida o id e pré-seleciona o modelo (`src/app/(frontend)/(home)/cards/page.tsx:20-27`). +- Filtro de Tipo: valor existente `card`, rótulo `Card` (`src/lib/contentPiece.ts:24-34`); peça publicada de tipo card continua peça comum, com o comportamento atual. +- Supersessão explícita: a decisão D6 do S27 (`docs/plans/central-conteudos-publica-impl.md:81-85`) fica revogada na parte do tile único; valem os itens individuais por modelo, sem peça catalogada e sem linha no banco. +- Regra de apresentação (decisão do gate): os itens de card aparecem **junto dos demais itens da Central, sem seção separada** — não existe cabeçalho/faixa própria de cards. +- Analytics (se a questão (c) for aceita): o clique no item conta pelo mecanismo único do C213/S32 como abertura de card — `subjectType: 'card'`, `subjectId = model.id` (`src/app/(frontend)/api/content-events/route.ts:95-114`) — nunca como peça; sem segundo analytics. + +## Direção no codebase (hipótese) + +- **Áreas prováveis:** `src/lib/cardModels.ts` (os 6 modelos/rótulos), `src/components/conteudos/` (`ContentPieceCatalog.tsx`, hoje `ContentPieceCardInvite.tsx`), `src/lib/contentPieceCatalog.ts` (itens/facetas/filtro/busca), `src/components/conteudos/ContentPieceFilters.tsx` e `src/app/(frontend)/conteudos/(catalog)/page.tsx` (o `showCardInvite` atual), o deep-link `src/app/(frontend)/(home)/cards/page.tsx` e, se (c) valer, `src/lib/contentEvents.ts` + `src/app/(frontend)/api/content-events/route.ts`. +- **Precedente a olhar:** D6 no `central-conteudos-publica-impl.md:81-85` (o que este item revoga) e `ContentPieceCardInvite.tsx:16-44` (o tile que morre); S30/S31 (modelos/pickers) e S32 (`docs/changelog/2026-09-23-s32.md` — `subjectType: 'card'`, `subjectId = model.id`); S28 (facetas + busca por `searchText`). +- **Risco de acoplamento:** itens sintéticos — nada de collection/migration/kill switch; a lista de modelos/labels é fonte única (não duplicar copy); a busca sem JS é contrato do catálogo; #1277 (`docs/plans/escala-dry-pos-s30.md`) mexe em `src/components/cards/` — sem conflito esperado com o catálogo público, mas serializar se rodar em paralelo. + +## Dependências + +- Nenhuma dura — catálogo (S27/S28) e os 6 modelos (S13–S16, S30, S31) já estão no repo. +- **Suave:** C213/S32, se a questão (c) for aceita (reusa o mecanismo existente, sem nada novo). +- Design UI aprovado no gate. + +## Fora de escopo + +- Card virar peça (linha, arquivo, publicação, kill switch) ou ganhar página/detalhe/OG próprios. +- Rota nova, segunda galeria, alterar o estúdio `/cards` ou o funil de geração (foto/canvas seguem no aparelho). +- Copy editável pelo CMS; busca semântica/tema aplicada a cards além do decidido; facetas próprias de card. +- Analytics novo (o mecanismo é o do C213/S32). +- Redesenho da Central/shell/nav; mudar a regra das peças publicadas (tipo card continua peça comum). + +## Rabbit holes de produto + +- **"Já que virou item, vira peça".** Se alguém "só completar": collection, migration, mídia, publicação e kill switch para cards — dono duplicado do catálogo. **Corte neste item:** item sintético, sem linha; o estúdio é o dono. +- **"Baixar o card direto do catálogo".** Se alguém "só completar": geração no catálogo/servidor e a foto sai do aparelho. **Corte neste item:** o item só leva a `/cards`; o card nasce no aparelho. +- **"Um SEO por card".** Se alguém "só completar": página, título e palavras-chave por modelo, virando segundo catálogo. **Corte neste item:** itens do board + apelidos decididos; sem rota nova. +- **"Card com tema/cidade para combinar com os filtros".** Se alguém "só completar": metadados territoriais/editoriais por card, um segundo modelo de conteúdo. **Corte neste item:** cards fora das facetas geográficas; tema só se um dia declarado (v1: nenhum). +- **"Contar quem fez o card".** Se alguém "só completar": identificar visitante para medir conversão do item. **Corte neste item:** só o evento anônimo existente, se (c) aceita. + +## Questões em aberto (produto) + +- **Como os cards se comportam sob faceta geográfica e temas?** **Opções:** A) ignoram facetas e ficam visíveis | B) excluídos quando faceta geográfica ativa | C) ganham temas próprios declarados. **Recomendação:** B — cards não são territoriais; tema só se declarado por modelo (v1 não declara). _(assumido — validar com produto)_ +- **O tile único "Card personalizado" fica como "ver todos os cards"?** **Opções:** A) fica como entrada geral | B) morre e é substituído pelos itens individuais, com o estúdio alcançável por cada item e pelo estado vazio. **Recomendação:** B — evita convite duplicado e é o pedido do operador. _(assumido — validar com produto)_ +- **O clique no item conta abertura de card ou de peça?** **Opções:** A) abertura de card (`subjectType: 'card'`, `subjectId = model`) pelo mecanismo do C213/S32 | B) abertura de peça | C) não conta. **Recomendação:** A — mede o interesse real no modelo sem duplicar como peça. _(assumido — validar com produto)_ + +## Referências + +- GitHub Issue — a registrar (`pnpm agent:register`). +- Design UI (gate): `docs/plans/central-conteudos-cards-no-catalogo-ui-design.html` (+ assets em `central-conteudos-cards-no-catalogo-ui-design-assets/`) +- `docs/plans/central-conteudos-publica-impl.md:81-85` (D6 revogada) e `docs/plans/central-conteudos-publica.md` (S27 — o catálogo e o tile) +- `src/components/conteudos/ContentPieceCardInvite.tsx:16-44`, `src/components/conteudos/ContentPieceCatalog.tsx:50-55`, `src/app/(frontend)/conteudos/(catalog)/page.tsx:108,153-157` +- `src/lib/cardModels.ts:65-135`, `src/lib/contentPieceCatalog.ts:39-107,155-269,506-548`, `src/components/conteudos/ContentPieceFilters.tsx` +- `src/app/(frontend)/api/content-events/route.ts:95-114`, `src/lib/contentEvents.ts`, `docs/changelog/2026-09-23-s32.md` +- `docs/plans/escala-dry-pos-s30.md` (#1277 — sobreposição só em `components/cards/`) + +## Self-score (shaping) + +5/5 — (1) fatia = um outcome verificável (cada modelo encontrável por nome, apelido, busca e Tipo "Card"); (2) appetite ~1–1,5 dia cabe: itens sintéticos no board e nos filtros existentes, sem rota nem migration; (3) persona/job/aceite em linguagem de produto, com os apelidos literais do dono e o guardrail "card não é peça"; (4) direção no codebase é hipótese, com D6 e o tile atual abertos como pista; (5) zero decisão dura de engenharia — sem collection/schema/signature, com as três dúvidas de produto posicionadas. diff --git a/docs/plans/central-conteudos-header-logo-ui-design.html b/docs/plans/central-conteudos-header-logo-ui-design.html new file mode 100644 index 00000000..581ea964 --- /dev/null +++ b/docs/plans/central-conteudos-header-logo-ui-design.html @@ -0,0 +1,96 @@ + + + + + + + Design — S33 · Marca no header da Central + + + +
+
+ S33 · decisão visual +

A marca volta a assinar a Central.

+

Mesmo header, mesma altura e mesma copy. O gate escolhe somente o ativo e seu peso visual.

+
+ +
+
CENA 01

Desktop 1280 · opções A e B lado a lado

+
+
+ +
+
+ Jorge Solla 1313 — Mais Saúde, Mais Futuro + Central de Conteúdos +
+
+

B · Marca negativa completa

+

Oficial e correta sobre vermelho, mas comprime nome, número e slogan na barra de 64 px. O slogan perde leitura e a massa vertical compete com o nome da seção.

+
+
+
+
+

DECISÃO RECOMENDADA

+

A · manter o lockup e corrigir a caixa, não redesenhar o header.

+

Altura do header: 64 px. Inset horizontal: 32 px dentro do conteúdo. Lockup visível: 188 × 50 px. Badge existente: 14 px, bold. Sem novo lockup e sem alteração de cor.

+
+
+
+ +
+
CENA 02

Mobile 390 · as duas opções na barra real de 56 px

+
+
+
+
Jorge Solla
☰ +
+
A · RECOMENDADA

Central de Conteúdos

A assinatura continua reconhecível sem disputar espaço com o menu.

+
+
+
Jorge Solla 1313 — Mais Saúde, Mais Futuro☰
+
B · ALTERNATIVA

Central de Conteúdos

O conjunto completo fica pequeno demais para o slogan cumprir sua função.

+
+
+
+ +
+
CENA 03

Página da peça · “Voltar à Central” e badge preservados

+
+
+
Jorge Solla
Voltar à Central +
+
+
NEEDS ASSET · PREVIEW REAL DA PEÇA
+
Central de Conteúdos

Título da peça publicada

Descrição editorial da peça, sem alteração neste item.

+
+
+
+
Jorge Solla
Voltar à Central
+
Central de Conteúdos

Título da peça publicada

+
+
+
+ + diff --git a/docs/plans/central-conteudos-header-logo.md b/docs/plans/central-conteudos-header-logo.md new file mode 100644 index 00000000..03b3f952 --- /dev/null +++ b/docs/plans/central-conteudos-header-logo.md @@ -0,0 +1,99 @@ +# S33 — Central de Conteúdos — logo do header no tamanho da marca + +Status: rascunho +Atualizado em: 2026-09-23 +Issue: #1301 +Priority: P2 +Impeccable: B — encaixe no header existente da Central pública (sem rota nova) +Design UI: docs/plans/central-conteudos-header-logo-ui-design.html +Appetite: ~0,25–0,5 dia eng; correção de fidelidade visual no header +Responsável: — + +## Intenção + +No header da Central de Conteúdos pública (`/conteudos`), a marca lê muito menor do que no resto do site público — testado em staging pelo operador. O ativo oficial tem uma moldura transparente grande em volta do desenho, então a caixa do header mostra só uma fração dele: a marca fica com peso de detalhe, não de assinatura. A Central é a casa das peças de "Peça voto pra Solla 1313" e o header é a primeira coisa que o eleitor vê; a marca precisa ler no mesmo peso das outras páginas públicas, tirada do kit como fonte única (sem lockup novo, sem paleta inventada). + +## Persona e fluxo + +- **Persona / contexto:** eleitor/simpatizante no celular, com pressa, chegando de um link compartilhado no WhatsApp; a Central ainda não é familiar e a marca no topo é a âncora de confiança de que ele está no lugar certo. +- **Job principal:** reconhecer de imediato que está na Central oficial de Solla 1313 e seguir para a peça. +- **Fluxo desejado:** abre `/conteudos` → vê a marca no topo no mesmo peso das outras páginas públicas → filtra/escolhe a peça; na página da peça e no estado de não encontrado, a mesma marca com o caminho de volta. +- **Anti-goals de produto:** não vira redesign do header (nem da Central); não cria rota nem tela nova; não troca a marca por um lockup próprio nem inventa cor/tipografia; não mexe em copy, badge ou comportamento do "Voltar à Central"; não é passada de olho nas outras páginas públicas. + +### Esboço de fluxo (B) + +```text +[abre /conteudos (catálogo, peça, não encontrado)] → [header vermelho com a marca no peso das outras públicas] +→ [segue para a peça / volta à Central] +``` + +### Design UI (B) + +- Design UI (gate): `docs/plans/central-conteudos-header-logo-ui-design.html` — o humano valida no gate que a marca lê no peso certo nos dois breakpoints, com a opção de ativo escolhida. + +## Objetivo e aceite + +- A marca no header da Central lê, nos dois breakpoints, no mesmo peso visual do header público de referência (`/jingles`) — aferido lado a lado em staging. +- Fonte única da marca é o kit 1313 (`public/campaign-kit/`); nenhum lockup recriado, nenhuma cor ou tipografia inventada. +- A correção vive no header da Central (escolha de ativo e/ou tamanho renderizado), sem redesenhar o header. +- Badge "Central de Conteúdos", link "Voltar à Central" e comportamento nos dois breakpoints permanecem. +- Nenhuma outra página pública muda (sem drive-by). + +## Dados (intenção) + +- **Vou apresentar dados?** Não. +- **Decisões desbloqueadas:** N/A — correção de fidelidade visual; nenhum ator decide com número. +- **Forma:** *adiada ao plano de implementação* — sem restrição de produto além da referência de peso visual acima. + +## Dados da decisão (literais) + +- Superfícies do header: `/conteudos` (catálogo, com e sem peças publicadas), `/conteudos/` e o não encontrado da peça — todas usam `ContentPiecePageHeader`. +- Header atual: `src/components/conteudos/ContentPiecePageHeader.tsx:12-22` — ``, dentro de um `div` `h-14 sm:h-16` sobre `bg-[#ae1603]`. +- Ativo atual: canvas 1037×595; recorte visível 790×285 (transparência topo 162, base 148, esquerda 123, direita 124) → marca visível ≈13,4 px em `h-7` e ≈17,2 px em `sm:h-9`. +- Referência de peso (`/jingles`): `src/components/CampaignPageHeader.tsx:20-27` com `marca-positiva-completa.png` (visível 552×415 no mesmo canvas 1037×595) em `h-[66px] sm:h-[74px]` → ≈46/52 px visíveis (≈3× a marca da Central). +- O ativo negativo `jorge-solla-negativo.png` só é usado em `ContentPiecePageHeader.tsx:16`; o S27 portou fielmente o `h-9` do artefato `docs/plans/central-conteudos-publica-ui-design.html:158-164,427-433` (cenas 01/04), mas artefato+ativo juntos renderizam pequeno. +- Dono da marca: `public/campaign-kit/README.md` (kit 1313). A pasta já tem, para fundo vermelho/escuro, a **marca completa** `marca-negativa-completa.png` (nome + 1313 + slogan; visível 552×415 no mesmo canvas, `README.md:35-37`) — ativo diferente do lockup de nome usado no header hoje; e não tem nenhuma variante **recortada** do lockup `jorge-solla-negativo.png`. + +## Direção no codebase (hipótese) + +- **Áreas prováveis:** `src/components/conteudos/ContentPiecePageHeader.tsx` (único componente do header da Central) e `public/campaign-kit/` (ativo/kit); rotas consumidoras em `src/app/(frontend)/conteudos/`. +- **Precedente a olhar:** `src/components/CampaignPageHeader.tsx` (header de `/jingles`, mesmo canvas, peso-alvo) e o S27 `docs/plans/central-conteudos-publica.md`. +- **Risco de acoplamento:** o header é page-local da Central (não é shell do site) — a correção não deve virar componente compartilhado nem alterar `CampaignPageHeader`. + +## Dependências + +- Nenhuma dura. Contexto: S27 (#1255) entregou a Central pública e o header. + +## Fora de escopo + +- Redesenho do header da Central ou da página (fica para novo item, se houver pedido). +- Outras páginas públicas e seus headers (`/jingles`, home, `/cards`) — sem mudanças de carona. +- Recriar lockup, paleta ou tipografia; qualquer coisa fora do kit 1313. +- Copy, badge, CTA e comportamento do "Voltar à Central". +- Qualquer mudança de dados, consentimento ou rotas. + +## Rabbit holes de produto + +- **"Já que estou no header, padronizo os outros."** Se alguém "só completar": vira refactor de todos os headers públicos e revisão de marca. **Corte neste item:** só o header da Central. +- **"Monto um lockup novo com o ativo recortado no Figma."** Se alguém "só completar": nasce uma marca paralela fora do kit. **Corte neste item:** kit como fonte única; no máximo preparo técnico do ativo oficial (recorte do PNG existente), não desenho novo. +- **"Ajusto o header inteiro para caber a marca."** Se alguém "só completar": muda altura, espaçamento e badge das telas. **Corte neste item:** a menor mudança que faça a marca ler no peso certo. + +## Questões em aberto (produto) + +- **Qual ativo/tamanho faz a marca ler no peso certo?** **Opções:** A) lockup `jorge-solla-negativo.png` com o recorte técnico da moldura transparente (preparo do ativo oficial no kit, sem redesenho); B) usar a marca completa `marca-negativa-completa.png` (nome + 1313 + slogan), que o kit destina a fundos vermelhos/escuros e tem proporção visível muito maior; C) compensar no header o tamanho renderizado do lockup atual, sem distorcer. **Recomendação:** decidir no gate com o design hi-fi mostrando A e B lado a lado (o lockup é o que o S27 desenhou; a marca completa é o ativo do kit para o fundo vermelho); C só se nenhuma das duas servir. _(assumido — validar no gate do design)_ + +## Referências + +- Design UI (gate): `docs/plans/central-conteudos-header-logo-ui-design.html` (+ assets em `central-conteudos-header-logo-ui-design-assets/`). +- `docs/plans/central-conteudos-publica-ui-design.html` — artefato do S27 (cenas 01/04/06/07/08: header com `h-9`). +- `src/components/conteudos/ContentPiecePageHeader.tsx`, `src/components/CampaignPageHeader.tsx`, `public/campaign-kit/README.md`. +- S27: `docs/plans/central-conteudos-publica.md` (Issue #1255). + +## Self-score (shaping) + +1. Fatia = um outcome verificável? 5/5 — a marca no peso certo, aferida lado a lado em staging. +2. Appetite declarado e a intenção cabe nele? 5/5 — ~0,25–0,5 dia; uma escolha de ativo/tamanho. +3. Persona + job + aceite claros (sem jargão de stack)? 4/5 — aceite fala em peso visual; a aferição exige comparação em staging. +4. Direção no codebase é hipótese (não contrato técnico)? 5/5 — arquivos e classes são literais de estado atual/evidência, não prescrição. +5. Zero decisões duras de engenharia no plano? 4/5 — a questão em aberto recomenda decidir no gate; a escolha final (ativo vs compensação) fica para o gate/impl. +Média: 4,6/5 — ≥4/5. diff --git a/docs/plans/central-conteudos-liderancas-ui-design.html b/docs/plans/central-conteudos-liderancas-ui-design.html new file mode 100644 index 00000000..8303ff4f --- /dev/null +++ b/docs/plans/central-conteudos-liderancas-ui-design.html @@ -0,0 +1,38 @@ + + + + + + Design — S34 · Lideranças nas peças + + + +
+
S34 · dois recortes, uma faceta

Quem aparece na peça fica encontrável — sem expor quem não aparece.

A ficha separa liderança interna de figura pública; a Central pública reúne apenas os nomes presentes em peças publicadas.

+ +
CENA 01

Ficha interna · desktop 1280 · os dois recortes

+
Campanha · ComunicaçãoCentral de Conteúdos
← Conteúdos

Título da peça em revisão

ProntoRascunho
+
+

Título

Título da peça em revisão

Quem aparece na peça

Marque somente pessoas visíveis ou participantes desta peça. A publicação expõe apenas o nome.

Curadoria humana
+

Lideranças da campanha

Busca nos registros existentes. Nenhum telefone, município ou voto vai para a Central pública.

Nome da liderança ×
Buscar liderança…⌄
Nome da liderançaRegistro da campanha
Outra liderança de exemplo
+

Figuras públicas

Texto curado com catálogo, no mesmo molde de Instituição.

Dep. Estadual Exemplo ×
Digite ou escolha uma figura pública…⌄
Dep. Estadual ExemploFigura pública catalogada
Personalidade Exemplo
+

Instituição

Sem instituição

Cidade

Sem cidade
+
+
+ +
CENA 02

Ficha interna · mobile 390 · pessoa marcada e ninguém marcado

+
Central de Conteúdos☰
← Conteúdos

Título da peça

Quem aparece na peça

Somente o nome poderá aparecer no filtro público.

Lideranças da campanha

Nome da liderança ×
Buscar liderança…⌄

Figuras públicas

Dep. Estadual Exemplo ×
Digite ou escolha…⌄
+
Central de Conteúdos☰
← Conteúdos

Peça sem ninguém marcado

Quem aparece na peça

Ninguém marcado. A peça pode ser publicada normalmente e não cria nenhum nome na faceta “Lideranças”.

Lideranças da campanha

Buscar liderança…

Figuras públicas

Digite ou escolha…
+
+ +
CENA 03

Catálogo público · faceta única “Lideranças” · desktop e mobile

+
Central de Conteúdos
Encontre uma peça por assunto, cidade ou pessoa…
Tipo⌄Cidade⌄Região⌄Tema⌄Instituição⌄
Lideranças⌄

EM PEÇAS PUBLICADAS

Nome da liderança
Dep. Estadual Exemplo
Personalidade Exemplo

Peças com Nome da liderança

O filtro combina com cidade, tema e os demais recortes.

Lideranças · Nome da liderança ×
NEEDS ASSET · PREVIEW REAL
Vídeo

Título da peça publicada

Nome da liderança · Tema

Regra visível do gate: este menu é derivado somente das peças publicadas. Despublicar a última peça de um nome remove esse nome da faceta imediatamente. Sem contato, território, organização, status ou votos.
+
☰
Busque uma pessoa…
Tipo⌄Lideranças · Nome da liderança ×

LIDERANÇAS · EM PEÇAS PUBLICADAS

Nome da liderança
Dep. Estadual Exemplo
NEEDS ASSET · PREVIEW REAL
Vídeo

Título da peça publicada

Nome da liderança

+
+
+ + diff --git a/docs/plans/central-conteudos-liderancas.md b/docs/plans/central-conteudos-liderancas.md new file mode 100644 index 00000000..ffc5214f --- /dev/null +++ b/docs/plans/central-conteudos-liderancas.md @@ -0,0 +1,119 @@ +# S34 — Central de Conteúdos — lideranças que aparecem nas peças (propriedade e filtro) + +Status: rascunho +Atualizado em: 2026-09-23 +Issue: #1303 +Priority: P2 +Impeccable: C — propriedade nova na ficha interna (C211) + faceta nova no catálogo público (S27) +Design UI: docs/plans/central-conteudos-liderancas-ui-design.html +Appetite: ~2 dias eng; um outcome verificável (a peça registra quem aparece e o catálogo público filtra por isso) +Responsável: — + +## Intenção + +A campanha já tem a Central de Conteúdos interna (C211), onde a assessoria cataloga as peças, e a Central pública (S27), onde o eleitor filtra por Tipo, Cidade, Região, Tema e Instituição — mas "quem aparece na peça" não existe em lugar nenhum. Numa campanha de dobradinhas, é exatamente esse o recorte que o eleitor procura: o material em que a liderança dele ou o estadual dele aparece, para repassar no grupo. A comunicação quer registrar isso na peça; o eleitor quer filtrar por isso. A decisão do humano no planejamento foi "Os dois": a peça registra as lideranças da campanha que aparecem E as figuras públicas (dobradinhas/estaduais e outras personalidades), e o catálogo público tem os dois recortes na mesma faceta `Lideranças`. O cuidado que define o item: o que é interno (liderança é PII, escopada por perfil) não pode vazar no que é público — a faceta mostra só nomes de quem aparece em peça publicada. + +## Persona e fluxo + +- **Persona / contexto:** dois atores. A assessoria de comunicação, na mesa, editando a ficha da peça (o mesmo gate que já edita a ficha hoje); o eleitor/liderança, no celular, na Central, procurando o material em que a referência dele aparece. +- **Job principal:** (comunicação) registrar quem aparece na peça; (eleitor) achar a peça em que uma pessoa aparece e repassá-la. +- **Fluxo desejado:** comunicação abre a ficha da peça → marca as lideranças da campanha que aparecem e as figuras públicas (dobradinhas/personalidades) → publica; eleitor abre `/conteudos` → filtra pela faceta `Lideranças` → vê só nomes de quem aparece em peça publicada → abre a peça e compartilha. +- **Anti-goals de produto:** segundo cadastro de pessoa; expor qualquer dado interno de liderança; virar diretório de lideranças ou placar de aparições; página pública por pessoa; mudar o que a liderança vê hoje (leader lockdown intocado). + +### Esboço de fluxo (C) + +```text +[assessoria] ficha da peça (C211) +→ marca quem aparece: lideranças da campanha (registros de Liderança) + figuras públicas (dobradinhas/personalidades) +→ publica a peça +[eleitor] /conteudos → faceta `Lideranças` (os dois recortes no mesmo filtro) +→ só nomes de quem aparece em pelo menos uma peça publicada (fail-closed) +→ abre a peça → baixa/compartilha +[peça despublicada] → o nome some da faceta se não houver outra peça publicada com ele +``` + +### Design UI (C) + +- Design UI (gate): `docs/plans/central-conteudos-liderancas-ui-design.html` (+ assets em `central-conteudos-liderancas-ui-design-assets/`) — cenas: ficha interna com os dois recortes (lideranças + figuras públicas), faceta `Lideranças` no catálogo público (mobile/desktop) e o estado de peça sem ninguém marcado. + +## Objetivo e aceite + +- A ficha da peça registra dois recortes de "quem aparece": (1) as lideranças da campanha — os registros de Liderança existentes, sem cadastro novo — e (2) figuras públicas (dobradinhas/estaduais e outras personalidades), em texto curado com catálogo, no molde de Instituição. +- O catálogo público ganha a faceta `Lideranças`, unindo os dois recortes no mesmo filtro (decisão do humano: "Os dois"); os filtros continuam combinando entre si como hoje. +- **Fail-closed de exposição:** a faceta mostra só NOMES de pessoas referenciadas por pelo menos uma peça publicada; nunca expõe liderança ou figura que não aparece em peça publicada. +- **Nada de dado interno:** sem contato, telefone, e-mail, municípios, organizações, status ou votos (declarados/estimados) de liderança; o leader lockdown segue intocado. +- Quem edita é quem já edita a ficha hoje (gate da assessoria de comunicação); a catalogação pode sugerir, mas nunca sobrescreve curadoria humana. +- Os nomes marcados entram na busca por termo da Central como qualquer outro conteúdo — buscar o nome de quem aparece acha a peça. +- Publicar/despublicar atualiza a faceta na hora: sem peça publicada com o nome, ele não aparece. +- Guardrails: sem cadastro paralelo de pessoa (relaciona ao dono existente ou usa o molde texto+catálogo); nada novo de PII é capturado e Consent/LGPD ficam intocados — a metade "lideranças da campanha" só mostra dados quando existirem lideranças (o dado de liderança segue atrás do bloqueio LGPD de produção). + +## Dados (intenção) + +- **Vou apresentar dados?** Não — a faceta é uma lista de nomes; sem contagem, sem ranking, sem placar de aparições. +- **Decisões desbloqueadas:** a comunicação decide quem aparece em cada peça; o eleitor decide qual peça procurar pelo nome de quem aparece nela. +- **Forma:** *adiada ao plano de implementação* — restrição de produto: só nomes de exibição (sem número, sem contagem por pessoa, sem métrica de aparições). + +## Dados da decisão (literais) + +- ID `S34`; slug `central-conteudos-liderancas` (arquivo `docs/plans/central-conteudos-liderancas.md`); tipo `feature`; Priority `P2`. +- Faceta pública: rótulo `Lideranças` (uma só), unindo os dois recortes no mesmo filtro. +- Recorte 1 — lideranças da campanha: os registros de `Liderança` existentes (dono atual; não criar cadastro de pessoa). +- Recorte 2 — figuras públicas: dobradinhas/estaduais do roster público e outras personalidades, em texto curado com catálogo (molde de `Instituição`), semeado com os nomes das dobradinhas. +- Regra de exposição (fail-closed): só NOMES de pessoas que aparecem em pelo menos uma peça publicada; sem peça publicada, o nome não aparece. +- Resposta do humano no planejamento (verbatim): **"Os dois"** — a peça registra lideranças da campanha E figuras públicas, e o filtro público tem os dois recortes na mesma faceta. +- Guardrail literal: **sem cadastro paralelo de pessoa**; sem exposição de contato/território/votos da liderança. + +## Direção no codebase (hipótese) + +- **Áreas prováveis:** ficha interna da peça (`src/components/campaign/content/ContentPieceForm.tsx`, `src/utilities/content/…`); contrato/filtro público (`src/lib/contentPieceCatalog.ts`, `src/components/conteudos/ContentPieceFilters.tsx`); catalogação (`src/utilities/content/contentPieceCataloging.ts`). +- **Precedente a olhar:** `institution` — campo texto na peça (`src/collections/ContentPiece.ts:303-307`) + catálogo (`src/lib/institutionCatalog.ts`) + aliases (`src/lib/institutionNameAliases.ts`) + match na catalogação (`contentPieceCataloging.ts:181-193`); a faceta pública deriva rótulos das peças publicadas por `slugify` (`contentPieceCatalog.ts:155-184,252-269`), parâmetro `instituicao` (`:39-55,96-107`). `Speech.mentionedPeople` (`src/collections/Speech.ts:306-312`) é precedente de "pessoas citadas" por texto, mas sem filtro público — não copiar o par acervo/C200. +- **Roster público de pessoas:** `src/lib/stateDeputyCatalog.ts` (53 dobradinhas, nome+número, público via S30). +- **Risco de acoplamento:** `leadership` é interno e PII-bound (leitura escopada por perfil — `src/utilities/access/leaderships.ts:31-32`); a superfície pública não pode ler `leadership`, `Contact`, `campaignUser` ou `electionCandidate` nem expor campo interno — os nomes públicos derivam só das peças publicadas. A busca pública casa o texto normalizado da peça (`src/lib/contentPiece.ts:323`), então o nome precisa ser encontrável por lá. Leader lockdown intocado. + +## Dependências + +- C211 (peças catalogadas/publicadas) e S27 (catálogo público com facetas) entregues — dura: sem peça publicada não há nome na faceta. +- Roster das dobradinhas (S30) como semente do recorte de figuras públicas — soft. +- Design hi-fi aprovado no gate. + +## Fora de escopo + +- Cards personalizados: a escolha do estadual no estúdio (S30/S31) é do visitante, não propriedade da peça. +- C200 (separação por pessoa no acervo / speakers em gravações, #1167) — superfície distinta; não acoplar. +- Expor qualquer dado interno de liderança (contato, telefone, e-mail, municípios, organizações, votos declarados/estimados). +- Mudanças de LGPD/Consent: nada novo de PII é capturado; o dado de liderança segue atrás do bloqueio LGPD de produção (a metade campanha só mostra quando houver lideranças). +- Filtro/coluna na lista interna de peças — só se o gate pedir (ver Q(a)). +- Página pública por pessoa, diretório/ranking de aparições, analytics de circulação (C213). + +## Rabbit holes de produto + +- **Cadastro paralelo de pessoa.** Se alguém "só completar": collection de "pessoas que aparecem" com nome/telefone/cidade. **Corte neste item:** liderança = registro existente; figura pública = texto curado + catálogo; nenhum cadastro novo. +- **A faceta virar diretório de lideranças.** Se alguém "só completar": listar todas as lideranças, com município e status. **Corte neste item:** só nomes de quem aparece em peça publicada; nada de dado interno. +- **Placar de aparições.** Se alguém "só completar": contador por pessoa, "quem aparece mais", ranking. **Corte neste item:** lista de nomes sem número. +- **Página por pessoa.** Se alguém "só completar": `/conteudos/pessoa/` ou um hub da liderança. **Corte neste item:** uma faceta no catálogo existente; a peça continua sendo a unidade. +- **A catalogação automática decidir por gente.** Se alguém "só completar": o pipeline preenche e sobrescreve os nomes. **Corte neste item:** sugestão só quando confiável; curadoria humana manda. + +## Questões em aberto (produto) + +- **Filtro só público ou também filtro/coluna na lista interna?** **Opções:** A) faceta pública (o pedido) + propriedade visível/editável na ficha interna | B) também filtro/coluna na lista interna. **Recomendação:** A — é o pedido; filtro/coluna interno só se o gate pedir. _(assumido — validar com produto)_ +- **Uma faceta unindo os dois recortes ou duas facetas?** **Opções:** A) uma faceta `Lideranças` com os dois recortes | B) `Lideranças` + `Figuras públicas`. **Recomendação:** A — o humano escolheu "Os dois" no mesmo filtro; B fica registrada como alternativa se o volume de figuras públicas justificar separar. _(assumido — validar com produto)_ +- **O recorte de figuras públicas reusa o roster das dobradinhas ou é texto com aliases?** **Opções:** A) texto curado + catálogo no molde de Instituição, semeado com os nomes das dobradinhas | B) só o roster fechado das 53 dobradinhas | C) texto livre sem catálogo. **Recomendação:** A — cobre dobradinhas e outras personalidades sem inventar cadastro; C perde o casamento de grafias. _(assumido — validar com produto)_ +- **Que nome da liderança aparece?** **Opções:** A) o nome do contato (é o título da Liderança hoje) | B) algum rótulo composto. **Recomendação:** A — só o nome; nunca telefone, e-mail ou município. _(assumido — validar com produto)_ + +## Referências + +- GitHub Issue — a registrar (`pnpm agent:register`). +- Design UI (gate): `docs/plans/central-conteudos-liderancas-ui-design.html` (+ assets em `central-conteudos-liderancas-ui-design-assets/`). +- Planos irmãos: `docs/plans/central-conteudos-ingestao.md` (C211), `docs/plans/central-conteudos-publica.md` (S27), `docs/plans/cards-estadual-dobradinha.md` (S30), `docs/plans/acervo-separacao-por-pessoa.md` (C200 — fora de escopo). +- Arquivos-pista: `src/collections/ContentPiece.ts`, `src/components/campaign/content/ContentPieceForm.tsx`, `src/lib/contentPieceCatalog.ts`, `src/components/conteudos/ContentPieceFilters.tsx`, `src/lib/institutionCatalog.ts`, `src/lib/institutionNameAliases.ts`, `src/utilities/content/contentPieceCataloging.ts`, `src/lib/stateDeputyCatalog.ts`, `src/collections/Leadership.ts`, `src/utilities/access/leaderships.ts`, `src/collections/Speech.ts`. +- `AGENTS.md` — convenções já travadas (Contact como dono da pessoa; sem cadastro paralelo; migrations para schema). + +## Self-score (shaping) + +5/5 — um outcome verificável, appetite declarado e nenhuma decisão dura de engenharia. + +- Fatia = um outcome verificável: a peça registra quem aparece e o catálogo público filtra por isso. +- Appetite ~2 dias cabe: uma propriedade na ficha existente + uma faceta no catálogo existente, sem fluxo novo. +- Persona + job + aceite claros, em linguagem de produto, sem jargão de stack. +- Direção no codebase é hipótese: arquivos citados como pista, nenhum nome novo cravado. +- Zero schema/migration/signature no plano; literais são só de produto (rótulo, recortes, regra de exposição e a resposta do humano). diff --git a/docs/plans/central-conteudos-link-instagram-ui-design.html b/docs/plans/central-conteudos-link-instagram-ui-design.html new file mode 100644 index 00000000..c7646098 --- /dev/null +++ b/docs/plans/central-conteudos-link-instagram-ui-design.html @@ -0,0 +1,46 @@ + + + + + + Design — C215 · Link do Instagram + + + +
+
C215 · ficha existente

O link nunca degrada em silêncio.

A ficha conta o que está acontecendo, o que foi extraído e por que uma peça ficou apenas como link.

+ +
CENA 01

Desktop 1280 · processando → extraída e catalogada

+
+
+
← Conteúdos

Peça adicionada pelo Instagram

ProcessandoRascunho
+
+

Processamento da peça

  1. 1. Link recebido

    Concluído

  2. 2. Mídia oficial

    Em andamento

  3. 3. Catalogação

    Aguardando

Título

Disponível após a catalogação

Tipo

—

Transcrição / texto

+
+
ProntoEstado final — mídia extraída
NEEDS ASSET · PREVIEW REAL

Arquivo e transcrição prontos

A mídia oficial foi baixada e a ficha foi catalogada. Revise os campos antes de publicar.

“Transcrição gerada aparece aqui para revisão editorial.”
+
+
+
+ +
CENA 02

Peça-link · motivo honesto e caminho para anexar o original

+
← Conteúdos

Peça adicionada pelo Instagram

ProntoRascunho
+
+

Motivo da peça-link

A ficha mostra um destes quatro motivos, sem código de erro nem jargão técnico.

Motivo

Link não encontrado entre as mídias recentes do perfil

Motivo

Carrossel: sem arquivo único para baixar

Motivo

Instagram indisponível no momento

Motivo

Sem credencial do Instagram configurada

Mídia de terceiro nunca é baixada. Esta peça não foi apagada e continua circulando pelo link.
+
+
+
+ +
CENA 03

Mobile 390 · estados essenciais na ficha e lista compacta

+
+
Central de Conteúdos☰
← Conteúdos

Peça adicionada pelo Instagram

ProcessandoRascunho
Buscando mídia oficial…

Procurando a publicação no perfil oficial…

+
Central de Conteúdos☰
← Conteúdos

Peça adicionada pelo Instagram

ProntoRascunho
Peça-link

Por que o arquivo não foi baixado

Carrossel: sem arquivo único para baixar

A peça continua disponível pelo link.

+
Conteúdos☰
Peça adicionada pelo InstagramProcessando

Instagram · Preparando a peça…

Peça adicionada pelo InstagramPronto

Instagram · Peça-link

Recomendação: a lista continua limpa; o motivo completo vive na ficha.

+
+
+
+ + diff --git a/docs/plans/central-conteudos-link-instagram.md b/docs/plans/central-conteudos-link-instagram.md new file mode 100644 index 00000000..cc2d984e --- /dev/null +++ b/docs/plans/central-conteudos-link-instagram.md @@ -0,0 +1,112 @@ +# C215 — Central de Conteúdos — link do Instagram do deputado baixa e cataloga a peça + +Status: rascunho +Atualizado em: 2026-09-23 +Issue: #1302 +Priority: P1 +Impeccable: B — encaixe na lista/ficha existentes do C211 (estado honesto), sem tela nova +Design UI: docs/plans/central-conteudos-link-instagram-ui-design.html +Appetite: ~1,5–2 dias eng; um outcome verificável — link do próprio perfil deixa de degradar em silêncio +Responsável: — + +## Intenção + +A assessoria de comunicação colou na Central de Conteúdos (`/campanha/comunicacao/conteudos`) o link de uma peça do **próprio** Instagram do deputado e a peça não foi baixada nem analisada: virou uma "peça-link" em silêncio. A promessa do fluxo — decidida no gate e registrada no C212 — é que peça adicionada por link tenha a mídia extraída e catalogada quando houver caminho oficial. O caminho oficial existe (Graph API da própria conta) e o pipeline existe; o que faltou foi o link do próprio perfil ser encontrado e resolvido. Este item conserta essa quebra. + +## Persona e fluxo + +- **Persona / contexto:** assessoria de comunicação (`communicator`) na mesa, operando a Central, colando links das peças do perfil oficial (@depjorgesolla) que acabaram de sair. +- **Job principal:** colar o link de uma peça do próprio Instagram e receber a peça baixada, transcrita e catalogada — como se tivesse enviado o arquivo. +- **Fluxo desejado:** cola o link → a peça nasce "Processando" → o post é procurado no perfil oficial → achou e é extraível: arquivo baixado, transcrito e catalogado → não achou/não extraível: peça-link **com motivo honesto na ficha** → assessoria revisa/edita ou anexa o arquivo; nada é apagado. +- **Anti-goals de produto:** não vira varredura automática do perfil; não vira tela nova nem segundo fluxo de configuração; não vira scraping/contorno; não baixa mídia de terceiro; não apaga peça-link; não encosta no board da home. + +### Esboço de fluxo (B) + +```text +[Central] → "Adicionar por link" → cola link do próprio perfil + (ex.: instagram.com/depjorgesolla/reel/ABC/ · .../reel/ABC/?igsh=… · .../p/ABC/) + → peça "Processando" → busca o post no perfil oficial (além das 50 mais recentes) + → achou + extraível: baixa o arquivo → transcreve → cataloga (igual ao envio por arquivo) + → não achou / não extraível: peça-link com motivo na ficha + ("Link não encontrado…" · "Carrossel…" · "Instagram indisponível…" · "Sem credencial…") + → revisa, edita, anexa o arquivo se quiser — a peça nunca é apagada +[outcome: link do próprio perfil vira peça baixada e catalogada — ou falha com motivo, nunca em silêncio] +``` + +### Design UI (B) + +- Design UI (gate): `docs/plans/central-conteudos-link-instagram-ui-design.html` + +## Objetivo e aceite + +- Colar um link do próprio perfil — nas formas que o browser copia — resulta em peça com mídia baixada, transcrita e catalogada, igual ao envio por arquivo. +- A busca pelo post colado não para na janela atual: vai para trás o suficiente para o uso real, com limite declarado; post além do limite recebe motivo honesto (não silêncio). +- Quando a extração não acontecer, a ficha mostra o motivo em linguagem de produto (vocabulário literal abaixo). Peça-link é resultado legítimo, não "Falhou". +- Peça-link continua fallback: circula pelo link, o arquivo original pode ser anexado e a peça nunca é apagada. +- Curadoria preservada: campos que a assessoria editou não são sobrescritos pela catalogação. +- **Guardrails:** extração só por caminho oficial (Graph API da própria conta) — nunca scraping/contorno; mídia de terceiro nunca é baixada; token nunca em log; o contrato do feed/board da home (cache de 5 min, snapshot, kill switch) não é reusado nem alterado; YouTube segue link-only por desenho (a Data API não entrega arquivo) — sem motivo de falha. + +## Dados (intenção) + +- **Vou apresentar dados?** Não — não há agregado nem KPI; o que muda é o estado da peça e o motivo visível na ficha. +- **Decisões desbloqueadas:** N/A — a decisão da assessoria é editorial/operacional ("anexar o arquivo original?"), não numérica. +- **Forma:** N/A — restrição: motivo em linguagem de produto, sem código de erro, stack ou jargão de API. + +## Dados da decisão (literais) + +- **Decisão do gate (C212, verbatim):** "Quando o assessor adiciona uma peça por link do Instagram ou Youtube, a mídia deve ser automaticamente extraída e catalogada." — com o corte do C211: **quando houver caminho oficial**. +- **Motivos (verbatim):** "Link não encontrado entre as mídias recentes do perfil" · "Carrossel: sem arquivo único para baixar" · "Instagram indisponível no momento" · "Sem credencial do Instagram configurada". +- **Formas de link aceitas:** `instagram.com` com `p|reel|reels|tv` + shortcode, com ou sem `www.`/`m.`, query ignorada (`?igsh=` ok) e **caminho prefixado pelo perfil** (`/depjorgesolla/reel//`, `/depjorgesolla/p//`); rejeitar `/stories/`, `instagr.am` e hosts fora de Instagram/YouTube (como hoje). +- **Fallback:** peça-link permanece, com aviso na ficha; "Mídia de terceiro nunca é baixada"; o arquivo original pode ser anexado pela assessoria; a peça nunca é apagada. + +## Direção no codebase (hipótese) + +- **Áreas prováveis:** resolução do link `src/utilities/content/contentPieceLink.ts`; job `src/utilities/content/contentPieceJob.ts`; parse `src/lib/contentPiece.ts`; feed `src/utilities/socialFeed/instagramFeed.ts`; action `src/app/(campaign)/campanha/actions/contentPieces.ts`; lista/ficha em `src/components/campaign/content/` e `.../comunicacao/conteudos/[id]/page.tsx`. +- **Fatos verificados (a revalidar):** hoje degradam para peça-link sem erro nem motivo — origem ≠ Instagram, parse falho, credencial ausente, `loadInstagramFeed` lançando, post fora da janela de 50, carrossel/sem `mediaUrl`; o job termina "Pronto" (`contentPieceJob.ts:278`). O parse rejeita caminho prefixado pelo perfil (`src/lib/contentPiece.ts:352-407`). Não há paginação no repo (`INSTAGRAM_MAX_RESULTS_CAP=50`). Falha depois de um match/download já vira "Falhou" com mensagem. +- **Precedente a olhar:** `docs/plans/central-conteudos-varredura-instagram.md` (C212 §Q1/Q2/Q4 — limites e regra de terceiro) e `downloadSource` (`src/utilities/speech/speechMediaPipeline.ts`) como download remoto→mídia. +- **Risco de acoplamento:** não reusar o caminho do sync do board (lock transacional do hook, snapshot, kill switch, cache de 5 min); o `sourceUrl` canônico é a identidade (não criar peça gêmea); `curatedFields` da assessoria não podem ser sobrescritos; nada de import que feche ciclo. + +## Dependências + +- **Dura: C211 (#1254)** — o fluxo de link, a ficha e o pipeline existem; este item corrige o comportamento (defeito). +- **Soft: C212 (#1256, entregue)** — os achados (janela de 50 sem paginação, `media_url`, regra de terceiro) são a base da decisão. +- Credencial do Instagram já governada pelo `SocialFeedSettings` (admin-only) — a ausência dela vira motivo honesto, não tela nova. + +## Fora de escopo + +- Varredura agendada do perfil (webhook + reconciliação + cursor próprio) — recomendação do C212 §Q4; vira item próprio se produto quiser. +- oEmbed/embed de terceiro (C211-FOLLOWUP-OEMBED, #1263) e download/persistência de mídia de terceiro (permanente). +- Backfill/reprocessamento em massa de peças-link antigas — item próprio, se produto quiser; "anexar arquivo" segue como caminho. +- Montar carrossel/álbum a partir dos filhos; redesenhar feed/board da home; nova tela ou novo estado de sync. + +## Rabbit holes de produto + +- **"Já que vai paginar, varre o perfil inteiro".** Se alguém "só completar": webhook, agendador, cursor e painel de status. **Corte neste item:** só o link colado é procurado; a varredura é outro item (C212 §Q4). +- **"A API não achou → scraping/yt-dlp".** Se alguém "só completar": crawler e download de terceiro. **Corte:** nunca; o resultado é motivo honesto + anexar arquivo. +- **"Carrossel vira álbum".** Se alguém "só completar": baixar cada filho, montar álbum, inventar capa. **Corte:** carrossel fica peça-link com motivo. +- **"Reprocessar todo o acervo".** Se alguém "só completar": job em massa sobre peças-link antigas. **Corte:** o fix vale para colagens novas; o resto é item próprio. +- **"Consertar o token/tela de config".** Se alguém "só completar": novo painel de credencial. **Corte:** `SocialFeedSettings` já é o dono; falta de credencial é motivo na ficha. + +## Questões em aberto (produto) + +- **Até onde a busca pelo post deve ir para trás?** **Opções:** A) paginação limitada (tudo dentro de uma janela declarada) | B) só as N mais recentes | C) só a janela atual (50). **Recomendação:** A, com motivo honesto quando o post estiver além da janela. _(assumido — validar com produto)_ +- **O que o operador vê quando a extração falha?** **Opções:** A) motivo só na ficha | B) motivo na ficha + selo na lista. **Recomendação:** A — a lista mantém o estado atual (evita ruído novo); o detalhe é onde a decisão acontece. _(assumido — validar com produto)_ +- **Aceitar também links prefixados pelo perfil e outras grafias?** **Opções:** A) sim, as grafias que o copiar-e-colar do browser produz | B) só a forma canônica atual. **Recomendação:** A — nunca aceitar stories/terceiros; o que muda é só a grafia do próprio post. _(assumido — validar com produto)_ + +## Referências + +- GitHub Issue — a registrar com `pnpm agent:register`. +- Design UI (gate): `docs/plans/central-conteudos-link-instagram-ui-design.html` (+ assets em `central-conteudos-link-instagram-ui-design-assets/`) +- Planos irmãos: `docs/plans/central-conteudos-ingestao.md` (C211) · `docs/plans/central-conteudos-varredura-instagram.md` (C212) +- Arquivos-pista: `src/utilities/content/contentPieceLink.ts` · `src/utilities/content/contentPieceJob.ts` · `src/lib/contentPiece.ts` · `src/utilities/socialFeed/instagramFeed.ts` · `src/app/(campaign)/campanha/actions/contentPieces.ts` · `src/components/campaign/content/AddContentPieceLinkDialog.tsx` · `src/components/campaign/content/ContentPieceCardList.tsx` · `src/app/(campaign)/campanha/(app)/comunicacao/conteudos/[id]/page.tsx` +- `AGENTS.md` — guardrails de campanha (sem scraping, sem credencial em log) e convenções de UI/nav + +## Self-score (shaping) + +1. Fatia = um outcome verificável? **Sim** — link do próprio perfil deixa de degradar em silêncio (baixa e cataloga, ou explica). +2. Appetite declarado e a intenção cabe? **Sim** (~1,5–2 dias; varredura, backfill e scraping cortados). +3. Persona + job + aceite claros sem jargão de stack? **Sim**. +4. Direção no codebase é hipótese? **Sim** — áreas e fatos como pista, sem contrato técnico. +5. Zero decisões duras de engenharia no plano? **Sim** — paginação, armazenamento do motivo e shape ficam no plano de implementação. + +**Score: 5/5.** diff --git a/docs/plans/central-conteudos-secao-home-ui-design.html b/docs/plans/central-conteudos-secao-home-ui-design.html new file mode 100644 index 00000000..a5e351f2 --- /dev/null +++ b/docs/plans/central-conteudos-secao-home-ui-design.html @@ -0,0 +1,88 @@ + + + + + + + Design — S36 · Central local na home + + + +
+
+ S36 · revisão do gate +

A peça do lugar da pessoa vem primeiro.

+

Até três peças: município → região → recentes. Sem localização, a seção simplesmente mostra recentes — sem erro, prompt surpresa ou espera eterna.

+
+ +
+
CENA 01

Localizada · desktop 1280 · município, região e complemento recente

+
+

Faça parte

Mostre que você está com Solla

SEÇÃO EXISTENTE · CARDS PERSONALIZÁVEIS

+
+

Central de Conteúdos

Peça voto pra Solla 1313

Comece pelo material do seu território e mande para quem você conhece.

⌖ Para seu municípioLocalização usada só nesta visita
+
+
NEEDS ASSET · FOTO REAL
FotoDo seu município

Título da peça local

Seu município · Tema

Ver esta peça →
+
NEEDS ASSET · POSTER REAL▶Tocar para carregar
VídeoDa sua região

Título da peça regional

Sua região · sem autoplay

Ver esta peça →
+
NEEDS ASSET · CAPA REAL▶
ÁudioMais recente

Mensagem recente para compartilhar

Completa a seleção local

Ver esta peça →
+
+
Ver todas as peças →

Nenhum card personalizável entra nesta amostra.

+
+

Apoie e acompanhe

Receba as novidades da campanha

+
+
+ +
+
CENA 02

Localizada · mobile 390 · recorte discreto, sem pedir GPS ao carregar

+

Faça parte

Mostre que você está com Solla

+

Central de Conteúdos

Peça voto pra
Solla 1313

Material do seu território para compartilhar.

⌖ Para seu município
+
NEEDS ASSET
FOTO REAL
Do seu município

Título da peça local

Ver peça →
NEEDS ASSET
POSTER REAL
▶
Da sua região

Título da peça regional

Só carrega no toque

Ver peça →
+ Ver todas as peças →

A localização não é guardada. Cards personalizáveis ficam na seção anterior.

+

Apoie e acompanhe

Receba as novidades

+
+
+ +
+
CENA 03

Sem localização ou fora da Bahia · recentes, sem erro e sem insistência

+
+

Central de Conteúdos

Peça voto pra Solla 1313

Veja as peças mais recentes e escolha uma para compartilhar.

Seleção recente
NEEDS ASSET · PREVIEW REAL
Foto

Peça recente

NEEDS ASSET · PREVIEW REAL
Vídeo

Outra peça recente

NEEDS ASSET · PREVIEW REAL
Áudio

Mensagem recente

Ver todas as peças →

Opcional e secundário. A seção já funciona sem isso.

+

Central de Conteúdos

Peça voto pra
Solla 1313

Veja as peças mais recentes.

Seleção recente
NEEDS ASSET · PREVIEW REAL
Foto

Título da peça recente

Ver peça →
Ver todas as peças →

Opcional. Sem prompt no carregamento.

+
+
+ +
+
CENA 04

Resolução da localização · transitória, não bloqueia e termina em recentes

+
+
INSTANTE INICIAL

Peça voto pra Solla 1313

A home já está utilizável. Só esta amostra define a melhor seleção.

Sem modal, sem overlay e sem prompt automático.

+
LOCALIZAÇÃO ACESSÍVEL

Seleção do seu território

GPS já acessível; senão, recorte aproximado por IP. A interface entrega o mesmo resultado: município → região → recentes.

Do seu municípioDa sua região

Nada é guardado, registrado ou usado fora desta seção.

+
SEM SINAL ÚTIL

Seleção recente

A espera termina e as peças recentes aparecem. Nenhum erro é mostrado.

Preview recente disponível

Nunca há spinner eterno.

+
+
+ +
+
CENA 05

Uma peça publicada · sem lacunas, independentemente da localização

+

Central de Conteúdos

Peça voto pra Solla 1313

Uma peça oficial já está pronta para você compartilhar.

Ver todas as peças →
+

Central de Conteúdos

Peça voto pra
Solla 1313

Uma peça oficial já está pronta.

NEEDS ASSET · PREVIEW REAL
Foto

Título da única peça publicada

Ver peça →
Ver todas as peças →
+
+ +
+
CENA 06

Zero peças · seção inteira ausente (fail-closed)

+

Faça parte

Mostre que você está com Solla

A SEÇÃO DA CENTRAL NÃO É RENDERIZADA · SEM LOCALIZAÇÃO, VAZIO OU CTA

Apoie e acompanhe

Receba as novidades da campanha

+

Faça parte

Mostre que você está com Solla

CENTRAL AUSENTE

Apoie e acompanhe

Receba as novidades

+
+
+ + diff --git a/docs/plans/central-conteudos-secao-home.md b/docs/plans/central-conteudos-secao-home.md new file mode 100644 index 00000000..0b1ba197 --- /dev/null +++ b/docs/plans/central-conteudos-secao-home.md @@ -0,0 +1,121 @@ +# S36 — Home — seção divulgando a Central de Conteúdos + +Status: rascunho +Atualizado em: 2026-09-23 +Issue: #1305 +Priority: P1 +Impeccable: C — seção nova na home pública (superfície nova dentro de página existente) +Design UI: docs/plans/central-conteudos-secao-home-ui-design.html +Appetite: ~2–3 dias eng; um outcome verificável (a home leva à Central com peças do território do visitante; a seção some quando não há peça publicada) +Responsável: — + +## Intenção + +A Central de Conteúdos (`/conteudos`, S27) está no ar com as peças "Peça voto pra Solla 1313", mas quem chega na home — o lugar mais visitado do site — só a descobre pelo link condicional do rodapé e pelo selo local da própria peça. Na reta final até 04/10, a home precisa empurrar o eleitor para a Central: uma seção curta que mostre peças do **território do visitante** (para ele se reconhecer e repassar) e o leve para lá. A localização é resolvida pelo próprio visitante — GPS quando acessível, senão IP —, sem guardar nada. + +Esta seção **supersede a decisão D7 do S27** ("Descoberta (rodapé + selo; sem seção nova)", `docs/plans/central-conteudos-publica-impl.md:87-91`), que rejeitou a seção nova na home por estar fora do escopo daquele item. A reabertura é decisão de produto do dono (pedido do operador); o rodapé e o selo local do S27 permanecem como estão — este item só acrescenta a seção. + +## Persona e fluxo + +- **Persona / contexto:** eleitor/simpatizante que abre jorgesolla1313.com.br no celular (link no WhatsApp, busca, indicação) e quer ajudar, mas não sabe onde pegar material nem o que escrever; o que o convence é ver o material do lugar dele. +- **Job principal:** descobrir que existe uma Central de peças oficiais de voto, reconhecer o material do seu território e chegar nela em um toque. +- **Fluxo desejado:** rola a home → a seção resolve a localização (GPS se acessível, senão IP; sem localização, segue) → vê até 3 peças publicadas do seu município (completando com a região e, se faltar, recentes) → toca numa peça ou no CTA "Ver todas as peças" → cai em `/conteudos` → baixa/compartilha dali (fluxo do S27). +- **Anti-goals de produto:** não é uma segunda Central nem catálogo paralelo (quem cataloga é o interno, C211); não duplica a seção S3 "Acompanhe de perto" (feed de redes/artigos) nem a seção de cards logo acima — **cards personalizáveis nunca são amostra**; não captura dado, não pede login, não guarda/loga a localização e não adiciona rastreio (analytics é C213); não re-hospeda mídia; não autoplaya áudio/vídeo; não redesenha a home. + +### Esboço de fluxo (C) + +```text +[visitante na home] → a seção resolve a localização + (GPS se acessível · senão IP no servidor · senão desconhecida — nunca guarda nem loga) +→ até 3 peças publicadas do município do visitante + (sem peça local: completa com a região; ainda faltando: recentes; sem localização: recentes) +→ nunca cards personalizáveis como amostra (a seção anterior da home já os mostra) +→ toca numa peça (mídia só no toque) ou no CTA "Ver todas as peças" → /conteudos +[zero peças publicadas] → a seção inteira some (fail-closed) +[localização indisponível/fora da Bahia] → recentes, sem erro e sem prompt insistente +``` + +### Design UI (C) + +- Design UI (gate): `docs/plans/central-conteudos-secao-home-ui-design.html` — cenas mobile/desktop da seção na home: peças do território, fallback sem localização, uma peça só, zero peças (seção ausente) e o estado de resolução da localização (sem spinner eterno). Revisão do gate: a primeira versão não tinha seleção por localização nem excluía os cards. + +## Objetivo e aceite + +- A home pública ganha uma seção dedicada à Central, visível só quando há peça publicada: sem peça, a seção não existe na página (fail-closed a zero, mesma condição do link do rodapé hoje). +- **Amostra por território do visitante:** a seção mostra até 3 peças publicadas do município do visitante; se não houver peças locais suficientes, completa com a região e, ainda faltando, com as mais recentes; sem localização ou fora da Bahia, mostra as mais recentes. +- **Localização sem rastro:** GPS só quando acessível (permissão já concedida ou affordance explícita — ver questão (a)); senão IP resolvido no servidor; **nunca persistir, logar ou setar cookie** com a localização ou o IP; nada de PII. +- **Cards personalizáveis nunca são amostra:** a seção anterior da home (`CampaignCardsSection`) já os mostra; peças publicadas de qualquer tipo (inclusive tipo card de arquivo) podem ser amostra. +- A seção leva à Central: CTA principal para `/conteudos` e prévia leve das peças (foto) ou só chamada de play (vídeo/áudio) — nada carrega sozinho. +- Kill switch instantâneo: despublicar uma peça reflete na seção sem deploy (mesmo contrato de cache/tag do catálogo, `contentPieces`). +- Sem autoplay, sem mídia pesada na abertura da home (contrato do S27); seção distinta do S3 e da seção de cards; sem rastreio novo; demais seções da home intocadas. +- **A seção é por visitante** (localização): não pode ser servida no mesmo HTML estático compartilhado do resto da home — o executor decide o mecanismo (resolver no cliente após a localização, ou render no servidor por IP), mantendo o resto da home como está. +- Celular primeiro: sem overflow horizontal (o e2e da home mede), usável em conexão ruim; nenhuma espera bloqueia o resto da home (a seção pode aparecer depois). + +## Dados (intenção) + +- **Dados: N/A** — a seção é superfície de descoberta; nenhum número, contador ou ranking. **Decisões desbloqueadas:** o visitante decide entrar na Central (e o que pegar lá); a comunicação decide o que publicar/despublicar. Nenhum dado do visitante é coletado ou guardado. + +## Dados da decisão (literais) + +- Item `S36`; slug `central-conteudos-secao-home`; tipo `feature`; Priority `P1`; Impeccable `C`. +- Condição da seção: **sem peça publicada → a seção inteira não aparece** (mesma condição do link "Conteúdos" no rodapé, hoje via `hasPublishedContentPieces`). +- CTA principal: `Ver todas as peças` → `/conteudos`. +- Conteúdo: **até 3 peças publicadas**, na ordem de seleção **município do visitante → região → mais recentes**; sem localização/fora da Bahia → mais recentes. +- Exclusão literal: **cards personalizáveis (os itens sintéticos dos 6 modelos) nunca entram como amostra** — a seção logo acima (`CampaignCardsSection`) já os mostra. +- Localização: GPS só se acessível (permissão já concedida ou affordance explícita); senão IP no servidor; **proibido persistir/logar/cookiar** localização ou IP; fora da Bahia ou indisponível → recentes. +- Sinal de IP: a viabilidade de resolver **município** pelo IP no deploy (headers do túnel Cloudflare e/ou fonte de geo-IP) é **a confirmar na implementação** — nunca estimada; se só resolver país/estado, a seleção degrada para região/recentes. +- Convenção das seções irmãs da home: `data-home-section` — valores existentes `hero`, `proof`, `contents`, `problem`, `flags`, `story`, `sound`, `cards`, `newsletter`; a seção nova segue a convenção (valor definido no plano de implementação). +- Cache/kill switch: mesma tag de listagem do catálogo (`contentPieces`), revalidada no publish/unpublish; a seleção por localização não entra no cache compartilhado. +- **Supersessão:** D7 do S27 (`docs/plans/central-conteudos-publica-impl.md:87-91`), opção A (rodapé + selo; sem seção nova), rejeitava a opção B (seção nova na home). Este item reabre e adota a seção nova; rodapé e selo local do S27 permanecem. +- Escopo do S27 intocado: filtros, busca, páginas de peça, share e mensagens de voto continuam como entregues. + +## Direção no codebase (hipótese) + +- **Áreas prováveis:** a home compõe seções hardcoded em `src/app/(frontend)/(home)/page.tsx:127-251`; a seção nova é um componente no molde de `JingleHomeSection` (`data-home-section="sound"`, "Ver todos" → `/jingles`) e `CampaignCardsSection` (`data-home-section="cards"`); a seleção local usa as facetas já existentes da peça (município/região, `src/lib/contentPieceCatalog.ts`) sobre a leitura pública cacheada (`src/utilities/content/contentPieceReads.ts`). +- **Precedentes de localização a olhar:** `src/lib/municipalityProximity.ts` (ponto → município/ZE, fora da Bahia, mais próximo — puro e testado), `src/utilities/campaignGeolocation.ts` e `src/components/campaign/shared/useNearestMunicipalitySlug.ts` / `NearestMunicipalityCard.tsx` (B14, geolocalização no dashboard staff — atenção: lá resolve só entre os municípios do portfólio; aqui o universo é o catálogo inteiro), e a extração de IP do túnel em `src/utilities/content/contentEventRateLimit.ts:33-37` / `src/utilities/ai/themeSearchGuard.ts:22` (`cf-connecting-ip` → `x-forwarded-for` → `x-real-ip`). +- **Descoberta hoje:** link condicional no rodapé (`CampaignFooter.tsx:34-37,65-67`) + selo local (`ContentPiecePageHeader.tsx:31-33`); `SiteHeader.tsx` não tem link. +- **Risco de acoplamento:** a home é estática/cacheada — a seção por visitante não pode contaminar o cache compartilhado nem virar leitura crua pesada; não editar as seções irmãs, `/conteudos` nem o rodapé; o e2e da home mede overflow horizontal; não acoplar ao #44 PUB2 (editabilidade da home é issue separada). + +## Dependências + +- **C211** (peças catalogadas e publicadas) — dura, indireta: sem peça publicada a seção some (fail-closed). +- S27 (`/conteudos` no ar) — dura: o CTA precisa do destino. +- B14 (mecânica de geolocalização/proximidade) — soft: precedente a reusar, não dependência de entrega. +- Design hi-fi aprovado no gate. + +## Fora de escopo + +- Cards personalizáveis como amostra (a seção anterior os mostra) e mudanças na `CampaignCardsSection`. +- Guardar/logar/cookiar a localização ou o IP; analytics/UTM (C213); login/captura/PII; novo Consent. +- Editabilidade/toggles/ordem das seções da home (#44 PUB2); mudar o rodapé, o selo local, o `SiteHeader` ou a própria `/conteudos`. +- Redesign de qualquer outra seção da home (S3 incluída) e personalização do resto da home por localização. + +## Rabbit holes de produto + +- **"Já que tem localização, personaliza a home inteira".** Se alguém "só completar": hero, cards e notícias por cidade. **Corte neste item:** só a seção da Central usa a localização; o resto da home fica como está. +- **"Guarda a cidade para a próxima visita".** Se alguém "só completar": cookie/localStorage de localização, perfil de visitante. **Corte:** nada é persistido — a resolução vale para a visita e morre nela. +- **"Pede o GPS de novo a cada visita".** Se alguém "só completar": prompt repetido no carregamento, spinner eterno. **Corte:** GPS só quando acessível (ou affordance); indisponível → IP/recentes, sem insistir. +- **"A seção vira uma mini-Central".** Se alguém "só completar": filtros, busca e ações de baixar/compartilhar na home. **Corte:** a seção só apresenta e leva; quem faz tudo é `/conteudos`. +- **"Publicar para não sumir".** Se alguém "só completar": hardcode de peças para a seção nunca ficar vazia. **Corte:** fail-closed a zero é regra (kill switch); o código não publica conteúdo. +- **"Tocar sozinho".** Se alguém "só completar": autoplay/preview animado para engajar. **Corte:** mídia só no toque, como no S27. + +## Questões em aberto (produto) + +- **Como obter o GPS?** **Opções:** A) prompt do navegador ao carregar a home | B) sem prompt: usa GPS só quando a permissão já estiver concedida (ou por uma affordance explícita na seção), senão IP. **Recomendação:** B — o prompt surpresa no carregamento queima confiança e a maioria nega; o IP já dá o recorte territorial na primeira visita. _(assumido — validar com produto)_ +- **Amostra local estrita ou completada?** **Opções:** A) só do município (pode mostrar menos de 3) | B) município → região → recentes | C) só recentes com selo local. **Recomendação:** B — a seção não fica vazia nem parece genérica. _(assumido — validar com produto)_ +- **Posição na home?** **Opções:** A) depois de `CampaignCardsSection`, antes da newsletter | B) junto de `CampaignContentSection` (S3). **Recomendação:** A — fecha a página com CTA de compartilhamento, mantendo cards + newsletter como bloco final de conversão. _(assumido — validar com produto)_ +- **Copy/CTA literais?** **Opções:** A) título na voz da Central ("Peça voto pra Solla 1313") + CTA `Ver todas as peças` | B) copy neutra ("Conheça a Central de Conteúdos") | C) outra. **Recomendação:** A — mesma voz do S27; copy final validada no gate/design. _(assumido — validar com produto)_ + +## Referências + +- GitHub Issue: a registrar para o S36 (`pnpm agent:register`). +- Design UI (gate): `docs/plans/central-conteudos-secao-home-ui-design.html`. +- `docs/plans/central-conteudos-publica.md` (S27) e `central-conteudos-publica-impl.md` (D7 superseded); `central-conteudos-publica-ui-design.html`. +- `src/app/(frontend)/(home)/page.tsx`, `src/components/jingles/JingleHomeSection.tsx`, `src/app/(frontend)/(home)/CampaignCardsSection.tsx`, `src/utilities/content/contentPieceReads.ts`, `src/components/CampaignFooter.tsx`, `src/components/CampaignContentSection.tsx` +- Localização: `src/lib/municipalityProximity.ts`, `src/utilities/campaignGeolocation.ts`, `src/components/campaign/shared/useNearestMunicipalitySlug.ts`, `src/utilities/content/contentEventRateLimit.ts`, `src/utilities/ai/themeSearchGuard.ts` +- `tests/e2e/frontend.e2e.spec.ts` e `scripts/lib/e2e-affected-manifest.mjs` (manifesto de e2e afetado pela home). +- `AGENTS-public.md` — convenções do site público (cache, kill switch, mídia). + +## Self-score (shaping) + +4,6/5 — (1) fatia = um outcome verificável (a home leva à Central com peças do território; a seção some sem peça); (2) appetite ~2–3 dias cabe (seção + resolução de localização + seleção, com o resto da home intocado); (3) persona/job/aceite em linguagem de produto; (4) direção no codebase é hipótese (precedentes citados como pista); (5) zero decisão dura de engenharia — o mecanismo de resolução fica no plano de implementação e a viabilidade do sinal de IP está marcada "a confirmar".