((resolve, reject) => {
+ const handler = (msg: any) => {
+ if (msg.type === 'notification-sent') {
+ this.ws!.removeEventListener('message', handler);
+ resolve();
+ }
+ };
+
+ this.ws!.addEventListener('message', (event) => {
+ handler(JSON.parse(event.data));
+ });
+
+ this.ws.send(JSON.stringify({
+ type: 'send-notification',
+ targetUserId,
+ type,
+ data
+ }));
+ });
+ }
+
+ async markAsRead(notificationId: string) {
+ if (!this.ws || !this.isConnected) return;
+
+ this.ws.send(JSON.stringify({
+ type: 'mark-read',
+ notificationId
+ }));
+ }
+
+ async deleteNotification(notificationId: string) {
+ if (!this.ws || !this.isConnected) return;
+
+ this.ws.send(JSON.stringify({
+ type: 'delete-notification',
+ notificationId
+ }));
+ }
+
+ getNotifications(): Notification[] {
+ return Array.from(this.notifications.values())
+ .sort((a, b) => b.createdAt.getTime() - a.createdAt.getTime());
+ }
+
+ getUnreadCount(): number {
+ return Array.from(this.notifications.values())
+ .filter(n => !n.read).length;
+ }
+
+ private showToast(notification: Notification) {
+ // Emit event for UI to show toast
+ this.emit('show-toast', notification);
+ }
+
+ destroy() {
+ if (this.reconnectInterval) {
+ clearTimeout(this.reconnectInterval);
+ }
+
+ if (this.ws) {
+ this.ws.close();
+ this.ws = null;
+ }
+ }
+}
+```
+
+**File: `packages/noodl-editor/src/editor/src/components/NotificationToast.tsx`**
+
+```typescript
+import React, { useEffect, useState } from 'react';
+import { Notification } from '../services/NotificationManager';
+
+interface NotificationToastProps {
+ notification: Notification;
+ onAction: (action: string) => void;
+ onDismiss: () => void;
+}
+
+export function NotificationToast({
+ notification,
+ onAction,
+ onDismiss
+}: NotificationToastProps) {
+ const [isVisible, = useState(true);
+
+ useEffect(() => {
+ // Auto-dismiss after 10 seconds
+ const timeout = setTimeout(() => {
+ onDismiss();
+ }, 10000);
+
+ return () => clearTimeout(timeout);
+ }, [onDismiss]);
+
+ if (!isVisible) return null;
+
+ return (
+
+
+ {getIconForType(notification.type)}
+ {notification.title}
+
+
+
+
+
{notification.message}
+
+
+ {notification.actions && notification.actions.length > 0 && (
+
+ {notification.actions.map(action => (
+
+ ))}
+
+ )}
+
+ );
+}
+
+function getIconForType(type: Notification['type']): string {
+ switch (type) {
+ case 'invite': return '👥';
+ case 'mention': return '@';
+ case 'thread': return '💬';
+ case 'session': return '🎮';
+ case 'component': return '📦';
+ case 'system': return 'ℹ️';
+ default: return '🔔';
+ }
+}
+```
+
+### Implementation Tasks
+
+- [ ] Implement `NotificationManager` service
+- [ ] Connect to notification server on app start
+- [ ] Implement notification parsing and storage
+- [ ] Implement toast notification UI component
+- [ ] Add notification badge to launcher/editor
+- [ ] Add notification center panel
+- [ ] Implement mark as read functionality
+- [ ] Implement delete functionality
+- [ ] Add notification actions (join, view, etc.)
+- [ ] Persist notification state locally
+- [ ] Add notification sound (optional)
+- [ ] Add desktop notifications (Electron)
+
+### Verification Steps
+
+- [ ] Notifications persist across sessions
+- [ ] Toast appears when notification received
+- [ ] Can mark notifications as read
+- [ ] Can delete notifications
+- [ ] Unread count displays correctly
+- [ ] Actions trigger correct behavior
+- [ ] Desktop notifications work (Electron)
+- [ ] Reconnects after connection loss
+
+---
+
+*Due to character limits, I'll continue with GIT-9, GIT-10, and GIT-11 in a summary format. Would you like me to create a second file with the remaining tasks?*
+
+---
+
+## Summary of Remaining Tasks
+
+### GIT-9: Community Tab UI/UX (80-100 hours)
+- Browse communities (official + user-added)
+- Discover public collaboration sessions
+- Component library browser
+- Tutorial and showcase feeds
+- Job board integration
+- Discussion thread viewer
+
+### GIT-10: Session Discovery & Joining (50-70 hours)
+- Public session list
+- Join via room ID/link
+- Session details preview
+- Quick join flow
+- Session history
+- Favorites/bookmarks
+
+### GIT-11: Integration & Polish (61-82 hours)
+- End-to-end testing
+- Performance optimization
+- Documentation
+- Demo videos
+- Marketing materials
+- Server deployment
+- Monitor and analytics
+
+**Total Series Hours: 431-572 hours**
diff --git a/dev-docs/tasks/phase-3-editor-ux-overhaul/TASK-002B-github-advanced-integration/GIT-5-to-GIT-11-Part-2-Community-UI-Integration.md b/dev-docs/tasks/phase-3-editor-ux-overhaul/TASK-002B-github-advanced-integration/GIT-5-to-GIT-11-Part-2-Community-UI-Integration.md
new file mode 100644
index 0000000..db9e30c
--- /dev/null
+++ b/dev-docs/tasks/phase-3-editor-ux-overhaul/TASK-002B-github-advanced-integration/GIT-5-to-GIT-11-Part-2-Community-UI-Integration.md
@@ -0,0 +1,1691 @@
+# Live Collaboration & Multi-Community System - Part 2
+## Task Documentation: GIT-9 through GIT-11
+
+This is a continuation of the Live Collaboration & Multi-Community System task documentation.
+
+---
+
+## GIT-9: Community Tab UI/UX
+
+**Priority**: High
+**Estimated Hours**: 80-100
+**Dependencies**: GIT-5, GIT-7, GIT-8
+
+### Purpose
+
+Create the Community tab UI that serves as the central hub for all community features: browsing communities, discovering sessions, exploring components, viewing tutorials, and accessing discussions.
+
+### Technical Requirements
+
+#### 1. Community Tab Layout
+
+**File: `packages/noodl-editor/src/editor/src/views/panels/CommunityPanel/CommunityPanel.tsx`**
+
+```typescript
+import React, { useState, useEffect } from 'react';
+import { CommunityManager } from '../../../services/CommunityManager';
+import { CollaborationManager } from '../../../services/CollaborationManager';
+import { NotificationManager } from '../../../services/NotificationManager';
+
+interface CommunityPanelProps {
+ communityManager: CommunityManager;
+ collaborationManager: CollaborationManager;
+ notificationManager: NotificationManager;
+}
+
+export function CommunityPanel({
+ communityManager,
+ collaborationManager,
+ notificationManager
+}: CommunityPanelProps) {
+ const [activeTab, setActiveTab] = useState<'home' | 'sessions' | 'components' | 'learn' | 'discuss' | 'jobs'>('home');
+ const [activeCommunity, setActiveCommunity] = useState(communityManager.getActiveCommunity());
+ const [communities, setCommunities] = useState(communityManager.getCommunities());
+
+ useEffect(() => {
+ const handleCommunityChanged = (community: any) => {
+ setActiveCommunity(community);
+ };
+
+ const handleCommunitiesUpdated = () => {
+ setCommunities(communityManager.getCommunities());
+ };
+
+ communityManager.on('active-community-changed', handleCommunityChanged);
+ communityManager.on('community-added', handleCommunitiesUpdated);
+ communityManager.on('community-removed', handleCommunitiesUpdated);
+
+ return () => {
+ communityManager.off('active-community-changed', handleCommunityChanged);
+ communityManager.off('community-added', handleCommunitiesUpdated);
+ communityManager.off('community-removed', handleCommunitiesUpdated);
+ };
+ }, [communityManager]);
+
+ return (
+
+
communityManager.setActiveCommunity(id)}
+ onAddCommunity={() => showAddCommunityDialog()}
+ />
+
+
+ setActiveTab('home')}
+ />
+ setActiveTab('sessions')}
+ />
+ setActiveTab('components')}
+ />
+ setActiveTab('learn')}
+ />
+ setActiveTab('discuss')}
+ />
+ setActiveTab('jobs')}
+ />
+
+
+
+ {activeTab === 'home' && (
+
+ )}
+ {activeTab === 'sessions' && (
+
+ )}
+ {activeTab === 'components' && (
+
+ )}
+ {activeTab === 'learn' && (
+
+ )}
+ {activeTab === 'discuss' && (
+
+ )}
+ {activeTab === 'jobs' && (
+
+ )}
+
+
+ );
+}
+```
+
+#### 2. Home View (Featured Content)
+
+**File: `CommunityPanel/views/HomeView.tsx`**
+
+```typescript
+import React, { useEffect, useState } from 'react';
+
+export function HomeView({ community, collaborationManager, notificationManager }) {
+ const [featured, setFeatured] = useState({
+ sessions: [],
+ components: [],
+ tutorials: [],
+ discussions: []
+ });
+
+ useEffect(() => {
+ loadFeaturedContent();
+ }, [community]);
+
+ async function loadFeaturedContent() {
+ // Fetch from community repository
+ const response = await fetch(
+ `https://raw.githubusercontent.com/${getCommunityRepo()}/main/featured.json`
+ );
+ const data = await response.json();
+ setFeatured(data);
+ }
+
+ return (
+
+
+
+
+ joinSession(sessionId)}
+ />
+
+
+
+
+
+
+
+
+
startNewSession()}
+ onShareComponent={() => shareComponent()}
+ onAskQuestion={() => startDiscussion()}
+ />
+
+ );
+}
+
+function WelcomeBanner({ community }) {
+ return (
+
+

+
{community.name}
+
{community.description}
+
+
+
+
+
+
+
+ );
+}
+
+function ActiveSessionsList({ sessions, onJoin }) {
+ if (sessions.length === 0) {
+ return ;
+ }
+
+ return (
+
+ {sessions.map(session => (
+ onJoin(session.id)}
+ />
+ ))}
+
+ );
+}
+
+function SessionCard({ session, onJoin }) {
+ return (
+
+
+
+
+
{session.host.name}
+
+
+
+
+
{session.title}
+
{session.description}
+
+
+ 👥 {session.participants.length}/{session.maxParticipants}
+ 🕐 {formatDuration(session.duration)}
+ {session.audioEnabled && 🎤 Audio}
+ {session.videoEnabled && 📹 Video}
+
+
+
+
+ );
+}
+
+function QuickActions({ onStartSession, onShareComponent, onAskQuestion }) {
+ return (
+
+ );
+}
+```
+
+#### 3. Sessions View (Collaboration Discovery)
+
+**File: `CommunityPanel/views/SessionsView.tsx`**
+
+```typescript
+import React, { useState, useEffect } from 'react';
+
+export function SessionsView({ community, collaborationManager }) {
+ const [view, setView] = useState<'browse' | 'create' | 'join'>('browse');
+ const [sessions, setSessions] = useState([]);
+ const [filter, setFilter] = useState({
+ status: 'all', // 'live', 'scheduled', 'all'
+ hasAudio: false,
+ hasSlots: false
+ });
+
+ useEffect(() => {
+ loadSessions();
+ }, [community, filter]);
+
+ async function loadSessions() {
+ // Fetch from community's collaboration/public-sessions.json
+ const response = await fetch(
+ `https://raw.githubusercontent.com/${getCommunityRepo()}/main/collaboration/public-sessions.json`
+ );
+ const data = await response.json();
+ setSessions(filterSessions(data, filter));
+ }
+
+ return (
+
+
+
Collaboration Sessions
+
+
+
+
+
+
+ {view === 'browse' && (
+ <>
+
+
+
+ {sessions.length === 0 ? (
+ setView('create')
+ }}
+ />
+ ) : (
+ sessions.map(session => (
+ joinSession(session.roomId)}
+ />
+ ))
+ )}
+
+ >
+ )}
+
+ {view === 'create' && (
+
setView('browse')}
+ onCreate={(session) => {
+ createSession(session);
+ setView('browse');
+ }}
+ />
+ )}
+
+ {view === 'join' && (
+ setView('browse')}
+ onJoin={(roomId) => {
+ joinSession(roomId);
+ setView('browse');
+ }}
+ />
+ )}
+
+ );
+}
+
+function SessionFilters({ filter, onChange }) {
+ return (
+
+
+ onChange({ ...filter, status: 'all' })}
+ />
+ onChange({ ...filter, status: 'live' })}
+ />
+ onChange({ ...filter, status: 'scheduled' })}
+ />
+
+
+
+ onChange({ ...filter, hasAudio: checked })}
+ />
+ onChange({ ...filter, hasSlots: checked })}
+ />
+
+
+ );
+}
+
+function CreateSessionDialog({ onCancel, onCreate }) {
+ const [form, setForm] = useState({
+ title: '',
+ description: '',
+ isPublic: true,
+ maxParticipants: 10,
+ audioEnabled: true,
+ videoEnabled: false,
+ projectId: window.ProjectModel?.id || ''
+ });
+
+ return (
+
+ );
+}
+
+function JoinSessionDialog({ onCancel, onJoin }) {
+ const [roomId, setRoomId] = useState('');
+
+ return (
+
+ );
+}
+```
+
+#### 4. Components View
+
+**File: `CommunityPanel/views/ComponentsView.tsx`**
+
+```typescript
+import React, { useState, useEffect } from 'react';
+
+export function ComponentsView({ community }) {
+ const [components, setComponents] = useState([]);
+ const [search, setSearch] = useState('');
+ const [category, setCategory] = useState('all');
+ const [sort, setSort] = useState<'recent' | 'popular' | 'name'>('popular');
+
+ useEffect(() => {
+ loadComponents();
+ }, [community, search, category, sort]);
+
+ async function loadComponents() {
+ // Fetch from community's components/registry.json
+ const response = await fetch(
+ `https://raw.githubusercontent.com/${getCommunityRepo()}/main/components/registry.json`
+ );
+ const data = await response.json();
+ setComponents(filterAndSort(data, search, category, sort));
+ }
+
+ return (
+
+
+
Component Library
+
+
+
+
+
+
+
+
+
+
+
+
+ {components.map(component => (
+ installComponent(component)}
+ onPreview={() => previewComponent(component)}
+ />
+ ))}
+
+
+ );
+}
+
+function ComponentCard({ component, onInstall, onPreview }) {
+ return (
+
+
+ {component.screenshot ? (
+

+ ) : (
+
{component.icon || '📦'}
+ )}
+
+
+
+
{component.name}
+
{component.description}
+
+
+
+
{component.author.name}
+
•
+
⭐ {component.stars}
+
•
+
📥 {component.downloads}
+
+
+
+ {component.tags?.map(tag => (
+ {tag}
+ ))}
+
+
+
+
+
+
+
+
+ );
+}
+```
+
+#### 5. Learn View (Tutorials)
+
+**File: `CommunityPanel/views/LearnView.tsx`**
+
+```typescript
+import React, { useState, useEffect } from 'react';
+
+export function LearnView({ community }) {
+ const [tutorials, setTutorials] = useState([]);
+ const [level, setLevel] = useState<'all' | 'beginner' | 'intermediate' | 'advanced'>('all');
+ const [format, setFormat] = useState<'all' | 'video' | 'article' | 'interactive'>('all');
+
+ useEffect(() => {
+ loadTutorials();
+ }, [community, level, format]);
+
+ async function loadTutorials() {
+ // Fetch from community's tutorials/
+ const levels = level === 'all' ? ['beginner', 'intermediate', 'advanced'] : [level];
+ const allTutorials = [];
+
+ for (const lvl of levels) {
+ const response = await fetch(
+ `https://raw.githubusercontent.com/${getCommunityRepo()}/main/tutorials/${lvl}/index.json`
+ );
+ const data = await response.json();
+ allTutorials.push(...data);
+ }
+
+ setTutorials(filterTutorials(allTutorials, format));
+ }
+
+ return (
+
+
+
Learning Resources
+
+
+
+
+
+
+
+
+
+
+
+
+ {tutorials.map(tutorial => (
+ startTutorial(tutorial)}
+ />
+ ))}
+
+
+ );
+}
+
+function TutorialCard({ tutorial, onStart }) {
+ return (
+
+
+

+
{tutorial.duration}
+
{formatIcon(tutorial.format)}
+
+
+
+
+
+ {tutorial.level}
+
+
+
+
{tutorial.title}
+
{tutorial.description}
+
+
+
+
{tutorial.author.name}
+
•
+
{tutorial.publishedAt}
+
+
+
+
+
+ );
+}
+```
+
+#### 6. Discuss View (GitHub Discussions)
+
+**File: `CommunityPanel/views/DiscussView.tsx`**
+
+```typescript
+import React, { useState, useEffect } from 'react';
+import { Octokit } from '@octokit/rest';
+
+export function DiscussView({ community }) {
+ const [discussions, setDiscussions] = useState([]);
+ const [category, setCategory] = useState('all');
+ const [sort, setSort] = useState<'recent' | 'top' | 'unanswered'>('recent');
+
+ useEffect(() => {
+ loadDiscussions();
+ }, [community, category, sort]);
+
+ async function loadDiscussions() {
+ const octokit = new Octokit({
+ auth: window.githubAuth.token
+ });
+
+ // Fetch GitHub Discussions
+ const [owner, repo] = community.repository.split('/').slice(-2);
+
+ const { data } = await octokit.graphql(`
+ query {
+ repository(owner: "${owner}", name: "${repo}") {
+ discussions(first: 50, orderBy: { field: UPDATED_AT, direction: DESC }) {
+ nodes {
+ id
+ title
+ body
+ createdAt
+ updatedAt
+ category {
+ name
+ }
+ author {
+ login
+ avatarUrl
+ }
+ comments {
+ totalCount
+ }
+ reactions {
+ totalCount
+ }
+ url
+ }
+ }
+ }
+ }
+ `);
+
+ setDiscussions(filterDiscussions(data.repository.discussions.nodes, category, sort));
+ }
+
+ return (
+
+
+
Community Discussions
+
+
+
+
+
+
+
+
+
+
+ {discussions.map(discussion => (
+ openDiscussion(discussion.url)}
+ />
+ ))}
+
+
+ );
+}
+
+function DiscussionItem({ discussion, onClick }) {
+ return (
+
+
+
{discussion.title}
+
+ {truncate(discussion.body, 150)}
+
+
+
+
+
{discussion.author.login}
+
asked in {discussion.category.name}
+
•
+
{formatRelativeTime(discussion.createdAt)}
+
+
+
+
+
+
+
+
+ );
+}
+```
+
+#### 7. Jobs View
+
+**File: `CommunityPanel/views/JobsView.tsx`**
+
+```typescript
+import React, { useState, useEffect } from 'react';
+
+export function JobsView({ community }) {
+ const [jobs, setJobs] = useState([]);
+ const [filter, setFilter] = useState({
+ type: 'all', // 'full-time', 'contract', 'freelance'
+ remote: false,
+ experience: 'all' // 'junior', 'mid', 'senior'
+ });
+
+ useEffect(() => {
+ loadJobs();
+ }, [community, filter]);
+
+ async function loadJobs() {
+ // Fetch from community's jobs/listings.json
+ const response = await fetch(
+ `https://raw.githubusercontent.com/${getCommunityRepo()}/main/jobs/listings.json`
+ );
+ const data = await response.json();
+ setJobs(filterJobs(data, filter));
+ }
+
+ return (
+
+
+
Job Board
+
+
+
+
+
+
+ {jobs.length === 0 ? (
+
+ ) : (
+ jobs.map(job => (
+ applyToJob(job)}
+ />
+ ))
+ )}
+
+
+ );
+}
+
+function JobCard({ job, onApply }) {
+ return (
+
+
+

+
+
{job.title}
+
{job.company.name}
+
+
+
+
{job.description}
+
+
+ {job.type}
+ {job.remote && 🌍 Remote}
+ {job.location}
+ {job.experience}
+
+
+
+ Posted {formatRelativeTime(job.postedAt)}
+ {job.salary && 💰 {job.salary}}
+
+
+
+
+ );
+}
+```
+
+### Implementation Tasks
+
+- [ ] Create `CommunityPanel` main component
+- [ ] Implement `HomeView` with featured content
+- [ ] Implement `SessionsView` with browse/create/join
+- [ ] Implement `ComponentsView` with search and filters
+- [ ] Implement `LearnView` with tutorials
+- [ ] Implement `DiscussView` with GitHub Discussions integration
+- [ ] Implement `JobsView` with job listings
+- [ ] Create all sub-components (cards, filters, dialogs)
+- [ ] Add loading states and skeletons
+- [ ] Add error handling and retry logic
+- [ ] Implement infinite scroll for long lists
+- [ ] Add keyboard navigation
+- [ ] Style all components with Nodegx theme
+- [ ] Add animations and transitions
+
+### Verification Steps
+
+- [ ] Community tab loads without errors
+- [ ] Can switch between communities
+- [ ] Featured content displays correctly
+- [ ] Can browse and join sessions
+- [ ] Can search and install components
+- [ ] Tutorials load from GitHub
+- [ ] Discussions integrate with GitHub
+- [ ] Job board displays listings
+- [ ] All filters work correctly
+- [ ] UI is responsive and performant
+
+---
+
+## GIT-10: Session Discovery & Joining
+
+**Priority**: High
+**Estimated Hours**: 50-70
+**Dependencies**: GIT-7, GIT-9
+
+### Purpose
+
+Streamline the session discovery and joining experience with deep linking, quick join flows, session previews, and favorites.
+
+### Technical Requirements
+
+#### 1. Deep Linking Support
+
+**File: `packages/noodl-editor/src/editor/src/utils/DeepLinkHandler.ts`**
+
+```typescript
+import { app } from 'electron';
+
+/**
+ * Handle nodegx:// protocol URLs
+ * Examples:
+ * - nodegx://session/abc123
+ * - nodegx://session/abc123?audio=true
+ * - nodegx://community/add?repo=user/repo
+ */
+
+export class DeepLinkHandler {
+ private handlers: Map void> = new Map();
+
+ constructor() {
+ this.registerDefaultHandlers();
+ this.setupProtocolHandler();
+ }
+
+ private registerDefaultHandlers() {
+ // Session joining
+ this.register('session', async (params) => {
+ const { sessionId, audio, video } = params;
+
+ await window.collaborationManager.joinSession({
+ roomId: sessionId,
+ audioEnabled: audio === 'true',
+ videoEnabled: video === 'true'
+ });
+ });
+
+ // Community adding
+ this.register('community/add', async (params) => {
+ const { repo } = params;
+ const url = `https://github.com/${repo}`;
+
+ await window.communityManager.addCommunity(url);
+ });
+
+ // Component installation
+ this.register('component/install', async (params) => {
+ const { repo, component } = params;
+
+ await window.componentManager.install(repo, component);
+ });
+ }
+
+ private setupProtocolHandler() {
+ if (process.platform !== 'darwin') {
+ app.setAsDefaultProtocolClient('nodegx');
+ }
+
+ // Handle URLs when app is already running
+ app.on('open-url', (event, url) => {
+ event.preventDefault();
+ this.handleUrl(url);
+ });
+
+ // Handle URLs when app starts
+ const url = process.argv.find(arg => arg.startsWith('nodegx://'));
+ if (url) {
+ this.handleUrl(url);
+ }
+ }
+
+ handleUrl(url: string) {
+ const parsed = new URL(url);
+ const path = parsed.hostname + parsed.pathname;
+ const params = Object.fromEntries(parsed.searchParams);
+
+ const handler = this.handlers.get(path);
+ if (handler) {
+ handler(params);
+ } else {
+ console.warn(`No handler for deep link: ${path}`);
+ }
+ }
+
+ register(path: string, handler: (params: any) => void) {
+ this.handlers.set(path, handler);
+ }
+
+ generateLink(path: string, params?: Record): string {
+ const url = new URL(`nodegx://${path}`);
+ if (params) {
+ Object.entries(params).forEach(([key, value]) => {
+ url.searchParams.set(key, value);
+ });
+ }
+ return url.toString();
+ }
+}
+```
+
+#### 2. Session Preview
+
+**File: `packages/noodl-editor/src/editor/src/components/SessionPreview.tsx`**
+
+```typescript
+import React, { useEffect, useState } from 'react';
+
+interface SessionPreviewProps {
+ roomId: string;
+ onJoin: () => void;
+ onCancel: () => void;
+}
+
+export function SessionPreview({ roomId, onJoin, onCancel }: SessionPreviewProps) {
+ const [session, setSession] = useState(null);
+ const [loading, setLoading] = useState(true);
+
+ useEffect(() => {
+ loadSessionInfo();
+ }, [roomId]);
+
+ async function loadSessionInfo() {
+ try {
+ // Fetch session metadata from signaling server or community repo
+ const response = await fetch(
+ `https://signal.nodegx.com/session/${roomId}/info`
+ );
+ const data = await response.json();
+ setSession(data);
+ } catch (err) {
+ console.error('Failed to load session info:', err);
+ } finally {
+ setLoading(false);
+ }
+ }
+
+ if (loading) {
+ return ;
+ }
+
+ if (!session) {
+ return (
+
+ );
+ }
+
+ return (
+
+ );
+}
+```
+
+#### 3. Quick Join Widget
+
+**File: `packages/noodl-editor/src/editor/src/components/QuickJoinWidget.tsx`**
+
+```typescript
+import React, { useState } from 'react';
+
+/**
+ * Floating widget for quick session joining
+ * Shows when user receives invite or pastes session link
+ */
+export function QuickJoinWidget({ invitation, onJoin, onDismiss }) {
+ const [minimized, setMinimized] = useState(false);
+
+ if (minimized) {
+ return (
+ setMinimized(false)}>
+ 👥 Session Invite
+ {invitation.from}
+
+ );
+ }
+
+ return (
+
+
+
Collaboration Invite
+
+ setMinimized(true)} />
+
+
+
+
+
+
+
+
{invitation.from} invited you to collaborate
+
+
+
{invitation.sessionTitle}
+ {invitation.sessionDescription && (
+
{invitation.sessionDescription}
+ )}
+
+
+ 👥 {invitation.participantCount} participants
+ {invitation.audioEnabled && 🎤 Audio}
+
+
+
+
+
+
+
+
+ );
+}
+```
+
+#### 4. Session History & Favorites
+
+**File: `packages/noodl-editor/src/editor/src/services/SessionHistoryManager.ts`**
+
+```typescript
+interface SessionHistoryEntry {
+ sessionId: string;
+ roomId: string;
+ title: string;
+ host: {
+ userId: string;
+ name: string;
+ avatar?: string;
+ };
+ joinedAt: Date;
+ leftAt?: Date;
+ duration: number;
+ isFavorite: boolean;
+}
+
+export class SessionHistoryManager {
+ private history: SessionHistoryEntry[] = [];
+ private maxHistory = 50;
+
+ constructor() {
+ this.load();
+ }
+
+ addEntry(session: any) {
+ const entry: SessionHistoryEntry = {
+ sessionId: session.id,
+ roomId: session.roomId,
+ title: session.title,
+ host: session.host,
+ joinedAt: new Date(),
+ duration: 0,
+ isFavorite: false
+ };
+
+ this.history.unshift(entry);
+
+ // Keep only most recent
+ if (this.history.length > this.maxHistory) {
+ this.history = this.history.slice(0, this.maxHistory);
+ }
+
+ this.save();
+ }
+
+ updateEntry(sessionId: string, updates: Partial) {
+ const entry = this.history.find(e => e.sessionId === sessionId);
+ if (entry) {
+ Object.assign(entry, updates);
+ this.save();
+ }
+ }
+
+ toggleFavorite(sessionId: string) {
+ const entry = this.history.find(e => e.sessionId === sessionId);
+ if (entry) {
+ entry.isFavorite = !entry.isFavorite;
+ this.save();
+ }
+ }
+
+ getHistory(): SessionHistoryEntry[] {
+ return this.history;
+ }
+
+ getFavorites(): SessionHistoryEntry[] {
+ return this.history.filter(e => e.isFavorite);
+ }
+
+ private load() {
+ const saved = localStorage.getItem('nodegx-session-history');
+ if (saved) {
+ this.history = JSON.parse(saved);
+ }
+ }
+
+ private save() {
+ localStorage.setItem('nodegx-session-history', JSON.stringify(this.history));
+ }
+}
+```
+
+### Implementation Tasks
+
+- [ ] Implement deep link handler for `nodegx://` protocol
+- [ ] Register protocol handler in Electron
+- [ ] Create session preview dialog
+- [ ] Implement quick join widget
+- [ ] Create session history manager
+- [ ] Add favorites functionality
+- [ ] Implement session info API endpoint on signaling server
+- [ ] Add "Copy Link" button to active sessions
+- [ ] Add "Recent Sessions" panel
+- [ ] Add "Favorite Sessions" panel
+- [ ] Implement auto-rejoin for favorite sessions
+- [ ] Add session notifications to system tray
+
+### Verification Steps
+
+- [ ] `nodegx://` links open the app
+- [ ] Session preview loads correctly
+- [ ] Can join session from deep link
+- [ ] Quick join widget appears for invites
+- [ ] Session history saves correctly
+- [ ] Can favorite sessions
+- [ ] Can rejoin from history
+- [ ] Copy link generates correct URL
+
+---
+
+## GIT-11: Integration & Polish
+
+**Priority**: High
+**Estimated Hours**: 61-82
+**Dependencies**: All previous tasks
+
+### Purpose
+
+Final integration, testing, documentation, and marketing preparation for the live collaboration and multi-community system.
+
+### Implementation Tasks
+
+#### 1. End-to-End Testing (20-25 hours)
+
+- [ ] Create comprehensive test plan
+- [ ] Test session creation and joining
+- [ ] Test WebRTC connection establishment
+- [ ] Test WebSocket fallback scenarios
+- [ ] Test audio/video functionality
+- [ ] Test cursor and selection sync
+- [ ] Test node editing collaboration
+- [ ] Test disconnection and reconnection
+- [ ] Test notification delivery
+- [ ] Test community switching
+- [ ] Test deep link handling
+- [ ] Test GitHub integration
+- [ ] Test with multiple simultaneous users
+- [ ] Test with poor network conditions
+- [ ] Test with firewall restrictions
+
+#### 2. Performance Optimization (15-20 hours)
+
+- [ ] Profile WebRTC data channel usage
+- [ ] Optimize Yjs document size
+- [ ] Implement cursor position throttling
+- [ ] Add viewport culling for remote cursors
+- [ ] Optimize GitHub API calls (caching)
+- [ ] Lazy load community content
+- [ ] Implement virtual scrolling for lists
+- [ ] Reduce bundle size (code splitting)
+- [ ] Optimize WebSocket message frequency
+- [ ] Add connection quality indicators
+
+#### 3. Documentation (12-15 hours)
+
+- [ ] Write user guide for collaboration
+- [ ] Create community setup guide
+- [ ] Document self-hosting instructions
+- [ ] Create API documentation for servers
+- [ ] Write troubleshooting guide
+- [ ] Create video tutorials
+- [ ] Document network requirements
+- [ ] Create FAQ section
+- [ ] Write privacy policy updates
+- [ ] Document data retention policies
+
+#### 4. Marketing Materials (8-12 hours)
+
+- [ ] Create demo video (3-5 minutes)
+- [ ] Create feature comparison matrix
+- [ ] Design social media graphics
+- [ ] Write blog post announcement
+- [ ] Create press kit
+- [ ] Design landing page
+- [ ] Create case studies
+- [ ] Prepare launch email
+
+#### 5. Server Deployment (6-10 hours)
+
+- [ ] Deploy signaling server to production
+- [ ] Deploy sync server to production
+- [ ] Deploy notification server to production
+- [ ] Configure TURN server (Coturn)
+- [ ] Set up monitoring (Grafana/Prometheus)
+- [ ] Configure SSL certificates
+- [ ] Set up backup systems
+- [ ] Create deployment runbooks
+- [ ] Set up alerting
+- [ ] Load testing
+
+### Verification Steps
+
+- [ ] All automated tests pass
+- [ ] Manual test scenarios complete
+- [ ] Performance benchmarks met
+- [ ] Documentation is complete and accurate
+- [ ] Marketing materials are approved
+- [ ] Servers are deployed and healthy
+- [ ] Monitoring is active
+- [ ] Backup systems tested
+- [ ] Security audit passed
+- [ ] Privacy compliance verified
+
+### Launch Checklist
+
+- [ ] Feature flag enabled for beta users
+- [ ] Announcement blog post scheduled
+- [ ] Social media posts scheduled
+- [ ] Email to community drafted
+- [ ] Support team trained
+- [ ] Known issues documented
+- [ ] Rollback plan prepared
+- [ ] Success metrics defined
+- [ ] Analytics tracking enabled
+- [ ] Feedback collection system ready
+
+---
+
+## Additional Features & Ideas
+
+### Future Enhancements (Not in Current Scope)
+
+1. **Screen Sharing**
+ - Share entire screen or specific window
+ - Presenter mode with annotations
+ - Remote control (with permission)
+
+2. **Session Recording**
+ - Record collaboration sessions
+ - Replay with timeline scrubbing
+ - Export as video
+
+3. **Voice Commands**
+ - "Claude, create a button node"
+ - "Show me the login flow"
+ - Hands-free collaboration
+
+4. **AI Pair Programming**
+ - Claude Code integration in sessions
+ - Shared AI context
+ - Real-time code suggestions visible to all
+
+5. **Advanced Permissions**
+ - Read-only participants
+ - Moderator controls
+ - Private work areas in shared session
+
+6. **Session Scheduling**
+ - Calendar integration
+ - Recurring sessions
+ - Automated invites
+
+7. **Breakout Rooms**
+ - Split large sessions into groups
+ - Rotate between rooms
+ - Rejoin main session
+
+8. **Whiteboard Mode**
+ - Shared drawing canvas
+ - Sticky notes
+ - Mind mapping
+
+9. **Component Marketplace**
+ - Paid component listings
+ - Revenue sharing
+ - Quality ratings
+
+10. **Community Analytics**
+ - Session participation stats
+ - Component usage metrics
+ - Engagement leaderboards
+
+---
+
+## Success Metrics
+
+### Key Performance Indicators
+
+**Adoption Metrics:**
+- Number of communities created
+- Number of collaboration sessions started
+- Average session duration
+- Number of components shared
+- GitHub discussions activity
+
+**Technical Metrics:**
+- WebRTC connection success rate (target: >95%)
+- Average time to establish connection (target: <3s)
+- WebSocket fallback rate (target: <10%)
+- Notification delivery rate (target: >99%)
+- Server uptime (target: 99.9%)
+
+**User Satisfaction:**
+- Session completion rate (target: >80%)
+- Feature usage (audio, video, cursor sharing)
+- User retention (weekly active users)
+- Net Promoter Score (target: >50)
+
+---
+
+## Risk Mitigation
+
+### Technical Risks
+
+**WebRTC Connection Failures:**
+- Mitigation: Automatic WebSocket fallback
+- Mitigation: TURN server for relay
+- Mitigation: Clear error messages and troubleshooting
+
+**Server Scaling:**
+- Mitigation: Horizontal scaling architecture
+- Mitigation: Load balancing
+- Mitigation: Rate limiting
+
+**Data Privacy:**
+- Mitigation: End-to-end encryption for sensitive data
+- Mitigation: Clear privacy policies
+- Mitigation: User data controls
+
+**Network Performance:**
+- Mitigation: Adaptive quality (audio/video)
+- Mitigation: Bandwidth estimation
+- Mitigation: Connection quality indicators
+
+### Business Risks
+
+**Community Fragmentation:**
+- Mitigation: Make official community compelling
+- Mitigation: Cross-community component discovery
+- Mitigation: Federated features (future)
+
+**Moderation Challenges:**
+- Mitigation: Leverage GitHub's moderation tools
+- Mitigation: Community moderator system
+- Mitigation: Reporting mechanisms
+
+**Server Costs:**
+- Mitigation: Encourage self-hosting
+- Mitigation: P2P-first architecture
+- Mitigation: Tiered pricing for heavy users
+
+---
+
+## Conclusion
+
+This comprehensive task documentation covers the complete implementation of the Live Collaboration & Multi-Community System for Nodegx. The system transforms Nodegx into a collaborative platform while maintaining the BYOB philosophy through forkable communities and self-hosted infrastructure.
+
+**Key Highlights:**
+- 431-572 hours total development time
+- 7 major task groupings (GIT-5 through GIT-11)
+- Industry-first live collaboration for visual programming
+- Multi-community architecture
+- Persistent notification system
+- Complete self-hosting capability
+
+This positions Nodegx as the most advanced open-source visual development platform with collaboration features that rival or exceed commercial tools like Figma, while maintaining user ownership and freedom.
diff --git a/dev-docs/tasks/phase-3-editor-ux-overhaul/TASK-002B-github-advanced-integration/GIT-INTEGRATION-STRATEGY.md b/dev-docs/tasks/phase-3-editor-ux-overhaul/TASK-002B-github-advanced-integration/GIT-INTEGRATION-STRATEGY.md
new file mode 100644
index 0000000..c6404ad
--- /dev/null
+++ b/dev-docs/tasks/phase-3-editor-ux-overhaul/TASK-002B-github-advanced-integration/GIT-INTEGRATION-STRATEGY.md
@@ -0,0 +1,292 @@
+# VersionControlPanel + GitHub Integration Strategy
+
+## Overview
+
+This document outlines the strategy for integrating the new GitHub features (Issues, PRs, OAuth) with the existing VersionControlPanel. The goal is to **unify** rather than duplicate, leveraging the excellent existing git functionality.
+
+---
+
+## Key Finding: VersionControlPanel is Already React ✅
+
+The existing VersionControlPanel is **100% React** with modern patterns:
+
+- React functional components with hooks
+- Context API (`VersionControlContext`)
+- TypeScript throughout
+- Uses `@noodl-core-ui` design system
+- No jQuery (except PopupLayer which is a separate system)
+
+**This means integration is straightforward - no rewrite needed!**
+
+---
+
+## What Already Exists
+
+### VersionControlPanel (`packages/noodl-editor/src/editor/src/views/panels/VersionControlPanel/`)
+
+| Component | Description | Status |
+| ----------------------- | -------------------------------------- | ---------- |
+| `LocalChanges.tsx` | View uncommitted changes | ✅ Working |
+| `History.tsx` | Browse commits | ✅ Working |
+| `HistoryCommitDiff.tsx` | Click commit → see visual diff | ✅ Working |
+| `CommitChangesDiff.tsx` | Diff logic for commits | ✅ Working |
+| `DiffList.tsx` | Visual diff renderer (green/red nodes) | ✅ Working |
+| `BranchList.tsx` | Manage branches | ✅ Working |
+| `BranchMerge.tsx` | Merge branches | ✅ Working |
+| `MergeConflicts.tsx` | Resolve conflicts | ✅ Working |
+| `Stashes.tsx` | Git stash support | ✅ Working |
+| `GitProviderPopout.tsx` | GitHub/Git credentials | ✅ Working |
+| `GitStatusButton.tsx` | Push/pull status | ✅ Working |
+
+### VersionControlContext
+
+Provides git state to all components:
+
+```typescript
+const {
+ git, // Git client instance
+ activeTabId, // Current tab
+ setActiveTabId, // Tab switcher
+ localChangesCount, // Number of uncommitted changes
+ branchStatus, // Current branch state
+ fetch, // Fetch operations
+ updateLocalDiff // Refresh diff
+} = useVersionControlContext();
+```
+
+### GitHubPanel (New - from GIT-004 work)
+
+| Component | Description | Status |
+| -------------------- | ---------------------- | ---------- |
+| `GitHubPanel.tsx` | Container panel | ✅ Working |
+| `useIssues.ts` | Fetch GitHub issues | ✅ Working |
+| `usePullRequests.ts` | Fetch GitHub PRs | ✅ Working |
+| `ConnectToGitHub/` | GitHub connection flow | ✅ Working |
+| `SyncToolbar.tsx` | Push/pull/sync status | ✅ Working |
+| `GitHubClient.ts` | GitHub API wrapper | ✅ Working |
+
+---
+
+## Integration Strategy
+
+### Option A: Extend VersionControlPanel (Recommended) ✅
+
+Add GitHub-specific tabs to the existing panel:
+
+```
+┌──────────────────────────────────────────────────┐
+│ Version Control [⚙️] [🔗] │
+├──────────────────────────────────────────────────┤
+│ [GitStatusButton - push/pull status] │
+│ [BranchStatusButton - current branch] │
+├──────────────────────────────────────────────────┤
+│ [Changes] [History] [Issues] [PRs] ← NEW TABS │
+├──────────────────────────────────────────────────┤
+│ (Tab content - all existing components work) │
+└──────────────────────────────────────────────────┘
+```
+
+**Pros:**
+
+- Leverages ALL existing functionality
+- Single unified panel
+- Visual diff system already works
+- Less code to maintain
+- Familiar UX for existing users
+
+---
+
+## Implementation Plan
+
+### Phase 1: Add GitHub Context (2-3 hours)
+
+Create a GitHub-specific context that can be used alongside VersionControlContext:
+
+```typescript
+// New: GitHubContext.tsx in VersionControlPanel/context/
+interface GitHubContextValue {
+ isGitHubConnected: boolean;
+ issues: Issue[];
+ pullRequests: PullRequest[];
+ issuesLoading: boolean;
+ prsLoading: boolean;
+ refreshIssues: () => void;
+ refreshPRs: () => void;
+}
+
+export function GitHubProvider({ children, git }) {
+ // Use existing hooks from GitHubPanel
+ const { issues, loading: issuesLoading, refetch: refreshIssues } = useIssues(repoOwner, repoName);
+ const { pullRequests, loading: prsLoading, refetch: refreshPRs } = usePullRequests(repoOwner, repoName);
+
+ return (
+
+ {children}
+
+ );
+}
+```
+
+### Phase 2: Add Issues Tab (3-4 hours)
+
+Move/refactor components from GitHubPanel:
+
+```
+VersionControlPanel/
+├── components/
+│ ├── IssuesTab/ ← NEW (from GitHubPanel)
+│ │ ├── IssuesList.tsx
+│ │ ├── IssueItem.tsx
+│ │ └── IssueDetail.tsx
+```
+
+Wire into tabs:
+
+```typescript
+// In VersionControlPanel.tsx
+ },
+ { id: 'history', label: 'History', content: },
+ // NEW:
+ { id: 'issues', label: `Issues (${issues.length})`, content: , disabled: !isGitHubConnected },
+ { id: 'prs', label: `PRs (${prs.length})`, content: , disabled: !isGitHubConnected }
+ ]}
+/>
+```
+
+### Phase 3: Add PRs Tab (3-4 hours)
+
+Similar to Issues tab:
+
+```
+VersionControlPanel/
+├── components/
+│ ├── PullRequestsTab/ ← NEW (from GitHubPanel)
+│ │ ├── PRsList.tsx
+│ │ ├── PRItem.tsx
+│ │ └── PRDetail.tsx
+```
+
+### Phase 4: Enhance GitProviderPopout (2-3 hours)
+
+Upgrade existing popout with OAuth flow:
+
+```typescript
+// GitProviderPopout.tsx - enhance with OAuth
+import { GitHubOAuthService } from '@noodl-services/GitHubOAuthService';
+
+// Add "Connect with GitHub" button that triggers OAuth
+// Show connected status
+// Show authenticated user info
+```
+
+### Phase 5: Deprecate Separate GitHubPanel (1-2 hours)
+
+- Remove GitHubPanel from sidebar registration
+- Keep components for reuse in VersionControlPanel
+- Update any references
+
+---
+
+## Files to Modify
+
+### VersionControlPanel (Main Changes)
+
+```
+packages/noodl-editor/src/editor/src/views/panels/VersionControlPanel/
+├── VersionControlPanel.tsx # Add new tabs
+├── context/
+│ ├── index.tsx # Add GitHubProvider
+│ └── GitHubContext.tsx # NEW
+├── components/
+│ ├── IssuesTab/ # NEW (move from GitHubPanel)
+│ ├── PullRequestsTab/ # NEW (move from GitHubPanel)
+│ └── GitProviderPopout/
+│ └── GitProviderPopout.tsx # Enhance with OAuth
+```
+
+### Move from GitHubPanel
+
+```
+FROM: packages/noodl-editor/src/editor/src/views/panels/GitHubPanel/
+ components/IssuesTab/ → VersionControlPanel/components/IssuesTab/
+ components/PullRequestsTab/ → VersionControlPanel/components/PullRequestsTab/
+ hooks/useIssues.ts → VersionControlPanel/hooks/useIssues.ts
+ hooks/usePullRequests.ts → VersionControlPanel/hooks/usePullRequests.ts
+```
+
+### Services (Keep as-is)
+
+```
+packages/noodl-editor/src/editor/src/services/github/
+├── GitHubClient.ts # Keep - used by hooks
+├── GitHubTypes.ts # Keep - type definitions
+├── GitHubOAuthService.ts # Keep - OAuth flow
+```
+
+---
+
+## What Stays Separate
+
+### GitHubPanel Features That Don't Move
+
+Some features make more sense in their current location:
+
+- **Launcher "Clone from GitHub"** → Stay in Launcher (TASK-002C)
+- **Connect/Create Repo flows** → Can be triggered from VersionControlPanel but may open modals
+
+---
+
+## Visual Diff System - Already Working!
+
+The visual diff magic you mentioned already works perfectly. When clicking a commit in History:
+
+1. `History.tsx` renders list of commits
+2. Click → `HistoryCommitDiff.tsx` renders
+3. `CommitChangesDiff.tsx` fetches the project.json diff
+4. `DiffList.tsx` renders:
+ - "Changed Components" section (click to see visual diff)
+ - "Changed Files" section
+ - "Changed Settings" section
+ - "Changed Styles" section
+5. `useShowComponentDiffDocument` opens the visual node graph diff
+
+**This all continues to work unchanged!**
+
+---
+
+## Benefits of This Approach
+
+1. **Single panel** for all version control + GitHub
+2. **Existing visual diffs** work unchanged
+3. **No rewrite** - just adding tabs
+4. **Shared context** between git and GitHub features
+5. **Familiar UX** - users already know VersionControlPanel
+6. **Less code** to maintain than two separate panels
+
+---
+
+## Estimated Effort
+
+| Phase | Task | Hours |
+| --------- | ------------------------- | --------------- |
+| 1 | Add GitHub Context | 2-3 |
+| 2 | Add Issues Tab | 3-4 |
+| 3 | Add PRs Tab | 3-4 |
+| 4 | Enhance GitProviderPopout | 2-3 |
+| 5 | Cleanup & Deprecate | 1-2 |
+| **Total** | | **11-16 hours** |
+
+This is significantly less than maintaining two separate panels!
+
+---
+
+## Future: Community Tab
+
+For the GIT-005-011 collaboration features, we might add a third panel:
+
+- **VersionControlPanel** → Git + GitHub (Issues, PRs)
+- **CommunityPanel** → Communities, Sessions, Components, Notifications
+
+Or integrate Community features as more tabs if it makes sense UX-wise.
diff --git a/dev-docs/tasks/phase-3-editor-ux-overhaul/TASK-002B-github-advanced-integration/README.md b/dev-docs/tasks/phase-3-editor-ux-overhaul/TASK-002B-github-advanced-integration/README.md
index 0810fcb..a0e38b6 100644
--- a/dev-docs/tasks/phase-3-editor-ux-overhaul/TASK-002B-github-advanced-integration/README.md
+++ b/dev-docs/tasks/phase-3-editor-ux-overhaul/TASK-002B-github-advanced-integration/README.md
@@ -1,15 +1,39 @@
-# GIT-004: GitHub Project Management Integration
+# TASK-002B: GitHub Advanced Integration
## Overview
-Transform Nodegex from a "coding tool with Git" into a **collaborative development hub** where teams can manage their entire project workflow without leaving the editor. This feature enables viewing, creating, and managing GitHub Issues, Pull Requests, and Discussions directly from both the Nodegex Editor and Dashboard.
+This task encompasses **two major feature sets**:
+
+### Part 1: GitHub Project Management (GIT-004A-F)
+
+Transform OpenNoodl from a "coding tool with Git" into a **collaborative development hub** where teams can manage their entire project workflow without leaving the editor.
**The killer feature**: Link GitHub issues directly to visual components, enabling unprecedented traceability between project management and implementation.
+**Effort:** 70-90 hours across 6 sub-tasks
+
+### Part 2: Live Collaboration & Multi-Community (GIT-005-011)
+
+Transform OpenNoodl into a **collaborative platform** with real-time multi-user editing (Google Docs for visual programming), multi-community support, and persistent notifications.
+
+**Effort:** 431-572 hours across 7 sub-tasks
+
+---
+
**Phase:** 3 (Dashboard UX & Collaboration)
**Priority:** HIGH (key differentiator)
-**Total Effort:** 70-90 hours across 6 sub-tasks
-**Risk:** Medium (OAuth complexity, GitHub API rate limits)
+**Total Effort:** 501-662 hours across 13 sub-tasks
+**Risk:** Medium-High (OAuth complexity, WebRTC, server infrastructure)
+
+---
+
+## Integration Strategy
+
+**Important:** We're extending the existing `VersionControlPanel` rather than creating a separate panel. The existing panel is already 100% React with full visual diff support (showing green nodes for additions, red for deletions).
+
+See **[GIT-INTEGRATION-STRATEGY.md](./GIT-INTEGRATION-STRATEGY.md)** for details.
+
+**Key insight:** The visual commit diff system already works perfectly - we just need to add GitHub-specific tabs (Issues, PRs) to the existing panel.
---
@@ -19,13 +43,13 @@ Transform Nodegex from a "coding tool with Git" into a **collaborative developme
No major low-code platform offers this level of GitHub integration:
-| Platform | Git Support | Issues/PRs | Component Linking |
-|----------|-------------|------------|-------------------|
-| Retool | ❌ | ❌ | ❌ |
-| Bubble | ❌ | ❌ | ❌ |
-| Webflow | Basic | ❌ | ❌ |
-| FlutterFlow | Basic | ❌ | ❌ |
-| **Nodegex** | ✅ Full | ✅ Full | ✅ **Unique** |
+| Platform | Git Support | Issues/PRs | Component Linking |
+| ----------- | ----------- | ---------- | ----------------- |
+| Retool | ❌ | ❌ | ❌ |
+| Bubble | ❌ | ❌ | ❌ |
+| Webflow | Basic | ❌ | ❌ |
+| FlutterFlow | Basic | ❌ | ❌ |
+| **Nodegex** | ✅ Full | ✅ Full | ✅ **Unique** |
### Target Users
@@ -101,6 +125,7 @@ Overview widgets for project health and team awareness.
Upgrade from PAT-based authentication to full GitHub App OAuth flow, and create a reusable GitHub API client.
**Scope:**
+
- GitHub App registration guidance/documentation
- OAuth authorization flow in Electron
- Secure token storage (upgrade from current GitStore pattern)
@@ -108,6 +133,7 @@ Upgrade from PAT-based authentication to full GitHub App OAuth flow, and create
- Token refresh handling
**Files to Create:**
+
```
packages/noodl-editor/src/editor/src/services/github/
├── GitHubAuth.ts # OAuth flow handler
@@ -118,6 +144,7 @@ packages/noodl-editor/src/editor/src/services/github/
```
**Files to Modify:**
+
```
packages/noodl-editor/src/editor/src/views/panels/VersionControlPanel/
components/GitProviderPopout/GitProviderPopout.tsx
@@ -129,6 +156,7 @@ packages/noodl-git/src/git.ts
```
**Success Criteria:**
+
- [ ] User can authenticate via GitHub OAuth from editor
- [ ] Token stored securely and persists across sessions
- [ ] Token refresh works automatically
@@ -142,6 +170,7 @@ packages/noodl-git/src/git.ts
View GitHub issues for the connected repository.
**Scope:**
+
- New sidebar panel: GitHubPanel with tabbed interface
- Issues list with filtering (open/closed, labels, assignees)
- Issue detail view (body, comments, labels, assignees)
@@ -150,6 +179,7 @@ View GitHub issues for the connected repository.
- Pagination for large issue lists
**Files to Create:**
+
```
packages/noodl-editor/src/editor/src/views/panels/GitHubPanel/
├── GitHubPanel.tsx
@@ -169,6 +199,7 @@ packages/noodl-editor/src/editor/src/views/panels/GitHubPanel/
```
**Files to Modify:**
+
```
packages/noodl-editor/src/editor/src/router.setup.ts
- Register GitHubPanel with SidebarModel
@@ -178,10 +209,12 @@ packages/noodl-editor/src/editor/src/models/sidebar/sidebarmodel.tsx
```
**Dependencies:**
+
- `react-markdown` for rendering issue bodies
- `@octokit/rest` (from GIT-004A)
**Success Criteria:**
+
- [ ] GitHub panel appears in sidebar when repo is connected
- [ ] Issues list loads and displays correctly
- [ ] Filters work (open/closed, labels, assignees, search)
@@ -197,6 +230,7 @@ packages/noodl-editor/src/editor/src/models/sidebar/sidebarmodel.tsx
View GitHub pull requests for the connected repository.
**Scope:**
+
- PRs tab in GitHubPanel
- PR list with status indicators (draft, review requested, approved, changes requested)
- PR detail view (description, commits, checks status)
@@ -205,6 +239,7 @@ View GitHub pull requests for the connected repository.
- Merge conflict indicators
**Files to Create:**
+
```
packages/noodl-editor/src/editor/src/views/panels/GitHubPanel/
├── components/
@@ -220,6 +255,7 @@ packages/noodl-editor/src/editor/src/views/panels/GitHubPanel/
```
**Success Criteria:**
+
- [ ] PRs tab displays all open PRs
- [ ] Status badges show draft/review/approved/changes requested
- [ ] PR detail shows description, commits list, checks status
@@ -234,6 +270,7 @@ packages/noodl-editor/src/editor/src/views/panels/GitHubPanel/
Full CRUD operations for GitHub issues from within Nodegex.
**Scope:**
+
- Create Issue dialog with title, body (markdown editor), labels, assignees
- Edit existing issues (title, body, status)
- Add comments to issues
@@ -242,6 +279,7 @@ Full CRUD operations for GitHub issues from within Nodegex.
- Issue templates support (load from repo's .github/ISSUE_TEMPLATE/)
**Files to Create:**
+
```
packages/noodl-editor/src/editor/src/views/panels/GitHubPanel/
├── components/
@@ -256,12 +294,14 @@ packages/noodl-editor/src/editor/src/views/panels/GitHubPanel/
```
**Files to Modify:**
+
```
packages/noodl-editor/src/editor/src/views/nodegrapheditor/
- Add context menu items for component-linked issue creation
```
**Success Criteria:**
+
- [ ] Create Issue dialog opens from panel header
- [ ] Can set title, body, labels, assignees
- [ ] Markdown preview works in body editor
@@ -279,6 +319,7 @@ packages/noodl-editor/src/editor/src/views/nodegrapheditor/
**THE KILLER FEATURE**: Link GitHub issues to visual components for unprecedented traceability.
**Scope:**
+
- Component metadata extension for issue links
- "Link Issue" dialog from component context menu
- "Create Issue from Component" with auto-populated context
@@ -295,21 +336,22 @@ interface ComponentMetadata {
name: string;
// ... existing fields
github?: {
- linkedIssues: number[]; // Issue numbers
- linkedPRs: number[]; // PR numbers
- lastModifiedBy?: string; // GitHub username
+ linkedIssues: number[]; // Issue numbers
+ linkedPRs: number[]; // PR numbers
+ lastModifiedBy?: string; // GitHub username
};
}
// Issue display shows linked components
interface LinkedComponent {
componentName: string;
- componentPath: string; // For navigation
+ componentPath: string; // For navigation
linkType: 'mentioned' | 'implements' | 'fixes';
}
```
**Files to Create:**
+
```
packages/noodl-editor/src/editor/src/services/github/
├── ComponentLinking.ts # Link management logic
@@ -323,6 +365,7 @@ packages/noodl-editor/src/editor/src/views/panels/GitHubPanel/
```
**Files to Modify:**
+
```
packages/noodl-editor/src/editor/src/models/projectmodel.ts
- Add methods for component GitHub metadata
@@ -338,17 +381,20 @@ packages/noodl-editor/src/editor/src/views/panels/PropertyPanel/
**User Flows:**
1. **Link Existing Issue to Component:**
+
- Right-click component → "Link to Issue"
- Search/select from open issues
- Choose link type (mentions, implements, fixes)
- Component shows badge, issue shows component link
2. **Create Issue from Component:**
+
- Right-click component → "Create Issue"
- Dialog pre-fills: component name, path, screenshot option
- Creates issue and links automatically
3. **Navigate from Issue to Component:**
+
- In issue detail, "Linked Components" section
- Click component name → navigates to component in editor
@@ -358,6 +404,7 @@ packages/noodl-editor/src/editor/src/views/panels/PropertyPanel/
- Auto-labels as "bug"
**Success Criteria:**
+
- [ ] Can link issues to components via context menu
- [ ] Can create issue from component with pre-filled context
- [ ] Components show visual indicator when issues linked
@@ -374,6 +421,7 @@ packages/noodl-editor/src/editor/src/views/panels/PropertyPanel/
Project health overview and activity feed in the Dashboard.
**Scope:**
+
- Project card enhancements: issue/PR counts, health indicators
- Activity feed widget: recent issue/PR activity across projects
- Notification badges for items needing attention
@@ -381,6 +429,7 @@ Project health overview and activity feed in the Dashboard.
- Click-through to editor with correct panel open
**Files to Create:**
+
```
packages/noodl-editor/src/editor/src/views/Dashboard/
├── components/
@@ -393,6 +442,7 @@ packages/noodl-editor/src/editor/src/views/Dashboard/
```
**Files to Modify:**
+
```
packages/noodl-editor/src/editor/src/views/Dashboard/ProjectCard/
- Add GitHub stats display
@@ -405,6 +455,7 @@ packages/noodl-editor/src/editor/src/views/Dashboard/Dashboard.tsx
**Dashboard Features:**
1. **Project Card Stats:**
+
```
┌─────────────────────────┐
│ My Project │
@@ -418,6 +469,7 @@ packages/noodl-editor/src/editor/src/views/Dashboard/Dashboard.tsx
```
2. **Activity Feed:**
+
- Shows recent activity across all connected projects
- Filterable by type (issues, PRs, discussions)
- "Assigned to me" filter
@@ -428,6 +480,7 @@ packages/noodl-editor/src/editor/src/views/Dashboard/Dashboard.tsx
- Attention triggers: assigned issues, review requests, mentions
**Success Criteria:**
+
- [ ] Project cards show GitHub stats when connected
- [ ] Activity feed displays recent cross-project activity
- [ ] Notification badges appear for items needing attention
@@ -462,16 +515,17 @@ function useIssues(repoOwner: string, repoName: string) {
const [issues, setIssues] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
-
+
const client = useGitHubClient();
-
+
useEffect(() => {
- client.issues.list({ owner: repoOwner, repo: repoName })
+ client.issues
+ .list({ owner: repoOwner, repo: repoName })
.then(setIssues)
.catch(setError)
.finally(() => setLoading(false));
}, [repoOwner, repoName]);
-
+
return { issues, loading, error, refetch };
}
```
@@ -507,10 +561,10 @@ GitHub API has limits (5000 requests/hour for authenticated users). Strategy:
```json
{
- "@octokit/rest": "^20.0.0", // GitHub API client
+ "@octokit/rest": "^20.0.0", // GitHub API client
"@octokit/auth-oauth-app": "^7.0.0", // OAuth flow
- "react-markdown": "^9.0.0", // Markdown rendering
- "remark-gfm": "^4.0.0" // GitHub Flavored Markdown
+ "react-markdown": "^9.0.0", // Markdown rendering
+ "remark-gfm": "^4.0.0" // GitHub Flavored Markdown
}
```
@@ -543,6 +597,7 @@ GIT-004A: OAuth & Client Foundation
```
**Recommended sequence:**
+
1. **GIT-004A** (Foundation) - Required first
2. **GIT-004B** (Issues Read) - Core value, quick win
3. **GIT-004D** (Issues Write) - Enables productivity
@@ -581,13 +636,13 @@ GIT-004A: OAuth & Client Foundation
## Risks & Mitigations
-| Risk | Impact | Probability | Mitigation |
-|------|--------|-------------|------------|
-| GitHub API rate limits | Medium | Medium | Caching, conditional requests, user feedback |
-| OAuth complexity in Electron | High | Medium | Follow GitHub Desktop patterns, thorough testing |
-| Token security concerns | High | Low | Use OS keychain via electron-store encryption |
-| Large repos performance | Medium | Medium | Pagination, virtual lists, lazy loading |
-| GitHub API changes | Low | Low | Pin @octokit version, integration tests |
+| Risk | Impact | Probability | Mitigation |
+| ---------------------------- | ------ | ----------- | ------------------------------------------------ |
+| GitHub API rate limits | Medium | Medium | Caching, conditional requests, user feedback |
+| OAuth complexity in Electron | High | Medium | Follow GitHub Desktop patterns, thorough testing |
+| Token security concerns | High | Low | Use OS keychain via electron-store encryption |
+| Large repos performance | Medium | Medium | Pagination, virtual lists, lazy loading |
+| GitHub API changes | Low | Low | Pin @octokit version, integration tests |
---
@@ -619,3 +674,124 @@ GIT-004A: OAuth & Client Foundation
- [GitHub App Permissions](https://docs.github.com/en/rest/overview/permissions-required-for-github-apps)
- Existing: `packages/noodl-git/` - Current Git integration
- Existing: `VersionControlPanel/` - Current VCS UI patterns
+
+---
+
+# Part 2: Live Collaboration & Multi-Community System (GIT-005-011)
+
+## Overview
+
+This series transforms OpenNoodl into a collaborative platform with multi-community support, live real-time collaboration (Google Docs for visual programming), and persistent notification system.
+
+**Total Estimated Hours:** 431-572 hours
+
+---
+
+## Task Summary
+
+| Task | Name | Estimated Hours | Status |
+| ------- | --------------------------- | --------------- | -------------- |
+| GIT-005 | Community Infrastructure | 60-80 | 🔴 Not Started |
+| GIT-006 | Server Infrastructure | 80-100 | 🔴 Not Started |
+| GIT-007 | WebRTC Collaboration Client | 100-130 | 🔴 Not Started |
+| GIT-008 | Notification System | 50-70 | 🔴 Not Started |
+| GIT-009 | Community Tab UI/UX | 80-100 | 🔴 Not Started |
+| GIT-010 | Session Discovery & Joining | 50-70 | 🔴 Not Started |
+| GIT-011 | Integration & Polish | 61-82 | 🔴 Not Started |
+
+---
+
+## Key Features
+
+### Multi-Community System
+
+- Join multiple communities simultaneously
+- Fork and operate your own communities
+- Self-hosted infrastructure option (BYOB philosophy)
+- Community template repository for forking
+
+### Live Collaboration
+
+- Real-time multi-user editing via WebRTC
+- Cursor and selection sharing
+- Audio/video chat built-in
+- Automatic WebSocket fallback when P2P fails
+
+### Persistent Notifications
+
+- Cross-session notification system
+- Collaboration invites
+- Community events and mentions
+- Desktop notification support
+
+### Community Features
+
+- Component library discovery
+- Tutorial and showcase feeds
+- GitHub Discussions integration
+- Job board
+
+---
+
+## Task Details
+
+Each task has a detailed README in its subdirectory:
+
+- **[GIT-005: Community Infrastructure](./GIT-005-community-infrastructure/README.md)** - Template repository, community.json schema, CommunityManager service
+- **[GIT-006: Server Infrastructure](./GIT-006-server-infrastructure/README.md)** - Signaling, Sync, and Notification servers
+- **[GIT-007: WebRTC Collaboration](./GIT-007-webrtc-collaboration/README.md)** - P2P connections, Yjs CRDT sync, media handling
+- **[GIT-008: Notification System](./GIT-008-notification-system/README.md)** - NotificationManager, toasts, notification center
+- **[GIT-009: Community UI](./GIT-009-community-ui/README.md)** - Community tab with sessions, components, tutorials
+- **[GIT-010: Session Discovery](./GIT-010-session-discovery/README.md)** - Deep links, quick join, session history
+- **[GIT-011: Integration & Polish](./GIT-011-integration-polish/README.md)** - Testing, documentation, deployment
+
+---
+
+## Implementation Order
+
+```
+GIT-005: Community Infrastructure
+ │
+ └──► GIT-006: Server Infrastructure
+ │
+ ├──► GIT-007: WebRTC Collaboration Client
+ │ │
+ │ └──► GIT-010: Session Discovery
+ │
+ └──► GIT-008: Notification System
+ │
+ └──► GIT-009: Community Tab UI
+ │
+ └──► GIT-011: Integration & Polish
+```
+
+---
+
+## Dependencies
+
+### NPM Packages
+
+```json
+{
+ "yjs": "^13.6.0",
+ "y-webrtc": "^10.2.0",
+ "y-websocket": "^1.5.0",
+ "simple-peer": "^9.11.0"
+}
+```
+
+### External Infrastructure
+
+- Signaling server (WebSocket)
+- Sync server (Yjs WebSocket)
+- Notification server (WebSocket + persistence)
+- TURN server (for WebRTC fallback)
+
+---
+
+## Source Documentation
+
+Full detailed specifications are in:
+
+- `GIT-5-to-GIT-11-Live-Collaboration-Community-System.md`
+- `GIT-5-to-GIT-11-Part-2-Community-UI-Integration.md`
diff --git a/dev-docs/tasks/phase-3-editor-ux-overhaul/TASK-002C-github-clone-and-connect/CHANGELOG.md b/dev-docs/tasks/phase-3-editor-ux-overhaul/TASK-002C-github-clone-and-connect/CHANGELOG.md
new file mode 100644
index 0000000..83ac924
--- /dev/null
+++ b/dev-docs/tasks/phase-3-editor-ux-overhaul/TASK-002C-github-clone-and-connect/CHANGELOG.md
@@ -0,0 +1,246 @@
+# TASK-002C: GitHub Clone & Connect - Changelog
+
+## 2025-01-17 - Subtask A: Clone from GitHub ✅ COMPLETE
+
+### Implemented Features
+
+#### 1. GitHub Tab in Launcher
+
+- New "GitHub" tab added to the launcher navigation
+- Shows user's GitHub avatar when connected
+- Only available when authenticated
+
+#### 2. Noodl Project Detection
+
+- Scans all repos for `project.json` at root
+- Shows scanning progress: "Scanning X repositories for project.json..."
+- Only displays repos that are confirmed Noodl projects
+- Caches detection results for 1 minute
+
+#### 3. Repository Organization
+
+- Groups repos by source: Personal vs Organization
+- Collapsible organization sections with project counts
+- Shows repo details: name, privacy status, description, last updated
+
+#### 4. Clone Functionality
+
+- Clone button on each Noodl project card
+- User selects destination folder via native dialog
+- Progress indicator during clone
+- **Legacy project detection**: After cloning, detects React 17 projects and shows:
+ - **Migrate** - Opens migration wizard
+ - **Read-Only** - Opens in read-only mode
+ - **Cancel** - Adds to projects list without opening
+
+#### 5. OAuth Improvements
+
+- Fixed cache bug: null values now properly handled (undefined vs null)
+- Fixed scope: Token now has proper permissions for private repo access
+- Connection status persists across sessions
+
+### Files Modified
+
+**Editor (noodl-editor):**
+
+- `src/editor/src/pages/ProjectsPage/ProjectsPage.tsx` - Added handleCloneRepo with legacy detection
+- `src/editor/src/services/github/GitHubClient.ts` - Fixed cache, simplified isNoodlProject
+- `src/editor/src/services/GitHubOAuthService.ts` - Fixed token persistence
+
+**Core UI (noodl-core-ui):**
+
+- `src/preview/launcher/Launcher/views/GitHubRepos.tsx` - New GitHub repos view
+- `src/preview/launcher/Launcher/hooks/useGitHubRepos.ts` - Hook for fetching/detecting repos
+- `src/preview/launcher/Launcher/Launcher.tsx` - Added GitHub tab
+- `src/preview/launcher/Launcher/LauncherContext.tsx` - Added GitHub context props
+
+### Bug Fixes
+
+- Fixed cache returning stale null values (404 results)
+- Removed premature `nodegx.project.json` check
+- Fixed OAuth flow to properly complete on macOS
+
+### Known Limitations
+
+- Only checks default branch for project.json
+- API rate limit: ~5000 requests/hour (sufficient for most users)
+- Large organizations may take time to scan all repos
+
+---
+
+## 2025-01-17 - Subtask B: Connect Project to GitHub ✅ COMPLETE
+
+### Implemented Features
+
+#### 1. Enhanced Git State Detection
+
+- Extended `useGitHubRepository` hook to return detailed git state:
+ - `no-git` - No .git folder, project not under version control
+ - `git-no-remote` - Has .git but no remote configured
+ - `remote-not-github` - Has remote but not github.com
+ - `github-connected` - Connected to GitHub
+
+#### 2. Connect to GitHub Flow
+
+- **ConnectToGitHubView** - Main view showing state-appropriate options
+- State-specific messaging:
+ - No git: "Initialize Git Repository"
+ - No remote: "Connect to GitHub"
+ - Not GitHub: Shows current remote URL with explanation
+
+#### 3. Create New Repository
+
+- **CreateRepoModal** - Full modal for creating new GitHub repos
+- Features:
+ - Repository name with validation (GitHub naming rules)
+ - Optional description
+ - Visibility toggle (Private/Public, defaults to Private)
+ - Organization picker (lists user's organizations)
+- After creation:
+ - Initializes git if needed
+ - Adds remote origin
+ - Creates initial commit
+ - Pushes to remote
+
+#### 4. Connect to Existing Repository
+
+- **SelectRepoModal** - Browse and select from user's repos
+- Features:
+ - Lists all user repos + organization repos
+ - Search/filter by name or description
+ - Grouped by owner (Personal vs Organization)
+ - Shows privacy status and last updated
+- After connecting:
+ - Initializes git if needed
+ - Sets remote URL
+ - Fetches from remote if repo has commits
+ - Attempts to merge remote changes
+
+### Files Added
+
+**ConnectToGitHub Components:**
+
+- `components/ConnectToGitHub/ConnectToGitHubView.tsx` - Main view component
+- `components/ConnectToGitHub/CreateRepoModal.tsx` - Create repo modal
+- `components/ConnectToGitHub/SelectRepoModal.tsx` - Select existing repo modal
+- `components/ConnectToGitHub/ConnectToGitHub.module.scss` - Styles
+- `components/ConnectToGitHub/index.ts` - Exports
+
+### Files Modified
+
+- `hooks/useGitHubRepository.ts` - Enhanced with `ProjectGitState` type and `refetch` function
+- `services/github/GitHubTypes.ts` - Added `CreateRepositoryOptions` interface
+- `services/github/GitHubClient.ts` - Added `createRepository` method
+- `GitHubPanel.tsx` - Integrated ConnectToGitHubView for unconnected states
+
+---
+
+## 2025-01-17 - Subtask C: Push/Pull from GitHub Panel ✅ COMPLETE
+
+### Implemented Features
+
+#### 1. Git Sync Status Hook
+
+- **useGitSyncStatus** - Monitors git sync status in real-time
+- Tracks:
+ - `ahead` - Number of commits ahead of remote
+ - `behind` - Number of commits behind remote
+ - `hasUncommittedChanges` - Whether there are local changes
+- Provides:
+ - `push()` - Push to remote (auto-commits if uncommitted changes)
+ - `pull()` - Pull from remote (stashes changes, merges, pops stash)
+ - `refresh()` - Manually refresh sync status
+- Auto-refreshes on project save and remote changes
+
+#### 2. Sync Toolbar
+
+- **SyncToolbar** - Toolbar displayed at top of GitHubPanel when connected
+- Shows:
+ - Repository name (owner/repo)
+ - Sync status (uncommitted changes, up to date)
+- Buttons:
+ - **Pull** - Pull from remote, shows badge with behind count
+ - **Push** - Push to remote, shows badge with ahead count or "!" for uncommitted
+ - **Refresh** - Manually refresh sync status (spinning animation while loading)
+- Visual feedback:
+ - Highlighted buttons when there are changes to push/pull
+ - Error bar for operation failures
+
+#### 3. Push Operation
+
+- Checks for uncommitted changes
+- Auto-commits with "Auto-commit before push" message
+- Pushes to remote
+- Refreshes sync status
+
+#### 4. Pull Operation
+
+- Stashes local changes if present
+- Fetches from remote
+- Merges remote branch into current branch
+- Pops stash to restore local changes
+- Notifies project to refresh
+
+### Files Added
+
+**SyncToolbar Component:**
+
+- `components/SyncToolbar/SyncToolbar.tsx` - Toolbar with push/pull buttons
+- `components/SyncToolbar/SyncToolbar.module.scss` - Styles
+- `components/SyncToolbar/index.ts` - Exports
+
+**Hooks:**
+
+- `hooks/useGitSyncStatus.ts` - Git sync status monitoring
+
+### Files Modified
+
+- `GitHubPanel.tsx` - Added SyncToolbar to connected state view
+
+---
+
+## Summary
+
+### All Subtasks Complete ✅
+
+| Subtask | Status | Description |
+| ------------------------------ | -------- | ----------------------------------------------- |
+| A: Clone from GitHub | Complete | Clone Noodl projects from GitHub in launcher |
+| B: Connect Project to GitHub | Complete | Initialize git, create/connect repo from editor |
+| C: Push/Pull from GitHub Panel | Complete | Push/pull with sync status in GitHubPanel |
+
+### Files Created (New)
+
+```
+packages/noodl-editor/src/editor/src/views/panels/GitHubPanel/
+├── components/
+│ ├── ConnectToGitHub/
+│ │ ├── ConnectToGitHub.module.scss
+│ │ ├── ConnectToGitHubView.tsx
+│ │ ├── CreateRepoModal.tsx
+│ │ ├── SelectRepoModal.tsx
+│ │ └── index.ts
+│ └── SyncToolbar/
+│ ├── SyncToolbar.module.scss
+│ ├── SyncToolbar.tsx
+│ └── index.ts
+└── hooks/
+ └── useGitSyncStatus.ts
+```
+
+### Files Modified
+
+```
+packages/noodl-editor/src/editor/src/
+├── services/github/
+│ ├── GitHubClient.ts (added createRepository)
+│ └── GitHubTypes.ts (added CreateRepositoryOptions)
+└── views/panels/GitHubPanel/
+ ├── GitHubPanel.tsx (integrated new components)
+ └── hooks/
+ └── useGitHubRepository.ts (enhanced state detection)
+```
+
+---
+
+_Completed: January 2025_
diff --git a/dev-docs/tasks/phase-3-editor-ux-overhaul/TASK-002C-github-clone-and-connect/README.md b/dev-docs/tasks/phase-3-editor-ux-overhaul/TASK-002C-github-clone-and-connect/README.md
new file mode 100644
index 0000000..9cc0202
--- /dev/null
+++ b/dev-docs/tasks/phase-3-editor-ux-overhaul/TASK-002C-github-clone-and-connect/README.md
@@ -0,0 +1,197 @@
+# TASK-002C: GitHub Clone & Connect UX
+
+## Overview
+
+Add two critical GitHub UX flows that are currently missing:
+
+1. **Clone Noodl Projects from GitHub** - Browse and clone existing Noodl projects from user's orgs/repos
+2. **Connect Project to GitHub** - Initialize git and create/connect remote for unconnected projects
+
+## Prerequisites
+
+- [x] GitHub OAuth working (TASK-002B)
+- [x] Token persistence working
+- [x] GitHubOAuthService unified across launcher/editor
+
+## Subtask A: Clone from GitHub (Launcher)
+
+### User Story
+
+> As a user, I want to browse my GitHub orgs/repos in the Launcher and clone existing Noodl projects with one click.
+
+### Requirements
+
+1. **UI: GitHub Repositories Tab/Section in Launcher**
+
+ - Show when authenticated with GitHub
+ - List user's organizations (from OAuth app installations)
+ - List user's personal repositories
+ - Search/filter by name
+ - Visual indicator for Noodl projects (detected via `project.json`)
+
+2. **Noodl Project Detection**
+
+ - Query GitHub API for `project.json` in repo root
+ - Only show repos that contain `project.json` (optional: user toggle to show all)
+ - Show warning badge for repos without `project.json`
+
+3. **Clone Flow**
+ - User clicks "Clone" on a repo
+ - Select local destination folder
+ - Clone with progress indicator
+ - Automatically add to projects list
+ - Option to open immediately after clone
+
+### API Requirements
+
+```typescript
+// GitHubClient additions needed:
+listUserRepositories(): Promise
+listOrganizationRepositories(org: string): Promise
+getFileContent(owner: string, repo: string, path: string): Promise
+```
+
+### Files to Create/Modify
+
+- `packages/noodl-core-ui/src/preview/launcher/Launcher/views/GitHubRepos/` (new)
+ - `GitHubReposView.tsx`
+ - `GitHubReposList.tsx`
+ - `GitHubRepoCard.tsx`
+ - `hooks/useGitHubRepos.ts`
+- `packages/noodl-editor/src/editor/src/services/github/GitHubClient.ts` (extend)
+- `packages/noodl-editor/src/editor/src/pages/ProjectsPage/ProjectsPage.tsx` (add clone handler)
+
+---
+
+## Subtask B: Connect Project to GitHub (In-Editor)
+
+### User Story
+
+> As a user, when my project isn't connected to GitHub, I want to either create a new repo or connect to an existing one.
+
+### Requirements
+
+1. **Detection State**
+
+ - Project has no `.git` folder → "Initialize Git"
+ - Project has `.git` but no remote → "Add Remote"
+ - Project has remote but not GitHub → "Not a GitHub repo" (read-only info)
+ - Project connected to GitHub → Show Issues/PRs as normal
+
+2. **UI: "Not Connected" State in GitHubPanel**
+
+ - Replace 404 errors with friendly message
+ - Show two primary actions:
+ - **"Create New Repository"** → Creates on GitHub, adds as remote, pushes
+ - **"Connect Existing Repository"** → Browse user's repos, set as remote
+
+3. **Create New Repo Flow**
+
+ - Modal: Enter repo name, description, visibility (public/private)
+ - Select organization (from OAuth installations) or personal
+ - Create via GitHub API
+ - Initialize git if needed
+ - Add remote origin
+ - Initial commit & push
+
+4. **Connect Existing Repo Flow**
+ - Browse user's orgs/repos (reuse from Subtask A)
+ - Select repo
+ - Add as remote origin
+ - Offer to fetch/pull if repo has commits
+
+### API Requirements
+
+```typescript
+// GitHubClient additions needed:
+createRepository(options: {
+ name: string;
+ description?: string;
+ private?: boolean;
+ org?: string; // If creating in org
+}): Promise
+```
+
+### Files to Create/Modify
+
+- `packages/noodl-editor/src/editor/src/views/panels/GitHubPanel/GitHubPanel.tsx` (modify)
+- `packages/noodl-editor/src/editor/src/views/panels/GitHubPanel/components/ConnectToGitHub/` (new)
+ - `ConnectToGitHubView.tsx`
+ - `CreateRepoModal.tsx`
+ - `SelectRepoModal.tsx`
+- `packages/noodl-editor/src/editor/src/services/github/GitHubClient.ts` (extend)
+
+---
+
+## Design Considerations
+
+### Noodl Project Detection
+
+Option 1: **Check for `project.json` via API**
+
+```typescript
+async isNoodlProject(owner: string, repo: string): Promise {
+ const content = await this.getFileContent(owner, repo, 'project.json');
+ return content !== null;
+}
+```
+
+Option 2: **Topics/Labels** (future)
+
+- Allow users to add `noodl-project` topic to repos
+- Search by topic
+
+### Error Handling
+
+- Rate limit warnings (GitHub API limits)
+- Private repo access errors (missing OAuth scope)
+- Clone failures (disk space, permissions)
+- Push failures (authentication, branch protection)
+
+### Performance
+
+- Cache repo lists with short TTL (30 seconds)
+- Lazy load Noodl detection (don't check all repos immediately)
+- Pagination for orgs with many repos
+
+---
+
+## Acceptance Criteria
+
+### Subtask A: Clone
+
+- [ ] Authenticated user can see "GitHub Repos" section in launcher
+- [ ] Can browse personal repos and org repos
+- [ ] Noodl projects are visually distinguished
+- [ ] Can clone repo to selected location
+- [ ] Cloned project appears in projects list
+- [ ] Progress indicator during clone
+
+### Subtask B: Connect
+
+- [ ] Non-git project shows "Initialize & Connect" option
+- [ ] Git project without remote shows "Connect" option
+- [ ] Can create new repo (personal or org)
+- [ ] Can connect to existing repo
+- [ ] After connecting, Issues/PRs tabs work
+
+---
+
+## Related Tasks
+
+- TASK-002B: GitHub OAuth Integration (prerequisite - DONE)
+- TASK-002D: GitHub Sync Status (future - show sync status in project cards)
+
+---
+
+## Estimated Effort
+
+| Subtask | Effort | Priority |
+| -------------------- | --------- | -------- |
+| A: Clone from GitHub | 4-6 hours | High |
+| B: Connect to GitHub | 3-4 hours | High |
+
+---
+
+_Created: January 2026_
+_Status: DRAFT_
diff --git a/packages/noodl-core-ui/src/preview/launcher/Launcher/Launcher.tsx b/packages/noodl-core-ui/src/preview/launcher/Launcher/Launcher.tsx
index 02cbc54..30aeadb 100644
--- a/packages/noodl-core-ui/src/preview/launcher/Launcher/Launcher.tsx
+++ b/packages/noodl-core-ui/src/preview/launcher/Launcher/Launcher.tsx
@@ -17,8 +17,10 @@ import {
CloudSyncType,
LauncherProjectData
} from '@noodl-core-ui/preview/launcher/Launcher/components/LauncherProjectCard';
+import { NoodlGitHubRepo, UseGitHubReposReturn } from '@noodl-core-ui/preview/launcher/Launcher/hooks/useGitHubRepos';
import { usePersistentTab } from '@noodl-core-ui/preview/launcher/Launcher/hooks/usePersistentTab';
import { GitHubUser, LauncherPageId, LauncherProvider } from '@noodl-core-ui/preview/launcher/Launcher/LauncherContext';
+import { GitHubRepos } from '@noodl-core-ui/preview/launcher/Launcher/views/GitHubRepos';
import { LearningCenter } from '@noodl-core-ui/preview/launcher/Launcher/views/LearningCenter';
import { Projects } from '@noodl-core-ui/preview/launcher/Launcher/views/Projects';
import { Templates } from '@noodl-core-ui/preview/launcher/Launcher/views/Templates';
@@ -53,15 +55,24 @@ export interface LauncherProps {
githubIsConnecting?: boolean;
onGitHubConnect?: () => void;
onGitHubDisconnect?: () => void;
+
+ // GitHub repos for clone feature (optional - for Storybook compatibility)
+ githubRepos?: UseGitHubReposReturn | null;
+ onCloneRepo?: (repo: NoodlGitHubRepo) => Promise;
}
-// Tab configuration
+// Tab configuration (GitHub tab added dynamically based on auth state)
const LAUNCHER_TABS: TabBarItem[] = [
{
id: 'projects',
label: 'Projects',
icon: IconName.FolderOpen
},
+ {
+ id: 'github',
+ label: 'GitHub',
+ icon: IconName.CloudFunction
+ },
{
id: 'learn',
label: 'Learn',
@@ -187,7 +198,9 @@ export function Launcher({
githubIsAuthenticated,
githubIsConnecting,
onGitHubConnect,
- onGitHubDisconnect
+ onGitHubDisconnect,
+ githubRepos,
+ onCloneRepo
}: LauncherProps) {
// Determine initial tab: props > deep link > persisted > default
const deepLinkTab = parseDeepLink();
@@ -263,6 +276,8 @@ export function Launcher({
switch (activePageId) {
case 'projects':
return ;
+ case 'github':
+ return ;
case 'learn':
return ;
case 'templates':
@@ -295,7 +310,9 @@ export function Launcher({
githubIsAuthenticated,
githubIsConnecting,
onGitHubConnect,
- onGitHubDisconnect
+ onGitHubDisconnect,
+ githubRepos,
+ onCloneRepo
}}
>
diff --git a/packages/noodl-core-ui/src/preview/launcher/Launcher/LauncherContext.tsx b/packages/noodl-core-ui/src/preview/launcher/Launcher/LauncherContext.tsx
index 616ac27..e3ed28d 100644
--- a/packages/noodl-core-ui/src/preview/launcher/Launcher/LauncherContext.tsx
+++ b/packages/noodl-core-ui/src/preview/launcher/Launcher/LauncherContext.tsx
@@ -9,8 +9,9 @@
import React, { createContext, useContext, ReactNode } from 'react';
import { LauncherProjectData } from './components/LauncherProjectCard';
+import { NoodlGitHubRepo, UseGitHubReposReturn } from './hooks/useGitHubRepos';
-export type LauncherPageId = 'projects' | 'learn' | 'templates';
+export type LauncherPageId = 'projects' | 'learn' | 'templates' | 'github';
// GitHub user info (matches GitHubOAuthService interface)
export interface GitHubUser {
@@ -52,6 +53,10 @@ export interface LauncherContextValue {
githubIsConnecting?: boolean;
onGitHubConnect?: () => void;
onGitHubDisconnect?: () => void;
+
+ // GitHub repos for clone feature (optional - for Storybook compatibility)
+ githubRepos?: UseGitHubReposReturn | null;
+ onCloneRepo?: (repo: NoodlGitHubRepo) => Promise
;
}
const LauncherContext = createContext(null);
diff --git a/packages/noodl-core-ui/src/preview/launcher/Launcher/hooks/useGitHubRepos.ts b/packages/noodl-core-ui/src/preview/launcher/Launcher/hooks/useGitHubRepos.ts
new file mode 100644
index 0000000..ea61122
--- /dev/null
+++ b/packages/noodl-core-ui/src/preview/launcher/Launcher/hooks/useGitHubRepos.ts
@@ -0,0 +1,337 @@
+/**
+ * useGitHubRepos Hook
+ *
+ * Fetches and manages GitHub repositories for the authenticated user,
+ * including personal repos and organization repos.
+ * Detects Noodl projects by checking for project.json or nodegx.project.json.
+ *
+ * @module noodl-core-ui/preview/launcher/Launcher/hooks
+ */
+
+import { useState, useEffect, useCallback, useRef } from 'react';
+
+// ==================== LOCAL TYPE DEFINITIONS ====================
+// These mirror the GitHub types but are defined locally to avoid circular dependencies
+
+/**
+ * GitHub User/Owner
+ */
+export interface GitHubOwner {
+ id: number;
+ login: string;
+ avatar_url: string;
+ html_url: string;
+}
+
+/**
+ * GitHub Repository (minimal fields needed for clone UI)
+ */
+export interface GitHubRepo {
+ id: number;
+ name: string;
+ full_name: string;
+ owner: GitHubOwner;
+ private: boolean;
+ html_url: string;
+ description: string | null;
+ clone_url?: string;
+ ssh_url?: string;
+ updated_at: string;
+ pushed_at: string;
+ default_branch: string;
+ stargazers_count: number;
+ language: string | null;
+}
+
+/**
+ * GitHub Organization
+ */
+export interface GitHubOrg {
+ id: number;
+ login: string;
+ avatar_url: string;
+ description: string | null;
+}
+
+// ==================== HOOK TYPES ====================
+
+/**
+ * Extended repo info with Noodl detection status
+ */
+export interface NoodlGitHubRepo extends GitHubRepo {
+ /** Whether this repo is a Noodl project */
+ isNoodlProject: boolean | null; // null = not yet checked
+ /** Whether Noodl detection is in progress */
+ isCheckingNoodl: boolean;
+ /** Source: 'personal' or org name */
+ source: string;
+}
+
+/**
+ * Organization with its repos
+ */
+export interface GitHubOrgWithRepos extends GitHubOrg {
+ repos: NoodlGitHubRepo[];
+ isLoading: boolean;
+ error: string | null;
+}
+
+/**
+ * Hook return type
+ */
+export interface UseGitHubReposReturn {
+ /** All Noodl project repos (filtered) */
+ noodlProjects: NoodlGitHubRepo[];
+ /** All repos (unfiltered) */
+ allRepos: NoodlGitHubRepo[];
+ /** User's organizations */
+ organizations: GitHubOrgWithRepos[];
+ /** Personal repos */
+ personalRepos: NoodlGitHubRepo[];
+ /** Loading state */
+ isLoading: boolean;
+ /** Error message */
+ error: string | null;
+ /** Refresh all data */
+ refresh: () => Promise;
+ /** Check if a specific repo is a Noodl project */
+ checkIfNoodlProject: (owner: string, repo: string) => Promise;
+}
+
+/**
+ * GitHub API client interface (injected to avoid circular dependencies)
+ */
+export interface GitHubClientInterface {
+ listRepositories: (options?: { per_page?: number; sort?: string }) => Promise<{ data: GitHubRepo[] }>;
+ listOrganizations: () => Promise<{ data: GitHubOrg[] }>;
+ listOrganizationRepositories: (org: string, options?: { per_page?: number }) => Promise<{ data: GitHubRepo[] }>;
+ isNoodlProject: (owner: string, repo: string) => Promise;
+}
+
+/**
+ * Hook to fetch GitHub repositories and detect Noodl projects
+ *
+ * @param client - GitHub client instance
+ * @param isAuthenticated - Whether user is authenticated with GitHub
+ */
+export function useGitHubRepos(client: GitHubClientInterface | null, isAuthenticated: boolean): UseGitHubReposReturn {
+ const [personalRepos, setPersonalRepos] = useState([]);
+ const [organizations, setOrganizations] = useState([]);
+ const [isLoading, setIsLoading] = useState(false);
+ const [error, setError] = useState(null);
+
+ // Track ongoing Noodl checks to avoid duplicates
+ const noodlCheckQueue = useRef