Skip to content

Releases

SyncPad v1.0.0

Choose a tag to compare

@Cosmichomeless Cosmichomeless released this 07 Oct 06:59
1bd36eb

Notas colaborativas que se editan entre varias personas y siguen funcionando sin conexión, sobre un CRDT (Yjs).

Demo: https://syncpad-0xyk.onrender.com (Render + Neon, plan gratuito; se duerme a los 15 minutos sin tráfico y la primera visita puede tardar cerca de un minuto).

Qué incluye

  • Edición simultánea de una nota con presencia y cursores.
  • Modo sin conexión: cada cambio se guarda en IndexedDB y se sincroniza al reconectar, con el estado «Pendiente» / «Guardado».
  • Convergencia por Yjs: las ramas divergentes se fusionan sin elegir un ganador; deshacer solo afecta a las ediciones propias.
  • Cuentas, workspaces e invitaciones con permisos comprobados en el servidor, también en conexiones WebSocket abiertas.
  • Texto con formato acotado (negrita, enlaces y listas); el servidor rechaza cualquier otra marca.
  • Registro de updates con ack y snapshots en PostgreSQL; copias con scripts/backup.sh y restore.sh.
  • Pila completa con docker compose up --build y una imagen de un solo origen (deploy/Dockerfile) para el despliegue.

Caso reproducible: un conflicto resuelto

Dos réplicas parten de «el perro corre», se quedan sin conexión y reemplazan la misma palabra: Ana escribe «lobo» y Luis «loro». Al reconectar no gana ninguna: las dos ven el mismo texto y se conservan ambas versiones.

cd backend && npx tsx ../scripts/conflict-demo.mts
Con conexión, las dos réplicas tienen: "el perro corre"
Sin conexión, Ana ve:  "el lobo corre"
Sin conexión, Luis ve: "el loro corre"
Tras reconectar, ambas ven: "el loboloro corre"
OK: convergen al mismo texto y se conservan las dos versiones (sin «último gana»).

El script no necesita servidor ni base de datos: usa el mismo documento y el mismo diff de reconexión que el cliente. El mismo caso con ventanas reales está en el paso 6 del guion de demo, y las reglas con sus límites en #38. Yjs garantiza convergencia, no sentido: decidir cuál de las dos palabras queda sería una decisión de producto, y hoy no hay marcas de conflicto.

Verificación

  • 146 pruebas en el backend, 36 en shared/, 161 en el frontend y 2 del entrypoint compilado.
  • 18 pruebas de integración con PostgreSQL y WebSocket.
  • 17 pruebas Playwright con tres clientes y reinicio del servidor. No se ejecutan en CI.
  • Humo público sobre la URL real: 10 de 10 el 2026-10-07 (scripts/smoke-public.mts).
  • CI: frontend.yml y backend.yml, incluida la imagen de despliegue arrancada sin capabilities, como en Render.

Limitaciones conocidas

  • Una sola instancia del servidor: las salas viven en memoria; no hay escalado horizontal.
  • Con 5 y 10 editores simultáneos se supera el presupuesto de latencia de 250 ms (medido con almacén en memoria, no contra PostgreSQL desplegado).
  • Copia local sin cifrar y sin compactación; sin CSP ni cabeceras de seguridad más allá de las del proxy.
  • Accesibilidad revisada con el árbol de Playwright, no con lector de pantalla.
  • El arranque en frío tras dormirse y las cuotas de RAM y CPU del plan gratuito no se han medido.
  • Las capturas del README salen de datos sembrados en local, no de la instancia pública.
  • Es un despliegue de exposición: los datos de la demo no son privados ni se garantizan.