Editor Integration
Editor Integration Protocol
Written for AI agents. See Log Methodology Note below for details.
Overview
A protocol for connecting browser-based editor applications to locally running Jay dev servers, enabling real-time development workflows with proper isolation between multiple editor tabs and dev server instances.
Problem
When developing Jay applications, we need a way for editor applications running in browser tabs to connect to locally running dev server processes. This creates several challenges:
- Multiple Editor Tabs: A user may have multiple editor tabs open, each working on different projects
- Multiple Dev Servers: Each project may have its own dev server process running locally
- Dual Port Requirements: Each dev server needs two ports - one for HTTP traffic of the site in development, and one for editor communication
- Port Management: We need to avoid port conflicts and ensure proper routing between tabs and servers
- Connection Isolation: Each editor tab should connect to the correct dev server instance
Solution: ID-Based Port Discovery
Core Protocol
- Tab ID Generation: Each editor tab generates a unique ID (UUID) when it loads
- Dev Server Configuration: Dev servers can be configured with a specific ID or start in "init" mode
- Port Range Scanning: Editor tabs scan a predefined range of ports to find the matching dev server
- Connection Establishment: Once found, the tab establishes a WebSocket connection to the dev server
- 2 Way Messaging: Two way Message based communication on top of WebSockets, packaged as two TS interfaces (dev server and editor)
Dev Server States
Init Mode
- Dev server starts without a specific ID
- Accepts the first connection request and adopts that tab's ID, updating into
.jayconfig file - Responds to any ID during the scanning phase
- Once connected, locks to that specific ID
Configured Mode
- Dev server starts with a specific ID (via
.jayconfig file) - Only responds to connection requests with the matching ID
- Rejects connections with non-matching IDs
Connection Flow
Editor Tab Dev Server
| |
|-- Generate UUID --------->|
| |
|-- Scan ports 3000-3100 -->|
| |
|<-- ID Match Response -----|
| |
|-- WebSocket Connect ----->|
| |
|<-- Connection Established-|
Port Scanning Strategy
- Dual Port Discovery: Editor tabs scan for the editor communication ports
- Default Port Ranges:
- HTTP site ports: 3000-3100
- Editor communication ports: 3101-3200
- Parallel Scanning: Send HTTP requests to each port in parallel
- ID Matching: Each request includes the tab's UUID
- Response Format: Dev servers respond with their current ID or "init" status
- WebSocket Connect: Editor Tab connects to the dev server with matching ID, or to one of the dev servers with "init" status. If connecting to a dev server with "init" status, it stores the UUID provided.
Implementation Details
Dev Server Endpoint
GET /editor-connect?id={tabId}
Response: { "status": "init" | "configured", "id": "server-id" }
WebSocket Upgrade
GET /editor-ws?id={tabId}
Upgrade: websocket
Benefits
- Automatic Discovery: No manual port configuration needed
- Isolation: Each tab connects to the correct dev server
- Flexibility: Supports both automatic and manual ID assignment
- Scalability: Can handle multiple concurrent development sessions
- Security: ID-based matching prevents unauthorized connections
Configuration: .jay File
The .jay file is a YAML configuration file that stores project-specific settings for the editor integration protocol.
File Structure
# .jay
editor:
id: '550e8400-e29b-41d4-a716-446655440000' # Optional: specific editor ID
name: 'my-site-1' # Optional: specific editor project name
portRanges:
http: [3000, 3100] # HTTP site port range
editor: [3101, 3200] # Editor communication port range
Configuration Options
editor.id: Optional UUID for the editor connection. If not specified, the dev server starts in init modeeditor.id: Optional UUID for the editor connection. If not specified, the dev server starts in init modeeditor.portRanges.http: Port range for the HTTP site server (default: [3000, 3100])editor.portRanges.editor: Port range for editor communication (default: [3101, 3200])
Auto-Generation
When a dev server in init mode accepts its first connection, it automatically creates or updates the .jay file with the editor ID and current port configuration.
Applicative Protocol
The applicative protocol defines the message-based communication between editor tabs and dev servers, packaged as TypeScript interfaces for both sides.
Editor Side Interface
interface EditorProtocol {
// Publish a jay-html file to the dev server
publish(params: { route: string; jayHtml: string; name: string }): Promise<{
success: boolean;
filePath?: string;
error?: string;
}>;
// Save an image to the local dev server
saveImage(params: {
imageId: string;
imageData: string; // base64 encoded image data
}): Promise<{
success: boolean;
imageUrl?: string;
error?: string;
}>;
// Check if a previously saved image exists
hasImage(params: { imageId: string }): Promise<{
exists: boolean;
imageUrl?: string;
}>;
}
Dev Server Side Interface
interface DevServerProtocol {
// Handle jay-html publication requests
onPublish(
callback: (params: {
pages: [
{
route: string;
jayHtml: string;
name: string;
},
];
}) => Promise<{
status: [
{
success: boolean;
filePath?: string;
error?: string;
},
];
}>,
): void;
// Handle image save requests
onSaveImage(
callback: (params: {
imageId: string;
imageData: string; // base64 encoded image data
}) => Promise<{
success: boolean;
imageUrl?: string;
error?: string;
}>,
): void;
// Handle image existence check requests
onHasImage(
callback: (params: { imageId: string }) => Promise<{
exists: boolean;
imageUrl?: string;
}>,
): void;
}
Message Format
All protocol messages are sent as JSON over WebSocket with the following structure:
interface ProtocolMessage {
id: string; // Unique message ID for request/response correlation
type: 'publish' | 'saveImage' | 'hasImage';
params: any;
timestamp: number;
}
interface ProtocolResponse {
id: string; // Matches the request ID
success: boolean;
data?: any;
error?: string;
timestamp: number;
}
Operation Details
Publish Operation
- Purpose: Saves a jay-html file to the dev server at the specified route
- File Location: Files are saved relative to the project root
- Response: Returns the full file path where the file was saved
Save Image Operation
- Purpose: Saves base64 image data to the dev server's public assets
- Storage: Images are saved to a configurable assets directory
- URL Format: Returns a URL accessible via the dev server's HTTP port
Has Image Operation
- Purpose: Checks if an image with the given ID already exists
- Caching: Allows editors to avoid re-uploading existing images
- Response: Returns both existence flag and current image URL if it exists
Log Methodology Note
Note: These design logs are written primarily for AI agents as part of the Design Log methodology and made accessible here for human readers. The language and structure are optimized for machine consumption — expect precise, specification-style prose rather than narrative documentation.