A proof-of-concept demonstrating Figma-style commenting tools that can be injected into any web application without modifying its source code. This simulates how Codesphere could overlay feedback tools onto customer deployments.
โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ
โ Browser โโโโโโถโ Proxy (:3000) โโโโโโถโ Target (:3001) โ
โ localhost:3000โ โ Injects script โ โ Black-box site โ
โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโฌโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโ
โ UI Server(:3002)โ
โ codesphere- โ
โ tools.js (IIFE) โ
โโโโโโโโโโโโโโโโโโโ
| Server | Port | Purpose |
|---|---|---|
| Proxy | 3000 | Entry point. Fetches HTML from target, injects <script> tag, serves comments API |
| Target App | 3001 | Simulated customer site with zero knowledge of commenting system |
| Commenting UI | 3002 | React overlay bundled as standalone IIFE, mounted in Shadow DOM |
- Zero-Config Injection - Commenting tools appear on any site passing through the proxy
- Shadow DOM Isolation - Overlay CSS is completely isolated from target site styles
- Robust Selector Engine - Generates unique CSS selectors (ID โ class โ nth-of-type fallback)
- Relative Anchoring - Pins stored as
selector + x/yPercentagefor resize-safe positioning - Draggable Pins - Click and drag any pin to reposition; changes persist to JSON
- Scroll/Resize Sync - Pins follow their target elements via
MutationObserver+ event listeners - Viewport Metadata - Each comment stores the viewport dimensions when created
# Clone the repo
git clone https://github.com/alexvcodesphere/comment-example.git
cd comment-example
# Install all dependencies
cd target-app && npm install && cd ..
cd commenting-ui && npm install && cd ..
cd proxy && npm install && cd ..
# Build the commenting UI bundle
cd commenting-ui && npm run build && cd ..
# Start all three servers (in separate terminals)
cd target-app && npm start # Terminal 1: Port 3001
cd commenting-ui && npm run serve # Terminal 2: Port 3002
cd proxy && npm start # Terminal 3: Port 3000
# Open browser
open http://localhost:3000comments-test/
โโโ target-app/ # Port 3001 - Simulated customer site
โ โโโ index.html # Rich HTML with aggressive CSS
โ โโโ styles.css # Uses !important to test isolation
โ โโโ server.js # Express static server
โ
โโโ commenting-ui/ # Port 3002 - React overlay (IIFE bundle)
โ โโโ src/
โ โ โโโ main.tsx # Shadow DOM mounting
โ โ โโโ CodesphereOverlay.tsx # Main React component
โ โ โโโ styles.ts # Isolated CSS-in-JS
โ โ โโโ api.ts # REST client
โ โ โโโ types.ts # TypeScript interfaces
โ โ โโโ hooks/
โ โ โ โโโ usePinPositions.ts # Scroll/resize/mutation sync
โ โ โโโ utils/
โ โ โโโ getSelector.ts # CSS selector generator
โ โ โโโ positionUtils.ts # Relative anchoring math
โ โโโ vite.config.ts # IIFE bundle config
โ โโโ server.js # Static file server for dist/
โ
โโโ proxy/ # Port 3000 - Injection proxy + API
โโโ server.js # HTML injection + /api/comments CRUD
โโโ comments.json # JSON file persistence
The proxy intercepts HTML responses and injects:
<script src="http://localhost:3002/codesphere-tools.js"></script>The injected script creates an isolated container:
const container = document.createElement("div");
const shadowRoot = container.attachShadow({ mode: "open" });
// All overlay UI renders inside shadowRootWhen placing a comment, the overlay temporarily hides itself to detect the underlying element:
overlayRoot.style.visibility = "hidden";
const element = document.elementFromPoint(x, y);
overlayRoot.style.visibility = "";Unique selectors are generated with priority:
- ID:
#main-nav - Unique class combo:
.hero-title - nth-of-type:
article.feature-card:nth-of-type(2)
Pins are stored as percentages of the target element:
{
"selector": ".hero-title",
"xPercentage": 66.88,
"yPercentage": 81.25
}| Method | Endpoint | Description |
|---|---|---|
| GET | /api/comments |
Fetch all comments |
| POST | /api/comments |
Create new comment |
| DELETE | /api/comments/:id |
Delete comment |
| PATCH | /api/comments/:id/resolve |
Mark as resolved |
| PATCH | /api/comments/:id/position |
Update position (after drag) |
interface Comment {
id: string;
selector: string; // CSS selector of target element
xPercentage: number; // 0-100, relative to element width
yPercentage: number; // 0-100, relative to element height
content: string;
author: { id; name; avatar };
createdAt: string;
resolved: boolean;
viewport?: { width; height }; // Screen size when comment was made
}- Staging review - Get feedback on deployments before production
- Design QA - Designers can annotate specific UI elements
- Bug reporting - Pin comments to exact problem areas
- Client feedback - Non-technical stakeholders can comment visually
Deploy as 3 separate services with path-based routing:
| Service | Env Variable | Value | Description |
|---|---|---|---|
| Target App | BASE_PATH |
/target |
Path where service is mounted |
| Commenting UI | BASE_PATH |
/commenting-ui |
Path where service is mounted |
| Proxy | TARGET_URL |
https://<workspace>.codesphere.com/target |
Full URL to Target App |
| Proxy | TOOLS_URL |
https://<workspace>.codesphere.com/commenting-ui |
Full URL to Commenting UI |
# CI Pipeline
cd target-app && npm install
# Run Command
cd target-app && node server.js
# Environment Variables
BASE_PATH=/target# CI Pipeline
cd commenting-ui && npm install && npm run build
# Run Command
cd commenting-ui && node server.js
# Environment Variables
BASE_PATH=/commenting-ui# CI Pipeline
cd proxy && npm install
# Run Command
cd proxy && node server.js
# Environment Variables
TARGET_URL=https://77015-3000.2.codesphere.com/target
TOOLS_URL=https://77015-3000.2.codesphere.com/commenting-uiNote: Replace
77015-3000.2.codesphere.comwith your actual Codesphere workspace URL.
MIT