// DevPulse Landing Page Controller // Uses Lucide icons (loaded via CDN in HTML) interface SimState { activeTab: string; prStatus: "open" | "approved" | "changes_requested" | "merged"; repoTab: string; } const state: SimState = { activeTab: "pr", prStatus: "open", repoTab: "overview", }; // All 21 commands data const commands = [ { name: "/repo", desc: "Repository intelligence, health score, dependencies, growth", icon: "book-open", color: "gh-blue", }, { name: "/pr", desc: "PR details, CI status, approve, request changes, merge", icon: "git-pull-request", color: "gh-green", }, { name: "/search", desc: "Search code, issues, PRs, repos, commits with qualifiers", icon: "search", color: "gh-purple", }, { name: "/code", desc: "View files, git blame, commit-to-PR resolution", icon: "code", color: "gh-blue", }, { name: "/investigate", desc: "Full lifecycle: issue → commit → PR → review → merge → release", icon: "git-merge", color: "gh-purple", }, { name: "/activity", desc: "Commit histograms, churn analysis, personal telemetry", icon: "bar-chart-2", color: "gh-green", }, { name: "/trending", desc: "Trending repos across TypeScript, Rust, AI/ML, Go, Python", icon: "trending-up", color: "gh-amber", }, { name: "/watch", desc: "Subscribe channels to releases, PRs, issues, security alerts", icon: "bell", color: "gh-blue", }, { name: "/actions", desc: "CI/CD workflow trees, run history, rerun/cancel controls", icon: "play-circle", color: "gh-green", }, { name: "/security", desc: "Dependabot alerts, CVE lookup, real-time secret scanner", icon: "shield-check", color: "gh-coral", }, { name: "/release", desc: "Latest releases, tag comparison, auto changelog generator", icon: "tag", color: "gh-purple", }, { name: "/team", desc: "Team velocity, cycle times, review load balancing", icon: "users", color: "gh-blue", }, { name: "/home", desc: "Morning cockpit: active PRs, reviews, alerts, trending", icon: "home", color: "gh-green", }, { name: "/connect", desc: "AES-256-GCM encrypted PAT storage for write actions", icon: "link", color: "gh-blue", }, { name: "/why", desc: "Trace file/line → commit → PR → originating issue", icon: "help-circle", color: "gh-purple", }, { name: "/ask", desc: "Query engine: stale PRs, bottlenecks, frequent files", icon: "message-circle", color: "gh-green", }, { name: "/tools", desc: "JSON formatter, base64, JWT inspector, hash, timestamps", icon: "wrench", color: "gh-amber", }, { name: "/settings", desc: "Server config: repos, channels, access controls", icon: "settings", color: "gh-blue", }, { name: "/help", desc: "Interactive command directory with examples", icon: "info", color: "gh-green", }, { name: "/ai", desc: "AI code explanations, PR summaries, bug fix suggestions", icon: "brain", color: "gh-coral", }, { name: "/code-review", desc: "Automated PR review: security, performance, style", icon: "eye", color: "gh-purple", }, ]; // Initialize everything document.addEventListener("DOMContentLoaded", () => { // Initialize Lucide icons if (typeof lucide !== "undefined") { lucide.createIcons(); } // Build commands grid buildCommandsGrid(); // Initialize simulator initSimulator(); // Initialize navbar initNavbar(); // Initialize mobile menu initMobileMenu(); // Initialize copy buttons initCopyButtons(); // Initialize scroll effects initScrollEffects(); }); // Build the 21 commands grid function buildCommandsGrid() { const grid = document.getElementById("commands-grid"); if (!grid) return; grid.innerHTML = commands .map( (cmd) => `
${cmd.name}

${cmd.desc}

`, ) .join(""); // Re-initialize icons for new elements if (typeof lucide !== "undefined") { lucide.createIcons(); } } // Simulator function initSimulator() { renderSimulator(); attachSimulatorEvents(); } function renderSimulator() { const container = document.getElementById("simulator-body"); if (!container) return; const templates: Record string> = { pr: () => renderPREmbed(), repo: () => renderRepoEmbed(), actions: () => renderActionsEmbed(), investigate: () => renderInvestigateEmbed(), code: () => renderCodeEmbed(), activity: () => renderActivityEmbed(), }; const renderer = templates[state.activeTab]; if (renderer) { container.style.opacity = "0"; container.style.transform = "translateY(8px)"; container.style.transition = "opacity 0.15s ease, transform 0.15s ease"; requestAnimationFrame(() => { container.innerHTML = renderer(); requestAnimationFrame(() => { container.style.opacity = "1"; container.style.transform = "translateY(0)"; }); }); } } function renderPREmbed() { const statusMap = { open: { text: "Ready to merge", color: "gh-green", icon: "check-circle" }, approved: { text: "Approved by you", color: "gh-green", icon: "check-circle" }, changes_requested: { text: "Changes Requested", color: "gh-coral", icon: "alert-triangle" }, merged: { text: "Merged into main", color: "gh-purple", icon: "git-merge" }, }; const status = statusMap[state.prStatus]; return `
DevPulse Bot Today at 10:42 AM
/pr 142 repo:vercel/next.js
vercel/next.js • Pull Request #142
feat(router): optimize parallel route cache hydration
${status.text} @timneutkens • 14 files • +482 -193
CI Status
12/12 Passing
Reviews
${state.prStatus === "approved" ? "3/2" : "2/2"} (Required met)
${ state.prStatus === "merged" ? `` : `` }
`; } function renderRepoEmbed() { return `
DevPulse Bot Today at 10:45 AM
/repo name:vercel/next.js
vercel/next.js
The React Framework for the Web. Health Score: 96/100
Stars & Forks
124,510 • 26,840
Issues / PRs
412 / 89
`; } function renderActionsEmbed() { return `
DevPulse Bot Today at 10:48 AM
/actions repo:vercel/next.js branch:canary
canary • Run #4,892 Passed
├── Unit Tests (Node 20 & 22) Passing (1m 42s)
├── Turbopack Integration E2E Passing (4m 15s)
├── Edge Runtime Compatibility Passing (52s)
└── Security Scanning & Audit Passing (38s)
`; } function renderInvestigateEmbed() { return `
DevPulse Bot Today at 10:50 AM
/investigate pr:142 repo:vercel/next.js
Full Development Trace
1. Issue #892 created by @alex (Sep 1)
2. Branch feature/route-cache (Sep 2)
3. Commit 8f3b12a by @timneutkens
4. PR #142 opened (Sep 2)
5. CI: 12 checks passed (Sep 2)
6. Approved by @sokra & @kdy1 (Sep 3)
7. Merged into canary (Sep 3)
8. Shipped in v15.2.0-canary.18 (Sep 4)
`; } function renderCodeEmbed() { return `
DevPulse Bot Today at 10:52 AM
/code blame file:packages/next/src/server/route-matcher.ts lines:40-46
route-matcher.ts (Lines 40-46)
40 | export function matchRoute(url: string, routes: Route[]): Route | null {
41 | // [e71ab82 @timneutkens 3d ago] Fast-path lookup
42 | const exact = exactMap.get(url);
43 | if (exact) return exact;
44 | // [8f3b12a @sokra 1w ago] Fallback evaluator
45 | return evaluateRegexRoutes(url, routes);
46 | }
Commit 8f3b12a originated from PR #138 merged Aug 28.
`; } function renderActivityEmbed() { return `
DevPulse Bot Today at 10:55 AM
/activity me days:7
Personal Activity Profile (@swadhin)
48 commits • 6 PRs authored • 14 PRs reviewed
Mon ██████████████ 14
Tue ██████████ 10
Wed ██████ 6
Thu ████████████ 12
Fri ████ 4
Sat █ 1
Sun █ 1
Churn Ratio
+2,140 / -840 (2.5x)
Avg Cycle
18h 40m
`; } function attachSimulatorEvents() { // Tab switching const tabs = document.querySelectorAll(".sim-tab-btn"); for (const tab of tabs) { tab.addEventListener("click", () => { for (const t of tabs) t.classList.remove("active"); tab.classList.add("active"); const target = tab.getAttribute("data-tab"); if (target) { state.activeTab = target; renderSimulator(); } }); } // PR simulator buttons document.addEventListener("click", (e) => { const target = e.target as HTMLElement; const btn = target.closest("button"); if (!btn) return; if (btn.id === "sim-btn-approve") { state.prStatus = "approved"; renderSimulator(); } else if (btn.id === "sim-btn-changes") { state.prStatus = "changes_requested"; renderSimulator(); } else if (btn.id === "sim-btn-merge") { btn.innerHTML = ` Merging...`; if (typeof lucide !== "undefined") lucide.createIcons(); setTimeout(() => { state.prStatus = "merged"; renderSimulator(); }, 800); } else if (btn.id === "sim-btn-rerun") { const original = btn.innerHTML; btn.innerHTML = ` Dispatching...`; if (typeof lucide !== "undefined") lucide.createIcons(); setTimeout(() => { btn.innerHTML = ` Triggered!`; if (typeof lucide !== "undefined") lucide.createIcons(); setTimeout(() => { btn.innerHTML = original; if (typeof lucide !== "undefined") lucide.createIcons(); }, 2000); }, 1000); } else if (btn.id === "sim-btn-copy-trace") { const text = "Issue #892 → PR #142 → v15.2.0-canary.18 (Commit 8f3b12a)"; navigator.clipboard.writeText(text).then(() => { const original = btn.innerHTML; btn.innerHTML = ` Copied!`; if (typeof lucide !== "undefined") lucide.createIcons(); setTimeout(() => { btn.innerHTML = original; if (typeof lucide !== "undefined") lucide.createIcons(); }, 2000); }); } }); } // Navbar scroll effect function initNavbar() { const navbar = document.getElementById("navbar"); if (!navbar) return; let ticking = false; const onScroll = () => { if (!ticking) { requestAnimationFrame(() => { if (window.scrollY > 10) { navbar.classList.add("navbar-scrolled"); } else { navbar.classList.remove("navbar-scrolled"); } ticking = false; }); ticking = true; } }; window.addEventListener("scroll", onScroll, { passive: true }); } // Mobile menu toggle function initMobileMenu() { const btn = document.getElementById("mobile-menu-btn"); const menu = document.getElementById("mobile-menu"); if (btn && menu) { btn.addEventListener("click", () => { menu.classList.toggle("hidden"); }); // Close on link click const links = menu.querySelectorAll("a"); for (const link of links) { link.addEventListener("click", () => { menu.classList.add("hidden"); }); } } } // Copy buttons function initCopyButtons() { const copyAllBtn = document.getElementById("copy-all-btn"); if (copyAllBtn) { copyAllBtn.addEventListener("click", () => { const commands = `git clone https://github.com/husteno-o/git-discord-bot.git\ncd git-discord-bot\nbun install\ncp .env.example .env\nbun run start`; navigator.clipboard.writeText(commands).then(() => { const original = copyAllBtn.innerHTML; copyAllBtn.innerHTML = ` Copied!`; if (typeof lucide !== "undefined") lucide.createIcons(); setTimeout(() => { copyAllBtn.innerHTML = original; if (typeof lucide !== "undefined") lucide.createIcons(); }, 2000); }); }); } } // Scroll effects function initScrollEffects() { // Intersection observer for reveal animations const reveals = document.querySelectorAll(".reveal"); if (reveals.length > 0) { const observer = new IntersectionObserver( (entries) => { for (const entry of entries) { if (entry.isIntersecting) { entry.target.classList.add("visible"); observer.unobserve(entry.target); } } }, { threshold: 0.1, rootMargin: "0px 0px -40px 0px" }, ); for (const el of reveals) observer.observe(el); } }