The Shift : Writing in the age of abundance
In the age of AI, online writing is undergoing a significant shift. While AI can generate content faster and more efficiently than humans, it lacks the ability to capture the unique perspectives and experiences that only human writers can provide. As a result, the Internet is likely to reward writing that prioritizes uniqueness and beauty over mere smartness and speed.
In today’s fast-paced digital landscape, collaboration has become a crucial aspect of content creation. Startup founders, VCs, and professionals across various industries are embracing tools that enable real-time collaboration, as they strive to generate ideas, write content, and refine it efficiently. One such platform that has gained significant traction in the design industry is Figma, a collaborative design tool valued at $10 billion. Read this blog post to learn more about Figma’s success story.
In this post I want to explore building an <span class="bg-highlight">
AI-native collaborative text editor application, utilizing Jamsocket, Next.js, and OpenAI’s Assistant API. Such an interface not only facilitates real-time brainstorming, writing, and content refinement among teams but also unlocks unparalleled creativity, enriched by intelligent suggestions and support from an AI co-writer.
- AI can’t replicate your unique voice and perspective. Your lived experiences, ideas, and writing style are one-of-a-kind, and that’s what will make your content stand out in a sea of AI-generated text.
- Readers crave high-quality, memorable content. With the abundance of mediocre writing online, people are hungry for exceptional ideas and beautifully crafted prose. By focusing on quality over quantity and authorship over speed you can capture and hold your audience’s attention.
- LLMs are like stochastic parrots, repeating patterns from their training data without true understanding. They generate text that may seem passable at first glance but lacks the depth, clarity, and intentionality of human writing. The difference is akin to a blurry photograph versus a carefully crafted painting - while the overall picture might be recognizable, the details are distorted and the meaning is lost.
- Shareable content is king. When you create content that is both unique and beautiful, it becomes more shareable. People are more likely to engage with and spread the word about writing that resonates with them on a personal level.
To succeed as a writer in the age of AI, embrace your singularity and hone your craft. Collaborate with AI agents to enhance your unique voice and perspective. These AI collaborators can help you refine your ideas, suggest improvements, and even challenge you to think more deeply about your writing.
Don’t try to outsmart or outpace AI; instead, focus on creating content that only you can produce, enhanced by the power of AI assistance. Use AI agents as a tool to augment your creativity and writing process, helping you craft more compelling and engaging content.
By leveraging the strengths of both human creativity and AI capabilities, you’ll be able to carve out a niche for yourself and build a loyal following of readers who appreciate your distinct voice and high-quality work. Embrace the collaboration between human ingenuity and artificial intelligence to create truly exceptional content that stands out in the digital landscape.
Building a Real-Time Collaborative Writing Tool
Here’s a concise overview of how we can design and implement this AI-powered collaborative writing tool:
Architectural Design
The application leverages a modular and scalable architecture:
- Frontend (Next.js + Quill): Next.js powers the user interface, integrating Quill as the rich text editor for seamless collaboration.
- AI Integration (OpenAI Assistant API): The OpenAI Assistant API provides contextual suggestions, corrections, and content generation to enhance the writing process.
- Real-time Collaboration (Jamsocket): Jamsocket enables real-time synchronization of document changes and user presence across connected clients.
- Backend Services (Next.js + Docker): The backend, including session management and AI request handling, is built using Next.js and deployed as containerized services using Docker.
Implementation Steps
- Set up Next.js: Create a new Next.js project and configure the necessary routes and API endpoints.
- Integrate Quill: Customize the Quill text editor to fit the application’s needs and ensure responsiveness.
- Connect Jamsocket: Implement real-time collaboration by setting up a Jamsocket service and managing user sessions.
- Integrate OpenAI Assistant API: Develop functions to fetch and display AI-powered writing suggestions based on user prompts.
- Deploy with Docker: Containerize the backend services using Docker for easy deployment and scalability.
By following this approach and leveraging the mentioned tech stack, you can build a feature-rich, AI-first collaborative writing tool that empowers creative teams to produce high-quality content efficiently.
🛠️ Tech Stack Used:
Technology | Description |
---|---|
Jamsocket | For real-time collaboration and shared state management |
Next.js | For building the server-side and client-side components |
OpenAI Assistants API | Integrates AI assistants for enhanced writing support |
Quill | Powers the text editor and syncs edits |
Tailwind CSS | For styling the application |
Astro | For the overall project setup and configuration |
Docker | For containerizing and deploying the session backend |
Jamsocket CLI | For managing the deployment to Jamsocket |
Laying the Foundation
Let’s start by setting up the project structure. We’ll be using a typical Next.js directory layout, with a few key components:
src/app/page.tsx
: This is the server-side component responsible for spawning the session backend on Jamsocket.src/components/Home.tsx
: The main client-side component that will handle the bulk of the application’s functionality.src/session-backend/index.ts
: The server-side logic for managing the shared state and real-time communication.
We’ll also include some helper components like TextCanvas.tsx
to encapsulate the text editor and synchronize edits between clients.
Implementing Session Backend
The session backend is the heart of our collaborative application. It acts as a stateful layer between the clients and the document storage, maintaining the shared state of the text document and handling real-time updates between connected users.
Here’s a simplified version of the session backend implementation in session-backend/index.ts
:
// ... imports
const io = new Server(8080);
let documentContent = ""; // Initial document state
io.on("connection", (socket: Socket) => {
socket.emit("snapshot", documentContent);
socket.on("update-document", (content: string) => {
documentContent = content;
socket.broadcast.emit("update-document", content);
});
// ... other event handlers
});
When a client connects, it receives a snapshot of the current document content. When a client updates the document, the session backend updates the shared state and broadcasts the changes to all connected clients.
Architecture
Integrating OpenAI Assistant
To provide AI-powered assistance during the collaborative writing process, we’ll integrate the OpenAI Assistant API. First, we’ll set up the API key in a .env
file:
OPENAI_API_KEY=[YOUR_OPENAI_API_KEY]
Then, in the session-backend/index.ts
file, we’ll create an OpenAI Assistant instance with instructions tailored for text editing collaboration:
const assistant = await openai.beta.assistants.create({
instructions: `You are an AI assistant for collaborative writing.
Help users with tasks like:
- Suggesting synonyms and alternative phrasings.
- Correcting grammar and spelling mistakes.
- Generating content based on user prompts.
- Providing feedback on the overall structure and flow of the document.`,
model: "gpt-4-1106-preview",
// ... other parameters
});
We’ll then modify the handleUserPrompt
function to send user prompts to the Assistant and process the responses to update the document state. This might involve parsing the Assistant’s response and applying the suggested changes to the shared document content.
Building the Text Editor Component
The heart of our collaborative text editor is the TextCanvas.tsx
component. We’ll use a library like Quill to handle real-time editing and synchronization, and integrate Jamsocket’s useEventListener
and useSend
hooks to receive updates from and send events to the session backend.
Here’s a complete example of the TextCanvas.tsx
component:
import React, { useEffect, useRef } from "react";
import Quill from "quill";
import "quill/dist/quill.snow.css";
import { useEventListener, useSend } from "@jamsocket/socketio";
import type { User } from "../types";
interface TextCanvasProps {
users: User[];
onCursorMove: (position: { x: number; y: number } | null) => void;
}
export function TextCanvas({ users, onCursorMove }: TextCanvasProps) {
const editorRef = useRef<HTMLDivElement>(null);
const sendEvent = useSend();
useEffect(() => {
if (!editorRef.current) return;
const editor = new Quill(editorRef.current, {
modules: {
toolbar: [
// ... toolbar options
],
},
theme: "snow",
});
editor.on("text-change", () => {
const content = editor.root.innerHTML;
sendEvent("update-document", content);
});
editor.on("selection-change", (range) => {
onCursorMove(range ? { x: range.index, y: range.index + range.length } : null);
});
return () => {
editor.off("text-change");
editor.off("selection-change");
};
}, [sendEvent, onCursorMove]);
return <div ref={editorRef} />;
}
The TextCanvas
component sets up a Quill editor instance and listens for text changes and cursor position updates. When the text is updated, it sends an update-document
event to the session backend. When the cursor position changes, it calls the onCursorMove
callback to update the cursor position for other users.
Real-Time Updates and Presence
To handle real-time updates and presence information, such as cursor positions and user avatars, we’ll use Jamsocket’s useEventListener
and useSend
hooks in the Home.tsx
component:
useEventListener<User>("cursor-position", (user) => {
// Update the user's cursor position in the local state
// and display it on the TextCanvas
});
// ...
const handleCursorMove = (position: { x: number; y: number } | null) => {
sendEvent("cursor-position", { x: position?.x, y: position?.y });
};
These hooks make it easy to synchronize the state between the session backend and the connected clients, creating a truly collaborative experience.
Deploying to Jamsocket
-
Use Jamsocket to manage shared state and real-time communication through session backends.
// Initialize Jamsocket session const session = Jamsocket.initSession('your-session-id'); session.on('update', (data) => { // Handle real-time updates });
-
Integrate OpenAI Assistant API to provide AI-powered suggestions and assistance during collaborative writing.
// Fetch AI suggestions async function fetchAISuggestions(prompt) { const response = await fetch('https://api.openai.com/v4/completions', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer your-openai-api-key' }, body: JSON.stringify({ model: 'text-davinci-002', prompt: prompt, max_tokens: 100 }) }); const data = await response.json(); return data.choices[0].text; }
-
Build a robust text editor component using libraries like Quill and synchronize edits using Jamsocket hooks.
// Initialize Quill editor and sync with Jamsocket useEffect(() => { const editor = new Quill('#editor', { theme: 'snow' }); editor.on('text-change', (delta, oldDelta, source) => { if (source === 'user') { session.send('text-change', delta); } }); }, []);
-
Handle presence information, such as cursor positions and user avatars, to enhance the collaborative experience.
// Update cursor position for all users session.on('cursor-move', (userId, position) => { // Update cursor position in the UI });
-
Deploy the session backend to Jamsocket for scalability and performance.
# Deploy session backend to Jamsocket jamsocket deploy --service your-service-name --image your-docker-image
So, there you have it. Stick to the guide, throw in your own twist, and boom - you’ve got yourself a slick, real-time text editor that’s not just smart but also plays well with others. Dive in, mess around, and make something cool.

About Sharad Jain
Sharad Jain is an AI Engineer and Data Scientist specializing in enterprise-scale generative AI and NLP. Currently leading AI initiatives at Autoscreen.ai, he has developed ACRUE frameworks and optimized LLM performance at scale. Previously at Meta, Autodesk, and WithJoy.com, he brings extensive experience in machine learning, data analytics, and building scalable AI systems. He holds an MS in Business Analytics from UC Davis.