De Notipad Editor a Notipad Publish: cómo un producto empieza a convertirse en plataforma

Hay un momento en el desarrollo de un producto en el que la pregunta deja de ser "qué pantalla falta" y pasa a ser otra:

qué capacidad de este producto debería existir fuera del producto.

En mi caso, esa pregunta apareció construyendo Notipad Editor.

La idea inicial era concreta: un editor Markdown local-first para escribir documentación técnica con una experiencia rica. Markdown portable, Git, diagramas, fórmulas, tablas, alertas, columnas, bloques de código, outline y un visor que no pareciera una previsualización de segunda categoría.

El objetivo no era inventar otro editor de texto. Era resolver un problema más específico: que la documentación técnica pudiera vivir en archivos normales, versionarse como código y aun así tener una experiencia visual lo bastante buena como para publicarse.

Ahí apareció la siguiente pregunta:

Important

Si un documento se ve bien dentro del editor, ¿por qué no debería poder publicarse con la misma fidelidad?

Esa pregunta es el origen de Notipad Publish.

Publicar Markdown no era el problema

Publicar Markdown es fácil.

Lo difícil es publicar el mismo documento que ve el usuario dentro del editor:

  • con las mismas tablas enriquecidas;
  • con las mismas alertas;
  • con los mismos bloques de código;
  • con diagramas y fórmulas;
  • con el mismo outline;
  • con la misma localización;
  • con los mismos estilos de lectura;
  • sin duplicar la lógica en cada frontend.

La trampa habitual es construir una web de publicación y volver a implementar el render allí.

Eso funciona al principio. Después aparecen variaciones:

Superficie Qué quiere hacer Riesgo si renderiza por su cuenta
Notipad Editor Autoría local-first El preview se convierte en la única versión fiel
Web pública del producto Mostrar contenido público El reader deriva respecto al editor
Nikki Asteinza web Dogfooding real con contenido propio El portfolio se vuelve un cuarto renderer
Notipad Publish Publicar sitios estáticos El sitio publicado no se parece al editor

El problema real no era convertir Markdown a HTML. Era mantener una promesa:

Bloque de codigo - text
un mismo documento debe verse y comportarse igual en todos los consumidores

La señal de arquitectura

La señal apareció cuando el renderer dejó de ser "código del editor" y empezó a comportarse como una capacidad independiente.

Un renderer enriquecido tiene entrada, salida y contrato propios:

Bloque de codigo - text
Markdown + dependencias + opciones
        ↓
HTML seguro + decoradores + bloques rich

Ese contrato no pertenece necesariamente a una ventana de Electron. Tampoco pertenece a una web pública concreta. Pertenece a la plataforma.

Por eso la primera extracción importante fue un núcleo de render compartido.

El core asume las partes que deben ser comunes:

  • parseo de Markdown;
  • limpieza de frontmatter;
  • sanitización;
  • IDs estables de headings;
  • decoradores de alertas, columnas y tablas;
  • estructuras rich para lectura;
  • soporte de diagramas, fórmulas y código;
  • API común para consumidores con DOM real o controlado.

El editor sigue siendo el producto de autoría. Pero el render deja de estar encerrado dentro del editor.

De librería a servicio

Una vez existe el core, aparece la siguiente frontera: usarlo también en backend.

Ahí entra un servicio de render server-side.

El servicio no reescribe el render. Lo consume.

La diferencia es que lo ejecuta en servidor, con un DOM controlado, para devolver HTML ya decorado. Esto importa porque algunas partes del render no son sólo string processing: necesitan estructura de documento para envolver tablas, bloques, columnas, alertas y código igual que el reader.

flowchart LR editor["Notipad Editor<br/>autoría local"] --> core["Núcleo de render<br/>contrato común"] web["Web pública del producto<br/>reader público"] --> core portfolio["Nikki Asteinza web<br/>dogfood real"] --> core core --> renderService["Servicio de render<br/>HTML server-side"] renderService --> publish["Notipad Publish<br/>bundle estático"]

La separación queda así:

Pieza Responsabilidad
Notipad Editor Escribir, revisar y versionar documentos
Núcleo de render Entender Markdown enriquecido y decorarlo
Servicio de render Ejecutar el render en servidor
Servicio de publicación Crear sitios, rutas, locales, assets y despliegues
Web pública del producto Marcar la referencia visual pública

Cada capa hace menos, pero lo hace mejor.

Publish no debe inventar otro producto visual

Una conclusión importante: compartir lógica no basta.

Si el HTML publicado es correcto pero el look and feel cambia, el usuario percibe que se ha roto algo. Por eso, para este desarrollo, la web pública del producto manda visualmente.

Publish reutiliza su gramática:

  • fondo con degradado;
  • header;
  • reader shell;
  • outline;
  • documento sin fondo propio;
  • botones;
  • selector de idioma;
  • comportamiento responsive.

Esto no es sólo CSS. Es parte del contrato de producto.

Note

El documento publicado no debe parecer una exportación genérica. Debe parecer una extensión natural del sistema donde fue escrito.

La localización también forma parte de Publish

Cuando aparece la publicación, aparece otra pregunta: qué pasa con los idiomas.

En el editor, el usuario piensa en contenido. En Publish, el sistema debe pensar en rutas, alternates y SEO.

Por eso Publish necesita entender variantes es y en:

Entrada Salida esperada
Página por defecto en es / o /blog/...
Variante en /en/ o /en/blog/...
Alternates hreflang="es", hreflang="en", x-default
UI selector de idioma consistente con la web del producto

La localización no puede ser un parche del frontend. Debe estar en el contrato de publicación.

Cómo una app empieza a abrir un abanico de servicios

Este es el punto más útil del proceso.

Notipad Editor empezó como una aplicación. Pero al observar sus capacidades repetibles, aparecieron piezas que podían sostener más de un producto.

Antes parecía En realidad era
Preview del editor Motor de render compartido
CSS interno Sistema visual reutilizable
Reader web Shell de lectura para documentos publicados
Export manual Capacidad de publicación
Markdown local Contenido portable para varias superficies
Sitio personal Dogfooding de Publish con riesgo controlado

La arquitectura deja de ser una app grande y empieza a ser un conjunto de primitivas:

flowchart TB product["Producto inicial<br/>Notipad Editor"] render["Render compartido"] styles["Estilos y componentes compartidos"] publish["Servicio de publicación"] web["Web pública"] portfolio["Portfolio dogfood"] future["Nuevos productos"] product --> render product --> styles render --> publish styles --> publish publish --> web publish --> portfolio render --> future styles --> future

Lo importante es que cada extracción tiene una razón concreta:

  • el render se extrae porque hay varios consumidores reales;
  • los estilos se comparten porque la paridad visual importa;
  • Publish aparece porque publicar con fidelidad ya no es un extra;
  • el portfolio sirve como prueba real antes de abrir la capacidad a clientes.

La regla práctica

La regla que estoy aplicando es esta:

Tip

Si una pieza va a ser usada por más de una superficie, no debe vivir escondida dentro de una sola app. Pero sólo debe extraerse cuando exista presión real.

Extraer antes de tiempo crea abstracciones decorativas.

Extraer demasiado tarde crea forks.

En este caso, la presión era clara:

  • el editor necesitaba render local;
  • la web del producto necesitaba reader público;
  • Nikki Asteinza web necesitaba publicar contenido propio;
  • Publish necesitaba generar páginas con la misma fidelidad;
  • el sistema necesitaba es y en;
  • los estilos tenían que ser compartidos para no romper la experiencia.

No era una abstracción prematura. Era el momento justo para pagar la deuda.

Qué aprendí de esta fase

Un producto no se convierte en plataforma porque le añades más funcionalidades.

Se convierte en plataforma cuando identificas sus capacidades repetibles, las separas con límites claros y las haces reutilizables sin perder calidad de producto.

El usuario no compra un núcleo de render.

El usuario nota si:

  • el documento se ve igual dentro y fuera del editor;
  • el sitio publicado no pierde estilos;
  • el idioma funciona;
  • los metadatos no se renderizan como contenido;
  • el header y el reader pertenecen al mismo sistema;
  • publicar no exige reescribir el documento.

La arquitectura sólo importa cuando consigue que todo eso pase de forma consistente.

Ese es el camino de Notipad ahora mismo: partir de un editor útil, extraer lo que tiene valor transversal y convertirlo poco a poco en una base de servicios reutilizables.

No construir una app cada vez más grande.

Construir una plataforma que permita lanzar más de un producto sin repetir el mismo trabajo.


Este artículo forma parte de mis notas de plataforma. Si te interesa el tema, sigue el blog o escríbeme.