Background
Herramientas de Desarrollo con IAdiciembre de 2025

Hexode v3.0: IDE en la Nube Colaborativo Nativo de IA

Un IDE colaborativo en la nube nativo de IA para escribir, ejecutar y discutir código directamente en el navegador.

Hexode v3.0: IDE en la Nube Colaborativo Nativo de IA — screenshot 1
01 — Overview

Descripción General

Hexode es un IDE colaborativo respaldado por la nube y basado en el navegador, diseñado para llevar el desarrollo nativo de IA y la colaboración en tiempo real directamente al navegador.

Permite a múltiples usuarios editar proyectos de múltiples archivos de forma colaborativa, ejecutar código y consultar a un asistente de codificación de IA integrado sin ninguna instalación local. Hexode también sirve como un entorno de codificación en el navegador sin configuración, diseñado para entrevistas técnicas y práctica de DSA.

02 — Why I Built It

Por Qué Construí Hexode

"Quería un entorno de desarrollo que viviera completamente en el navegador: sin configuración local, un lugar para escribir y ejecutar código, practicar problemas de entrevistas y DSA, colaborar con otras personas en tiempo real y usar IA dentro del mismo flujo de trabajo."

03 — Architecture

Arquitectura

Browser (Client)
React / MonacoYjs State
WebSocket
Node.js + Express (Backend)
Yjs Sync
REST API
HexodeAI
Orchestrator
MongoDBPersistence
Gemini ProHexodeAI
Judge0Code Execution
  • LevelDB is used for CRDT persistence.
  • Clerk provides authentication.
  • Vercel hosts the frontend.
04 — Real-Time Collaboration

Colaboración en Tiempo Real

Monaco serves as the primary editing surface, while Yjs provides CRDT-based shared document state. File contents are represented as Y.Text, and project files are tracked using a Y.Map. Synchronization is transported over WebSocket, with Awareness providing real-time presence and cursor state. Chat messages are also persisted within the shared Yjs document.

Crucially, the server implements the Yjs binary synchronization and awareness protocol directly using y-protocols/sync, y-protocols/awareness, and lib0 encoding/decoding.

By avoiding the standard y-websocket server package, the HTTP and WebSocket state live together in the same Node.js process. This means the server already has access to the live Yjs documents, allowing the AI endpoint to access that state without requiring the browser to resend the full code context.

05 — Synchronization Bug

Hard Problem Callout

El Error de Sincronización: Resolviendo la Condición de Carrera de Inicialización

In the original approach, a simple setTimeout was used before initializing a project. This risked overwriting the state before the CRDT synchronization had fully completed.

The final approach waits for the Websocket/Yjs provider to emit a 'synced' event. By combining provider.on('synced') with a check to ensure yFilesMap.size === 0, the project initializes only when appropriate. This is a correctness and race-condition fix, ensuring reliable document state.

Old ApproachsetTimeout(() => init(), 1000)
Final Approachprovider.on("synced", ...) + yFilesMap.size === 0
06 — Multi-File Execution

Ejecución de Código de Múltiples Archivos

Hexode supports multi-file projects, but Judge0 receives a single source_code string. This central mismatch requires a language-specific transformation pipeline.

For Java, public classes are renamed to Main, packages are stripped, access modifiers are handled, and Main collisions are managed.

For JavaScript, a custom require() shim is injected, resolving relative modules through an in-memory registry.

For C, C++, and Python, files are merged via ordered concatenation.

JavaScriptPythonJavaCC++
07 — HexodeAI

HexodeAI

When a user sends a message, it hits the /api/ai/chat endpoint. After rate limiting, the server reads the current Yjs document state directly from memory. It builds the context (capped at 2000 characters) and sends it to the Gemini API (gemini-3-flash-preview).

The response is streamed back via SSE (Server-Sent Events) and consumed by the client using a ReadableStream for incremental React rendering.

The AI endpoint enforces limits of 5 requests per minute and 20 requests per day. Additionally, a keyword-based query firewall blocks unrelated queries before they even reach the Gemini API.

08 — Engineering Challenges

Desafíos de Ingeniería

1. Condición de Carrera en Inicialización CRDT

Problem: Initializing default project files could overwrite remote state if synchronization hadn't finished.

Approach: Listen to the Yjs provider's 'synced' event and check if the document is empty before initializing.

Result: Removed the initialization race that could overwrite synchronized project state.

2. Ejecución de Proyectos de Múltiples Archivos

Problem: Executing multi-file code against a single-string execution API (Judge0).

Approach: Implement language-specific merging pipelines (e.g., custom require shims, class renaming, concatenation).

Result: Enables multi-file execution across 5 supported languages.

3. Protocolo Manual WebSocket Yjs

Problem: Need to share HTTP and WebSocket state without running separate processes.

Approach: Implement the Yjs binary sync protocol directly on the Express server using lib0 and y-protocols.

Result: Unified server state, enabling the AI to read live documents from memory.

4. Manejo de Errores a Mitad de Flujo SSE

Problem: HTTP status codes cannot be changed once headers are sent during a Server-Sent Events stream.

Approach: Stream specialized error event payloads that the client interprets and renders gracefully.

Result: Robust UI error states even when the LLM API fails mid-generation.

5. Revinculación de Monaco/Yjs

Problem: Switching files in the IDE left lingering CRDT bindings on the editor instance.

Approach: Destroy the previous MonacoBinding and rebind on file name changes.

Result: Clean transitions between files with correct cursor and edit tracking.

09 — Technical Decisions

Decisiones Técnicas

Manual Yjs Server

Sharing the HTTP and WebSocket server provides direct access to the server-side document state in memory.

Sync-Event Initialization

Prevents premature default initialization that would corrupt incoming CRDT state.

Server-Side Yjs Context for AI

Avoids sending the full document contents over the network from the browser with every AI request.

Derived WebSocket URL

Deriving the WebSocket URL from the API URL reduces frontend deployment configuration surface.

10 — Trade-offs

Compromisos y Limitaciones

  • Los documentos Yjs en memoria impiden el escalado horizontal directo.
  • La autorización es actualmente solo del lado del cliente.
  • Se utiliza la API pública de Judge0 CE, que tiene limitaciones de tarifa y SLA.
  • No hay una suite de pruebas automatizadas.
  • El código base es JavaScript sin TypeScript.
  • La terminal es simulada en lugar de ser un verdadero PTY.
  • No hay una interfaz de usuario dedicada para la resolución de conflictos, ya que Yjs maneja los conflictos CRDT automáticamente.
11 — What I Learned

Lo Que Aprendí

Los sistemas en tiempo real son fundamentalmente problemas de sincronización.

El estado CRDT cambia la forma en que se debe razonar sobre la persistencia y la inicialización. Ya no puedes simplemente cargar el estado desde una base de datos; tienes que fusionarlo de manera segura.

El contexto de IA de múltiples archivos es un problema de arquitectura, no simplemente 'llamar a una API LLM'. Diseñar el sistema para que el servidor tenga acceso a los documentos en vivo elimina por completo la carga útil del cliente.

La ejecución confiable requiere diseñar en torno a las limitaciones del servicio de ejecución.

Qué Construiría Diferente Hoy

"Si comenzara Hexode hoy, haría que la plataforma fuera nativa de IA desde el nivel de arquitectura en lugar de tratar a la IA como un asistente agregado a un IDE existente. También elegiría Judge0 desde el principio en lugar de pasar por el enfoque anterior basado en Piston."

12 — Tech Stack

Pila de Tecnología

TechnologyRole
ReactBiblioteca de interfaz de usuario frontend
ViteHerramientas y empaquetador frontend
MonacoSuperficie del editor de código
YjsCRDT para colaboración en tiempo real
WebSocketTransporte de sincronización en tiempo real
Node.jsEntorno de tiempo de ejecución backend
ExpressAPI backend y host WebSocket
MongoDB AtlasBase de datos principal para metadatos
MongooseModelado de objetos MongoDB
LevelDBAlmacenamiento persistente para CRDT
GeminiLLM que impulsa HexodeAI
Judge0Motor de ejecución de código
ClerkAutenticación de usuario
Framer MotionAnimaciones de interfaz de usuario
TailwindEstilo CSS utility-first