Copiloto em Next.js com UI estilo Notion usando shadcn/ui para gerar ideias de keywords, títulos e artigos completos. Toda a persistência agora acontece no próprio fluxo do n8n, enquanto a autenticação é controlada via Supabase Auth (somente para proteger o acesso à interface).
- Node.js 18+
- Projeto Supabase (usado apenas para autenticação)
-
Copie o arquivo de variáveis:
cp .env.example .env.local
-
Preencha o
.env.localcom:NEXT_PUBLIC_SUPABASE_URLeNEXT_PUBLIC_SUPABASE_ANON_KEYpara habilitar o login (os valores públicos do seu projeto Supabase)NEXT_PUBLIC_ALLOWED_DOMAINpara restringir o domínio (por padrão@kodus.io)N8N_KEYWORDS_ENDPOINT,N8N_KEYWORDS_STATUS_ENDPOINT,N8N_KEYWORDS_HISTORY_ENDPOINT,N8N_TITLES_ENDPOINT,N8N_SOCIAL_ENDPOINT,N8N_POST_ENDPOINT,N8N_ARTICLES_ENDPOINTcaso precise sobrescrever os padrõesN8N_BEARER_TOKENse os webhooks exigirem autenticaçãoPOST_BRIDGE_API_URL(defaulthttps://api.post-bridge.com) ePOST_BRIDGE_API_KEYpara listar contas e agendar posts sociais direto do appCHANGELOG_API_URL(base URL ou endpoint completo) para buscar updates de changelog como ideias de social (source=changelog)CHANGELOG_REPOSITORYno formatoowner/repo(defaultkodustech/kodus-ai)CHANGELOG_LOOKBACK_DAYSpara janela de busca (1-365, default30)CHANGELOG_GITHUB_TOKENopcional, caso o repositório seja privado
-
Instale dependências e inicie:
npm install npm run dev
A interface em / já traz todo o fluxo: dois botões para gerar keywords (com ou sem ideia), multi-seleção para gerar títulos, e um bloco final para gerar e visualizar o artigo. Tudo foi construído com componentes shadcn (button, card, table, checkbox etc.) seguindo o visual minimalista do Notion.
- A página
/calendariounifica:- execuções futuras dos Scheduled Jobs,
- posts sociais agendados no Post-Bridge,
- posts já publicados no WordPress.
- A página
/kanbancentraliza o fluxo completo em colunas:Backlog→Research→SEO Ready→Drafting→Review→Scheduled→Published
- Você pode:
- criar cards manuais (ideia, keyword, título, artigo, social)
- importar ideias do
blog,changelogou ambos - mover cards entre estágios
- A persistência usa a tabela
growth_work_items. - Antes de usar, rode o SQL:
docs/growth_work_items.sql
- Você pode definir o país (Brasil ou Estados Unidos) e o idioma (pt/en) diretamente na primeira seção da UI. Os valores são enviados ao webhook como
location_code(2076 ou 2840) elanguage(ptouen).
- O POST em
N8N_KEYWORDS_ENDPOINTretorna somente o identificador da task. O front guarda esse ID e começa a checarN8N_KEYWORDS_STATUS_ENDPOINT?task_id=<id>. - Enquanto o webhook ainda processa, o endpoint de status responde
[]. Assim que termina, retorna a lista completa de keywords (cada item comkeyword,search_volume,cpc,competition, etc.). - Quando o app detecta que a lista chegou, ele apenas atualiza o UI automaticamente (sem gravar em banco). Todo o armazenamento fica a cargo do n8n. Se quiser alterar o intervalo ou timeout de polling, ajuste o efeito em
components/seo-workspace.tsx. - O botão “Explorar histórico salvo” consulta
N8N_KEYWORDS_HISTORY_ENDPOINT, permitindo reaproveitar keywords antigas (armazenadas via Supabase pelo fluxo do n8n) diretamente na etapa de geração de títulos.
- Ao solicitar um artigo, enviamos um POST para
N8N_POST_ENDPOINTcom título, keyword selecionada, opções de pesquisa e instruções customizadas. O webhook retorna apenas otaskId. - A UI passa a exibir o status da task e consulta periodicamente
N8N_ARTICLES_ENDPOINT?task_id=<id>até que o conteúdo esteja pronto. Quando o texto chega, a prévia é atualizada automaticamente. - O usuário também pode escolher categorias específicas (IDs fornecidos acima). Esses IDs são enviados na mesma requisição, permitindo que o n8n associe cada artigo a uma taxonomia no Supabase.
- A aba de Social continua gerando variações via
N8N_SOCIAL_ENDPOINT. - No bloco de conteúdo base, você pode trocar a fonte entre:
Blog posts(WordPress)Changelog (build in public)(viaCHANGELOG_API_URL->POST /api/v1/changelogemformat=json)
- Cada variação agora possui botão de agendamento:
- ao abrir o modal, o app consulta
GET /api/social/accounts, que chamaGET /v1/social-accountsno Post-Bridge; - ao confirmar, o app envia para
POST /api/social/schedule, que chamaPOST /v1/postsno Post-Bridge com:captionscheduled_at(ISO UTC)social_accounts(array de IDs numéricos)
- ao abrir o modal, o app consulta
- Após retorno com sucesso, o evento aparece no calendário via leitura dos posts
scheduledno Post-Bridge.