A lightweight collaborative document editor (React frontend + Node.js GraphQL backend) with real-time sync using Yjs.
Quick links: Frontend -> frontend/, Backend -> backend/, Collab server -> collab-server/.
Motivation: Existing document systems often suffer from slow updates and rigid architectures. We aimed to build a developer-friendly, full-stack platform that solves these pain points using modern systems and real-time synchronization.
Shrest Das - Docker + Kubernetes orchestration, AWS EC2 deployment, Collaboration, CI/CD pipeline
Maharsh Jani - Frontend-Backend Integration, PostgreSQL, Frontend Features + Templates
Sean Patel - Backend, GraphQL Queries, Version History, Commenting, Document Management
Nikhil Devarakonda - Frontend, Version History
cd backend
npm install
cd .. && chmod +x ./init_postgres.sh && ./init_postgres.sh && cd backend
service postgresql start
node backend/index.jscd backend
npm test
npm run lintcd frontend
npm install
npm startcd frontend
npm test
npx eslint src/ --ext .js,.jsx - Frontend:
localhost:3000 - GraphQL Playground:
localhost:4000/graphql
# Get all documents
query {
documents {
id
title
content
lastModified
}
}
# Get single document
query {
document(id: 1) {
title
content
}
}
# Create document
mutation {
createDocument(title: "Test", content: "Content") {
id
title
}
}
# Update document
mutation {
updateDocument(id: 1, title: "Updated", content: "New content") {
id
title
}
}This project includes a GitHub Actions workflow that builds Docker images for the backend and frontend,
pushes them to Docker Hub, and then SSHs into an EC2 instance to run docker compose pull and
docker compose up -d to deploy the latest images.
Required repository secrets (Settings → Secrets → Actions):
DOCKER_USERNAME- Docker Hub username used to push imagesDOCKER_PASSWORD- Docker Hub password or access tokenEC2_HOST- Public IP or DNS name of the EC2 instanceEC2_USER- SSH username (e.g.,ubuntu)EC2_SSH_KEY- The private SSH key (in PEM format) for theEC2_USER(no passphrase)EC2_SSH_PORT- SSH port (optional; set to22if omitted)
Server-side setup (one-time on the EC2 instance):
- Install Docker and Docker Compose v2:
sudo apt update
sudo apt install -y docker.io docker-compose-plugin
sudo usermod -aG docker $USER
newgrp docker- Create a deploy directory and give it a name matching the repository (example used by the workflow):
mkdir -p ~/fa25-team118-titans
cd ~/fa25-team118-titans
# place project's docker-compose.yml here (the workflow copies it)- Make sure the EC2 user can run docker commands and has enough permissions.
How the workflow works (high level):
- Builds backend and frontend Docker images and pushes them to Docker Hub using
DOCKER_*secrets. - Copies
docker-compose.ymland a smalldeploy.shscript to~/fa25-team118-titanson the EC2 host via SCP. - SSHs into the EC2 host and runs
deploy.sh, which runsdocker compose pullanddocker compose up -d.
Security notes:
- Keep
EC2_SSH_KEYand Docker Hub credentials secret. Prefer using a Docker Hub access token over a password. - Consider restricting SSH access to GitHub Actions runner IP ranges or using a bastion host.
This repo also now includes a deploy-k8s GitHub Actions workflow that builds backend/frontend Docker images,
pushes them to Docker Hub, and applies Kubernetes manifests in the k8s/ directory.
Required repository secrets for Kubernetes deploy:
DOCKER_USERNAME- Docker Hub username used to push imagesDOCKER_PASSWORD- Docker Hub password or access tokenKUBECONFIG- base64-encoded kubeconfig file for a service account or user that can apply manifests (keep secret)
What the workflow does:
- Builds backend/frontend images and tags them with the commit SHA.
- Restores
kubeconfigfrom theKUBECONFIGsecret and writes it to$HOME/.kube/config. - Replaces placeholders in the manifests under
k8s/with the pushed image tags and applies the manifests.
Notes:
- The provided manifests will continue to be worked on.
gh secret set DOCKER_USERNAME --body "${DOCKER_USERNAME}"
gh secret set DOCKER_PASSWORD --body "${DOCKER_PASSWORD}"
base64 -w0 $HOME/.kube/config | gh secret set KUBECONFIG --body -This repository includes a lightweight collaboration server using Yjs and y-websocket for local development and experimentation.
This repository now includes a lightweight collaboration server using Yjs and y-websocket.
What was added:
collab-server/— a small Yjs websocket server (listens on port1234by default).collab-server/Dockerfileandcollab-server/package.jsonso the server can be run via Docker.docker-compose.ymlincludes acollabservice exposed atws://localhost:1234for local development.docker-compose.ymlwas updated to add acollabservice exposed onws://localhost:1234for local development.- Frontend integration in
frontend/src/components/DocsFrontend.jsxconnects to the collab server and syncs document HTML via aY.Textnamedcontent. - Frontend integration in
frontend/src/components/DocsFrontend.jsxthat connects to the collab server and syncs document HTML via aY.Textnamedcontent.
Quick start (development):
- Build and start services (this will build the collab server image and start it):
docker compose up --build- Install frontend deps and run frontend (if not running in Docker):
cd frontend
npm install
npm start- Open the app in two browser windows and open the same document — edits should sync in near real-time via the collab server.
Notes:
- The current client writes the full editor
innerHTMLinto Y.Text on each input. This is a pragmatic starting point but not optimal for cursor preservation or efficient edits. - For production use, consider a proper editor binding (ProseMirror/TipTap/Quill) and secure the collab server (TLS + auth).
Notes and next steps:
- The current client writes the full editor
innerHTMLinto Y.Text on each input. This is a pragmatic starting point but not optimal for cursor preservation or efficient edits.