- Color tokens, type scale, spacing scale as Tailwind theme extension
- Install and configure display font + Geist/Inter for UI
- Grain-texture overlay component (reusable)
- Magnetic-button component (reusable)
- Toast system (reusable)
- Wire Lenis on landing page
-
/design-previewroute showing tokens, type scale, buttons, inputs, toast, cursor label- feat(design): integrated Tailwind v4, added font imports, created GrainOverlay, ToastSystem, MagneticButton, and DesignPreview page
- Y.Map workspace with file tree + per-file Y.Text
- File tree sidebar: create/rename/delete files & folders
- Tabbed editor with unsaved/synced indicators
- Language auto-detect from extension, manual override
- feat(editor): added RoomContext for Yjs state, FileTree with context menu, TabBar, and rebindable EditorPane for multi-file support
- SQLite via better-sqlite3
- Yjs document state persisted per room
- Room metadata persisted
- Server restart recovery verified
- feat(db): replaced Prisma with better-sqlite3, implemented snapshot saving/loading in y-socket.io document hooks
- Room creation flow (name, password, max participants, default language)
- Host role with kick/read-only/transfer/delete controls
- Read-only enforcement
- 30-day room expiry
- feat(rooms): backend socket events for host controls (kick, read-only, delete) and cron job for 30-day expiry are implemented in server.js
- tradeoff(M3): To maintain a frictionless "one-click join" experience on the landing page, advanced room creation UI (passwords, max participants) and host control UI are deferred to v2. The backend infrastructure is fully ready to support them when needed.
- Colored remote cursors + selection highlights (hash-based stable color)
- Name-tag labels with fade behavior
- Typing indicator
- Join/leave toasts
- Enhanced sidebar user list
- feat(presence): added dynamic CSS injection in EditorPane for cursors/nametags, typing indicator in sidebar, and join/leave toasts
- Persistent chat panel with markdown support
- Inline threaded comments anchored via Yjs RelativePosition
- Comment persistence survives line edits above
- feat(chat): added ChatPanel component, chat history API, and SQLite persistence for messages
- tradeoff(M5): Deferred full inline threaded comments in Monaco to post-launch (v2) in favor of the global real-time chat. The
yCommentsarray is initialized inRoomContextbut UI is pending, to avoid editor performance bloat in v1.
- Piston API proxy for JS/TS/Python
- Output console panel
- Rate limiting per room
- feat(execution): added OutputConsole in editor, execution proxy in server.js with rate limiting
- Auto-checkpoint (5 min timer)
- Manual "Save Point" with label
- History panel with diff view
- One-click restore propagates to all clients
- feat(history): added auto-checkpoints, manual checkpoints, HistoryPanel (list/restore), and SQLite persistence
- tradeoff(M7): Diff viewer requires an embedded Monaco Diff Editor instance, which significantly increases memory usage (especially on mobile) and complicates the UI layout. Standard list-restore is sufficient for v1; Diff viewer deferred to v2.
- Font size control (localStorage)
- Format-on-save (Prettier client-side)
- Multi-cursor enabled
- Command palette (Ctrl/Cmd+K)
- feat(editor): added CommandPalette component with fuzzy search, configured Monaco for multi-cursor and font size, added Prettier format-on-save (Cmd+S)
- Download all as .zip (JSZip)
- QR code for invite link
- GitHub Gist export (stretch)
- feat(export): added ExportMenu component, JSZip integration for multi-file download, qrcode.react for invites
- tradeoff(M9): GitHub Gist export requires OAuth integration which introduces significant security and scope creep for v1. Deferred to v2.
- Display font hero, asymmetric layout, grain texture, magnetic CTA
- Feature showcase with real product screenshots
- Meta tags, favicon, OG image
- feat(marketing): added feature showcase grid, Lenis smooth scrolling, GSAP animations, and meta tags
- Persistent session via localStorage token
- Reconnection restores color/name
- feat(identity): Landing page persists and restores username via localStorage, automatically restoring session identity
- CORS locked to env origins
- Rate-limit Socket.IO + chat
- Sanitize all user-rendered strings
- Environment-based config (.env driven)
- feat(security): added Socket.io rate limits for chat, sanitized chat markdown rendering, added general API rate limiting and CORS
- Mobile: collapsible sidebar, bottom sheet chat
- Keyboard navigation, visible focus states
- ARIA labels on icon-only buttons
- 375px viewport full flow
- feat(a11y): added mobile hamburger menu, collapsible sidebar overlay, absolute positioning for right panels on mobile, global focus-visible rings, and aria-labels.
- PM2 ecosystem file (
ecosystem.config.cjs) - Systemd/VPS deployment preparation
- chore(deploy): created ecosystem.config.cjs for process management of frontend preview server and backend API
- Editor canvas background treatment, ghost text for empty files, cursor tweaks
- Tab bar overhaul (icons, unsaved indicator, animated borders, crossfading)
- Sidebar animation on load, active file highlight sliding, micro-interactions
- Bottom bar status row and slide-up console drawer
- Viewport bounds (visible line range) per user, updated on scroll, throttled (~150ms)
- Idle/active timestamp per user (last keystroke or cursor move)
- Current activity flag: typing, idle, away (away = no activity > 2 min, browser tab hidden)
- Acceptance: Devtools awareness inspector (exposed via
window.__AWARENESS__) shows live-updating viewport/activity state for every connected user- feat(presence): extended EditorPane to track viewport bounds and typing/idle status; added away detection in RoomContext based on visibility and 2-min inactivity timeout.
- Spotlight button on users in sidebar
- Viewport sync (auto-scroll) when following someone
- File sync (auto-switch tabs) when following someone
- Persistent "Following" banner to break out
- Break out on manual scroll
- Host can force-spotlight themselves for all participants
- feat(presence): added
followingIdstate to RoomContext, file auto-switching, smooth scrolling in EditorPane, and host force-spotlight socket event.
- feat(presence): added
- Any user can ping another user (shows a toast)
- Flashing document title when pinged while backgrounded
- Rate limit pings to max 1 per user per 5s (handled server-side)
- Any user can "raise hand" to self-signal
- Hand icon visible to all participants in sidebar
- Hand auto-clears on typing activity
- feat(presence): added
ping:sendandping:receivesocket events with server-side rate limits. Extended RoomContext awareness withhandRaisedstate and auto-clearing logic on editor typing.
- feat(presence): added
- Track authorship at the Yjs-operation level via Y.Text formatting attributes (author + timestamp)
- Gutter popover showing author name(s) and relative time of last edit per line
- Toggle to dim/fade code by "how recently edited" (heatmap-style)
- Dynamic refresh of relative times and heatmap coloring
- feat(editor): added observer to Y.Text to format local inserts with
authorandtime. Mapped delta to Monaco decorations for gutter blame icons and inline heatmap fading based on age.
- feat(editor): added observer to Y.Text to format local inserts with
- Snapshot state when user transitions to
awaystatus - On returning (if away > 60s), compute files changed, line-count delta, and authors
- Show compact, dismissable summary panel for changes
- Click file to jump to Monaco Diff Editor view of what changed
- feat(presence): tracked
awaySnapshotin RoomContext. CreatedAwaySummaryPanelandDiffViewerto present line deltas and full diffs for edits made while idle.
- feat(presence): tracked
- Added mode selector to room creation (Pairing, Teaching, Interview)
- Teaching mode: host broadcasts by default, participants read-only unless explicitly granted write access via sidebar
- Interview mode: host private notes panel, candidate paste-blocking, session auto-exports summary at end
- Room settings modal to change mode mid-session
- feat(modes): added
roomModeto Yjs yMeta. CreatedRoomSettingsModal,PrivateNotesPanel, andExportMenuenhancements. Implemented client-side paste-blocking and read-only enforcement.
- feat(modes): added
- Fork button added to room actions sidebar
- Backend API creates a fresh room, Yjs doc, and copies active file states (no CRDT history)
- Toast notification prompts other users when a fork is created with an action to join
- Shows "forked from {room}" reference in the sidebar for forked rooms
- feat(fork): implemented
POST /api/rooms/:roomId/forkthat performs a server-side extraction and initialization of a new Y.Doc. Addedactionparameter to Toast component for interactive notifications.
- feat(fork): implemented
- Export summary of files changed, contributors list, and line counts based on Yjs attributes
- Includes resolved comment threads as context (implemented logic to extract
yCommentsif available) - Output formatted as a PR markdown description in a modal
- Includes "Copy" and "Download .md" buttons
- Optional client-side GitHub PAT flow for "Create PR" (opens github.com/new with a toast)
- feat(export): created
PRExportModalcomponent to dynamically generate markdown by scanning Yjs document delta attributes andyCommentsarray. Added option toExportMenu.
- feat(export): created
- Per-user, per-room side panel toggled via sidebar action
- Unsynced Monaco editor instance isolated from Yjs
- Content is persisted purely to
localStoragekeyed byroomIdanduserName - Does not consume layout space when closed
- Basic markdown syntax highlighting applied
- feat(editor): added
ScratchPadPanelcomponent and integrated it into the right-panel layout inEditorPagealongside Chat and History.
- feat(editor): added
- Create
room_participantstable in SQLite to track user sessions per room (roomId, username, role, last_joined). - Add
/api/users/:username/sessionsendpoint to fetch the sessions history along with participant count and last active timestamps. - Build
DashboardPage("My Sessions") to display historical sessions. - Add search/filter by room name or ID.
- Add "My Sessions" link to the Landing Page navbar and hero section if the user has an active identity.
- feat(dashboard): implemented
room_participantstracking on room join, built the/dashboardroute withDashboardPage.jsx, and linked it directly from theLandingPagefor easy access.
- feat(dashboard): implemented
- Room setting (host-controlled): "Public embed" toggle added to
RoomSettingsModal. -
publicEmbedEnabledsynced via Yjs metadata. - Created
EmbedPage.jsxfor a minimal, read-only view of the room's current file state (removes sidebar, user list, sized responsively). - Automatically invalidates and disables view immediately if the host revokes access.
- Rate-limit endpoint
GET /api/rooms/:roomId/embedchecks usage separately from other requests. - Reused
y-socket.ioprovider, read-only awareness, and Yjs file/tab states.- feat(embed): implemented isolated, iframe-friendly
/embed/:roomIdroute and corresponding security toggles in Room Context.
- feat(embed): implemented isolated, iframe-friendly