Skip to main content
Feedback é o único módulo aqui cujas linhas são escritas pelos seus usuários e não por você. Três superfícies ficam sobre elas, e o que cada uma pode carregar é o desenho.

O board que seus usuários veem

position aceita inline (padrão), center, bottom-right, bottom-center ou bottom-left — as mesmas cinco que a pesquisa aceita, e um vocabulário só de propósito: um produto que põe a pesquisa no canto e o quadro no centro está descrevendo um layout, não dois. Inline o quadro abre dentro do cartão, embaixo do título a que pertence. As três posições flutuantes deixam só o botão onde você o colocou, que é o que as torna úteis: um header ou um menu tem espaço para um botão e não para uma lista de ideias com um formulário embaixo. Só o center escurece a página; os cantos flutuam sobre uma página que continua legível e clicável, e o Esc fecha as três. Num app Next, importe do @userkit/nextjs — é o mesmo componente, e em modo proxy a leitura do board, o voto e a submissão são encaminhados pelos handlers, com a sessão num cookie httpOnly da sua própria origem. O board fica atrás do portão de contato verificado, por uma razão que não é a do changelog nem a da pesquisa: não é o que a resposta revela, é o que a escrita faz. Enviar coloca as palavras de um estranho numa página que você publica com o seu nome, e um voto é uma linha da qual o seu ranking de roadmap é construído — as duas são afirmações que qualquer um que saiba um external_id poderia fazer de um navegador. Sessões anônimas passam por esse portão, como passam em todo lugar, e então são recusadas pelas duas escritas com identity_required: o widget mina uma por carregamento de página, então um board que as contasse estaria contando recargas. Ler é aberto a elas, que é o que o documento público já mostra de qualquer forma. O board diz a esta pessoa em quais posts ela votou. Nunca diz o que aqueles votantes pagam. Uma pessoa pode escrever alguns pedidos por dia; além disso a API responde 429, que é “depois” e não “nunca”.

Cinco status

open, planned, in_progress, shipped, declined — e eles percorrem essa ordem, que é por que o vocabulário volta na resposta em vez de ficar cravado num cliente. Todo valor que não é open nomeia uma resposta diferente que você deu. Não existe um sexto valor significando “duplicado”: isso é merged_into_id, e mesclar é um ato e não um status.

O roadmap público

O nono documento cacheável, e o único cujas linhas foram escritas pelos seus usuários e não por você — que é por que o que ele leva é deliberadamente estreito: o título, o corpo, o status e uma contagem simples de votos. Não quem pediu, que é o seu dado sobre o seu usuário. Não a receita por trás dos votos, que nunca sai do painel. body é texto puro escrito por um dos seus usuários. Nunca renderize como markup. É a única coluna deste plano que alguém de fora da sua equipe consegue colocar numa página que você publica. Toda leitura de board é limitada a 500 posts em vez de paginada. Esse limite é uma afirmação de produto tanto quanto técnica — um board com quinhentos posts vivos tem um problema de triagem e não de paginação — e ele precisa ser um número só nas três leituras, porque o ranking é calculado sobre o conjunto que a lista devolveu.

O peso

O peso de um post é a soma do valor mensal das assinaturas ativas dos clientes distintos por trás dos seus votantes — então um time de cinco vale a receita dele uma vez, não cinco votos. Preços anuais são divididos por 12, preços avulsos nunca entram, e um trial entra quando termina. Ele existe neste endpoint e em nenhum outro lugar. Não no roadmap público, não no board do próprio contato, não num webhook. É uma query separada que só a listagem de staff faz, então uma resposta pública não consegue adquirir um peso porque alguém adicionou um campo numa projeção compartilhada. Seus usuários podem saber quantas pessoas querem algo; não podem saber o que essas pessoas pagam. A moeda é um argumento, nunca um palpite. Não há tabela de câmbio aqui, então somar unidades menores entre moedas produz um número que não é nenhuma delas — pedir a ordem por peso sem nomear uma moeda é 400 e não um padrão. E a resposta relata quantos dos clientes por trás de cada post pagam em outra moeda ou em nada, porque um peso de zero ao lado de quatro other_currency_customers diz algo completamente diferente de um peso de zero ao lado de quatro free_customers. Um número solto não diria nenhum dos dois, e uma tranquilização é exatamente o que faz alguém parar de conferir.

Mesclando duplicados

Os votos movem para o sobrevivente com ON CONFLICT DO NOTHING, então quem votou nos dois conta uma vez. merged_into_id registra para onde o post foi, e cada voto movido registra de qual post ele veio. Não existe endpoint de desfazer merge, e não precisa existir: as duas metades da proveniência ficaram, então um merge errado é reparável à mão. feedback_post.merged é entregável justamente porque muda a contagem de votos de um post que ninguém editou — um espelho do seu board que só tivesse ouvido “criado” e “status mudou” manteria o duplicado para sempre e estaria errado sobre o total no sobrevivente.

Avisando quem votou que saiu

Mire um post de changelog no post de feedback em vez de num segmento:
A audiência é um JOIN, não uma lista de destinatários copiada: quem vota depois de você publicar recebe, quem retira o voto para de receber. Como todo post direcionado, ele fica fora do documento público do changelog.

O que sai do prédio

feedback_post.created, feedback_post.status_changed, feedback_post.merged e feedback_vote.cast são todos entregáveis como webhooks. status_changed leva os dois status, para você agir sobre a transição em vez de comparar dois payloads — o barramento não é ordenado, então “o anterior” não é algo que um consumidor consiga reconstruir. Definir um status que o post já tem não anuncia nada. feedback_vote.cast leva o post e o contato e nunca o peso.

Permissões

feedback:read é de owner, admin e member — triagem é trabalho de suporte, e o assento member é o agente de suporte. feedback:write — responder, mesclar, registrar em nome de alguém — é de owner e admin. É o único lugar deste conjunto de módulos em que a leitura é separada da escrita. Changelog, checklists e pesquisas compartilham um engagement:manage, porque operar o que seus usuários veem é um ato; um board de feedback é algo que sua mesa de suporte lê o dia inteiro e raramente muda.