Tienes un problema y todavía no lo sabes: tu documentación empezó a mentir en cuanto la publicaste. Cambias un archivo, mueves una carpeta, renombras un componente — y el README, el diagrama y la wiki interna siguen describiendo la web de la semana pasada. Context Driven Development invierte el orden para que eso no pueda ocurrir: el contexto se especifica primero y manda, el código es su consecuencia, y un validador impide que ambos se contradigan.
El problema: documentación que envejece más rápido de lo que la escribes
Casi todo el software se documenta después. Primero se programa, y cuando ya funciona, alguien escribe un README o dibuja un diagrama para explicarlo. El problema es estructural: en cuanto el código vuelve a cambiar —y cambia cada día—, esa documentación deja de ser cierta y nadie la actualiza. Acabas con dos versiones de la verdad que se contradicen, y la gente (o una IA) toma decisiones leyendo la equivocada.
La causa de raíz no es pereza, es el orden. Si la documentación llega al final, siempre va por detrás. La única forma de que deje de mentir es que deje de ir al final.
La idea: el contexto manda, el código es su consecuencia
Esta web no nace en el editor de código, sino en un blueprint. Antes de que exista un solo componente, ya está escrito qué secciones habrá, cómo se relacionan y de qué piezas está hecha cada una. A esa forma de trabajar la llamo Context Driven Development: el contexto se especifica primero y el código es su consecuencia.
Es una variante aplicada de Spec-Driven Development. La diferencia: en lugar de una spec por funcionalidad que se archiva, mantengo un mapa vivo de todo el proyecto. Toda la web se sostiene sobre tres capas que hablan el mismo idioma: el Context —el blueprint que manda—, el design system —los tokens y componentes con los que se construye— y apps/web —la aplicación Next que ensambla las dos anteriores—. Lo interesante no es cada capa por separado, sino cómo se conectan.
«El código es la consecuencia del blueprint, no su origen. Si el Context y el código se contradicen, manda el Context.»
Cómo se conectan las piezas
Lo que sigue es ese sistema hecho interactivo. Cada caja es una capa real de la web y cada flecha, una relación: el Context especifica los nodos, cada nodo declara qué componentes del design system usa y dónde vive su código, y apps/web ensambla todo. Arrastra las cajas para seguir las conexiones.
Diagrama hecho con React Flow: el artículo enseñando, en vivo, cómo está conectada la web que lo muestra.
Dos conexiones merecen atención, y cada una resuelve un problema concreto. La flecha de puntos en burdeos es la sincronización bidireccional: ataca el problema del envejecimiento. Y Connections —Obsidian, Figma, las bases de datos— ataca otro: el de copiar datos que luego se quedan obsoletos. Son fuentes vivas que se consultan bajo demanda, no se copian dentro del blueprint. Veamos las dos piezas que hacen que todo esto se sostenga: qué hay dentro de un nodo, y por qué la sincronización no se rompe.
Qué hay dentro de un nodo: cinco capas
El problema de «¿dónde toco esto?» se resuelve en el nodo. Cada página vive en el Context como un nodo: una ficha cuyo frontmatter tiene cinco capas, cada una resolviendo una pregunta distinta:
- Identidad semántica — qué es este concepto y con quién se relaciona (su hiperónimo, sus hipónimos, sus hermanos). Es la capa que teje el knowledge graph.
- SEO + URL — su título, su descripción, su slug canónico, su
hreflang. Para que la encuentren las personas. - GEO — la pregunta que responde y la respuesta corta y extraíble. Para que la citen ChatGPT, Perplexity o las AI Overviews.
- Sitemap técnico — prioridad, frecuencia de cambio, idiomas.
- Implementación — y aquí está la más útil en el día a día: los hot-paths, la ruta exacta de los archivos que hacen funcionar la página, más los componentes del design system que usa.
Gracias a los hot-paths no hace falta leer todo el repositorio para tocar una sección. Abro el nodo, leo su capa de implementación y voy directo al archivo correcto. Una IA hace lo mismo: encuentra el sitio a la primera, sin perderse entre carpetas. El nodo convierte «buscar dónde está esto» en «ya sé dónde está esto».
La sincronización bidireccional no es magia: es protocolo más validador
Aquí está la pregunta honesta: si el código y el Context viven en sitios distintos, ¿qué impide que vuelvan a divergir? La respuesta no es un demonio mágico corriendo en segundo plano. Son dos cosas mucho más simples:
- Protocolo. Cuando muevo o creo código, actualizo la capa de implementación del nodo en el mismo commit. No es un paso aparte que se posponga: es parte del cambio.
- Validador. Un script (
pnpm validate:context) comprueba que cadaruta-codigoy cada componente que declara un nodo existen de verdad. Si moví un archivo y olvidé actualizar el nodo, la validación falla.
Por eso es bidireccional: el nodo te dice dónde escribir el código (Context → código), y el validador te impide mentir si el código se movió y el nodo se quedó atrás (código → Context). Ninguna dirección depende de la buena memoria. El problema del envejecimiento no se resuelve con disciplina heroica, sino haciendo que la mentira rompa el build.
¿Enlaces o vectores? Para qué sirve cada uno
Cuando explico esto, la pregunta técnica que más me hacen es: ¿el grafo de conocimiento funciona con enlaces tipo Obsidian o con vectores (embeddings)? Hoy la respuesta es clara: enlaces, no vectores. Y conviene entender por qué, porque cada herramienta resuelve un problema distinto.
Las relaciones del Context son wikilinks ([[Otro término]]) en el frontmatter, que un script resuelve en relaciones tipadas y explícitas: es-un (hiperónimo ↑), tipo-de (hipónimo ↓), relacionado (↔). Un enlace tipado dice exactamente por qué dos conceptos se tocan. Un vector solo diría que están cerca, sin el motivo.
| Enlaces tipados (lo que uso) | Vectores / embeddings | |
|---|---|---|
| Qué afirman | «X es un tipo de Y», con el porqué | «X está cerca de Y», sin el porqué |
| Fuertes en | precisión y citabilidad | descubrimiento difuso |
| En git | una línea revisable y diffeable | opaco; hay que re-embeddear |
| Mejores para | la columna vertebral del grafo | «artículos parecidos», búsqueda semántica |
La conclusión defendible es enlaces primero: son deterministas, se revisan en un pull request como cualquier línea de código, y cada relación lleva su motivo —que la propia web muestra al decirte por qué un término es cercano a otro—. Los vectores son una capa futura útil para lo que los enlaces no cubren: enlazar un concepto mencionado con palabras distintas a su nombre. No es «ambos hoy»; es enlaces para la estructura, vectores cuando haga falta recall.
El design system: una sola fuente de componentes
La segunda capa resuelve el mismo problema de fondo —que las cosas se contradigan— pero en lo visual. Sin un design system, cada página reinventa sus botones y su color, y tarde o temprano dejan de parecerse entre sí. Con él, los tokens de marca —color, tipografía, espacios— y los componentes reutilizables viven en un único lugar. apps/web no inventa botones: los toma de ahí. Así, un cambio de marca se hace una vez en los tokens y se propaga a toda la web, sin recorrer página por página.
El propio diagrama de arriba es un ejemplo: no es un dibujo suelto, es el componente ds:integrations/flow del design system. El artículo usa las mismas piezas que describe.
En la práctica
Antes de cambiar un término del glosario abro su nodo, leo sus hot-paths y edito solo eso. Si muevo el código, actualizo la capa de implementación del nodo en el mismo commit. Sincronización bidireccional, sin excepciones.
Esto es, en el fondo, lo que resuelve Context Driven Development: pensar y construir dejan de ser dos fases separadas con un handoff en medio —ese punto donde la documentación se queda atrás— y se convierten en un mismo sistema, donde el blueprint, el design system y el código siempre cuentan la misma historia.
Un mes después: el complemento que le faltaba
Todo lo anterior lleva meses funcionando. Pero al usarlo de forma intensiva —461 términos de glosario, decenas de nodos, un agente leyendo el Context a diario— apareció un matiz que no había visto al diseñarlo, y que merece explicarse porque completa el sistema.
El validador comprueba una cosa muy concreta: que lo que el nodo declara exista. Que la ruta esté ahí, que el componente del design system exista de verdad. Eso resuelve el drift estructural: mover un archivo sin actualizar su nodo rompe el build, exactamente como prometía.
Lo que no cubre es el drift semántico: que el nodo diga algo sobre el código que dejó de ser cierto. Un caso real de esta web: el nodo de la wiki afirmaba «426 términos». El glosario había crecido a 461. Las rutas existían, los componentes existían, el validador pasaba en verde — y el nodo mentía. Ninguna de las dos capas era incorrecta por separado; lo que faltaba era alguien preguntando «¿sigue siendo verdad lo que este nodo afirma?».
Son dos tipos de verdad distintos:
| Estructural | Semántica | |
|---|---|---|
| Pregunta | ¿existe lo que el nodo declara? | ¿es cierto lo que el nodo afirma? |
| Ejemplo de fallo | ruta movida, componente renombrado | «426 términos» cuando son 461 |
| Se detecta con | validador determinista | comparación de afirmaciones contra la realidad |
| Puede romper el build | sí | no, sin ayuda |
La pieza que faltaba es una auditoría de nodo: un comando que, para un nodo dado, reúne las afirmaciones verificables (cifras que cita, rutas y comandos que nombra, componentes que declara, si su par bilingüe existe) y las contrasta con el repositorio real. Añade además una señal muy útil: si el código de sus hot-paths cambió después que el nodo, hay motivo para sospechar.
El reparto importa, y es lo que lo hace fiable: la máquina reúne los hechos, no dicta el veredicto. Comparar «426» con «461» es determinista. Decidir si esa diferencia significa «actualiza la cifra» o «el código se desvió del criterio» exige entender la intención — eso lo resuelve quien lee, sea persona o agente. Una herramienta que fingiera juzgar intenciones daría falsos positivos, y una herramienta con falsos positivos deja de leerse.
Con esa pieza, la estructura final queda así:
- Protocolo — el nodo se actualiza en el mismo commit que su código.
- Validador estructural — lo declarado existe, y además todo archivo tiene un nodo que lo reclama: cobertura completa en ambas direcciones.
- Auditoría semántica — lo afirmado sigue siendo cierto; los hechos se reúnen solos, el juicio lo pone quien lee.
La primera capa es disciplina, la segunda es determinismo, la tercera es criterio asistido. Y la lección de fondo confirma la tesis del método más de lo que la corrige: un sistema que no puede auditarse a sí mismo acaba mintiendo, por bien diseñado que esté. Que el propio Context detecte sus mentiras no es un parche sobre el modelo — es el modelo llevado hasta donde tenía que llegar.



