aboutsummaryrefslogtreecommitdiff

JCHAT - JMAP-based Chat Protocol and Implementation

JCHAT is a chat protocol built on top of JMAP (JSON Meta Application Protocol) [RFC8620], providing real-time messaging capabilities with efficient synchronization and push notifications.

Project Structure

jchat/
├── draft-jchat-00.txt          # RFC draft specification
├── rfc8620.txt                 # Base JMAP RFC for reference
├── server/                     # Erlang/OTP server implementation   ├── src/                    # Server source code   ├── test/                   # Comprehensive test suite   ├── config/                 # Configuration files   ├── rebar.config            # Build configuration   └── Makefile               # Build automation
└── client/                     # HTML/JavaScript web client
    ├── index.html              # Main client interface
    ├── jmap-client.js          # JMAP client library
    ├── app.js                  # Application logic
    └── package.json            # Project metadata

Features

Protocol Features (JCHAT RFC)

  • Conversations: Group messaging with metadata and participant management
  • Messages: Rich text messages with attachments, replies, and reactions
  • Participants: User roles, permissions, and presence management
  • Real-time Updates: Push notifications and efficient delta synchronization
  • Standards Compliant: Built on proven JMAP foundation

Server Implementation

  • Erlang/OTP: Fault-tolerant, concurrent server architecture
  • Mnesia Database: Built-in distributed database for persistence
  • HTTP API: RESTful JMAP endpoints with JSON serialization
  • Push Notifications: Server-Sent Events for real-time updates
  • Comprehensive Testing: Unit, property-based, and performance tests

Web Client

  • Modern UI: Responsive design with conversation list and chat interface
  • Real-time Messaging: Live message updates and typing indicators
  • Cross-platform: Works in any modern web browser
  • JMAP Integration: Native support for JMAP protocol features

Quick Start

Prerequisites

  • Erlang/OTP 24+ (for server)
  • Any HTTP server for client (shttpd, Python, nginx, etc.)
  • rebar3 (Erlang build tool)

Running the Server

cd server
make compile
make run

The server will start on http://localhost:8080 with the following endpoints: - GET /jmap/session - JMAP session information
- POST /jmap/api - JMAP method calls - GET /jmap/eventsource - Server-Sent Events for push notifications

Running the Client

The client is a dependency-free web application built with vanilla HTML, CSS, and JavaScript.

Quick Start (no installation required)

Using shttpd (recommended):

cd client
shttpd . --port 3000

Using Python:

cd client
python3 -m http.server 3000

Using any web server:

cd client
# Point nginx, Apache, or any HTTP server to this directory

The client will be available at http://localhost:3000

Testing

Server Tests

cd server
make test          # Run all tests
make test-unit     # Unit tests only
make test-prop     # Property-based tests
make test-perf     # Performance tests

Manual Testing

  1. Start the server: cd server && make run
  2. Start the client: cd client && shttpd . --port 3000
  3. Open http://localhost:3000 in your browser
  4. The client will automatically connect to the server

API Examples

Create a Conversation

const conversation = await jmapClient.createConversation({
    title: "Project Discussion",
    participantIds: ["user1", "user2", "user3"]
});

Send a Message

const message = await jmapClient.sendMessage(
    conversationId,
    "Hello, everyone!",
    "text/plain"
);

Query Messages

const messages = await jmapClient.queryMessages({
    inConversation: conversationId,
    after: "2025-08-15T10:00:00Z"
});

Architecture

JMAP Foundation

JCHAT extends JMAP with chat-specific object types: - Conversation: Container for messages and participants - Message: Individual chat messages with rich metadata
- Participant: User membership in conversations - Presence: User availability and status information

Server Architecture

┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐
│   HTTP Layer    │────│   JMAP Methods   │────│   Data Layer    │
│  (Cowboy)       │    │  (Conversations, │    │   (Mnesia)      │
│                 │    │   Messages, etc) │    │                 │
└─────────────────┘    └──────────────────┘    └─────────────────┘
         │                       │                       │
         │              ┌────────────────┐               │
         └──────────────│  Push Manager  │───────────────┘
                        │ (Server-Sent   │
                        │  Events)       │
                        └────────────────┘

Client Architecture

┌─────────────────┐    ┌──────────────────┐    ┌─────────────────┐
│   UI Layer      │────│  Application     │────│  JMAP Client    │
│  (HTML/CSS)     │    │  Logic           │    │  Library        │
│                 │    │  (JChatApp)      │    │  (JMAPClient)   │
└─────────────────┘    └──────────────────┘    └─────────────────┘
                                │                       │
                                │              ┌────────────────┐
                                └──────────────│  Server API    │
                                               │ (HTTP/JSON)    │
                                               └────────────────┘

Protocol Details

JMAP Capability

"urn:ietf:params:jmap:chat"

Core Methods

  • Conversation/get, Conversation/set, Conversation/query, Conversation/changes
  • Message/get, Message/set, Message/query, Message/changes
  • Participant/get, Participant/set, Participant/changes
  • Presence/get, Presence/set

Example JMAP Request

{
  "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:chat"],
  "methodCalls": [
    ["Conversation/query", {
      "accountId": "primary",
      "sort": [{"property": "lastMessageAt", "isAscending": false}]
    }, "c1"],
    ["Message/query", {
      "accountId": "primary", 
      "filter": {"inConversation": "#c1/ids/0"},
      "sort": [{"property": "sentAt", "isAscending": true}]
    }, "c2"]
  ]
}

Development

Server Development

  • Add new JMAP methods in src/jchat_methods.erl
  • Extend data models in src/jchat.hrl
  • Database operations in src/jchat_db.erl
  • Add tests in test/ directory

Client Development

  • UI components in index.html and CSS
  • JMAP protocol handling in jmap-client.js
  • Application logic in app.js
  • Build with any modern JavaScript toolchain

Testing Strategy

  1. Unit Tests: Individual function testing
  2. Integration Tests: Full JMAP request/response cycles
  3. Property Tests: Randomized testing with PropEr
  4. Performance Tests: Load testing and benchmarks
  5. Manual Tests: End-to-end user scenarios

Deployment

Production Server

cd server
make release
_build/prod/rel/jchat/bin/jchat start

Docker Deployment

# Build server image
cd server
docker build -t jchat-server .

# Build client image  
cd client
docker build -t jchat-client .

# Run with docker-compose
docker-compose up

Contributing

  1. Read the JCHAT RFC draft (draft-jchat-00.txt)
  2. Follow Erlang/OTP conventions for server code
  3. Use modern JavaScript practices for client code
  4. Add tests for all new features
  5. Update documentation as needed

Standards Compliance

  • RFC 8620: JSON Meta Application Protocol (JMAP)
  • RFC 8259: JSON Data Interchange Format
  • RFC 3339: Date and Time on the Internet
  • RFC 7231: HTTP/1.1 Semantics and Content

License

This project is licensed under the MIT License - see the LICENSE file for details.

References