Inicio rápido
De un proyecto vacío a una capa de comentarios funcionando, y de ahí a tu propio backend.
Instala
npm install helldotsMonta la capa
Llámalo una vez, desde el navegador, tan pronto como quieras — pospone su propio trabajo con el DOM hasta que el documento esté listo.
import { createCommentOverlay } from 'helldots';
createCommentOverlay({
user: { name: 'Ana' },
persistence: 'localStorage',
});Deja un comentario
Aparece una barra de herramientas al pie de la página.
- Alt+C (Opción+C en macOS) activa el modo comentario.
- Haz clic donde sea para anclar un comentario a ese elemento.
- Arrastra para seleccionar una región y adjuntar un recorte a resolución completa.
- La bandeja de la barra lista todos los comentarios, los filtra y muestra el panel de métricas.
Eso es todo. Los comentarios sobreviven a una recarga, se vuelven a anclar cuando la página cambia, y se quedan en el navegador de quien visita.
Pruébalo aquí
Este sitio ejecuta exactamente eso. Abre el Playground y maneja el widget a través de su API pública.
Conectarlo a tu propio backend
persistence: "localStorage" es una comodidad, no el diseño. Quítalo y
suscríbete en su lugar — cada comentario es JSON plano.
import { createCommentOverlay } from 'helldots';
const overlay = createCommentOverlay({
user: { name: currentUser.name, id: currentUser.id },
onCommentCreated: (comment) => api.post('/comments', comment),
onReplyAdded: (comment, reply) => api.post(`/comments/${comment.id}/replies`, reply),
onCommentStatusChanged: (comment) => api.patch(`/comments/${comment.id}`, comment),
onCommentUpdated: (comment) => api.patch(`/comments/${comment.id}`, comment),
onCommentDeleted: (id) => api.delete(`/comments/${id}`),
// El sitio seguro para cargar: el widget ya montó y las cuentas son reales.
onReady: async (o) => {
const { orphaned } = o.loadComments(await api.get('/comments'));
if (orphaned) console.info(`${orphaned} comentarios perdieron su elemento`);
},
});Diez callbacks separados es una forma. La otra es un solo flujo, que suele ser lo que quieres cuando todo va a un único endpoint:
createCommentOverlay({
onChange: (event) => api.post('/helldots-events', event),
});ChangeEvent es una unión discriminada — haz switch sobre event.type y
TypeScript estrecha el payload por ti. Ambas vías llevan los mismos eventos en
los mismos momentos; suscríbete a una, a la otra, o a las dos.
Carga desde onReady
loadComments() se puede llamar en cualquier momento — si se llama antes de
que el widget haya montado, los datos se retienen y se aplican al montar. Pero
las cuentas que devuelve vuelven a cero, porque todavía no se ha resuelto nada
contra el DOM. Usa onReady cuando esos números importen.
Un componente de React
import { useEffect } from 'react';
import { createCommentOverlay } from 'helldots';
export function Comments({ user }) {
useEffect(() => {
const overlay = createCommentOverlay({ user, persistence: 'localStorage' });
return () => overlay.cleanup();
}, [user]);
return null;
}cleanup() elimina el widget por completo, que es lo que hace esto seguro bajo
el doble montaje de React en desarrollo. Para un router del lado del cliente
además necesitas notifyNavigation() — mira
frameworks.
Siguientes pasos
Persistencia
localStorage, tu propio almacén, y cómo reconciliar los dos.
Frameworks
Next.js, Vue, Astro, SPAs y una etiqueta script simple.
Capturas
Qué es de verdad una captura aquí, y las cuatro palancas sobre su coste.
Identidad y permisos
A quién se atribuye un comentario, y quién puede editarlo o borrarlo.